2012-02-03 01:52:58 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								%% The contents of this file are subject to the Mozilla Public License
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								%% Version 1.1 (the "License"); you may not use this file except in
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								%% compliance with the License. You may obtain a copy of the License
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								%% at http://www.mozilla.org/MPL/
							 | 
						
					
						
							
								
									
										
										
										
											2010-10-28 05:14:19 +08:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								%%
							 | 
						
					
						
							
								
									
										
										
										
											2012-02-03 01:52:58 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								%% Software distributed under the License is distributed on an "AS IS"
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								%% the License for the specific language governing rights and
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								%% limitations under the License.
							 | 
						
					
						
							
								
									
										
										
										
											2010-10-28 05:14:19 +08:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								%%
							 | 
						
					
						
							
								
									
										
										
										
											2012-02-03 01:52:58 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								%% The Original Code is RabbitMQ.
							 | 
						
					
						
							
								
									
										
										
										
											2010-10-28 05:14:19 +08:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								%%
							 | 
						
					
						
							
								
									
										
										
										
											2012-02-03 01:52:58 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								%% The Initial Developer of the Original Code is VMware, Inc.
							 | 
						
					
						
							
								
									
										
										
										
											2013-01-23 20:25:55 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								%% Copyright (c) 2007-2013 VMware, Inc.  All rights reserved.
							 | 
						
					
						
							
								
									
										
										
										
											2010-10-28 05:14:19 +08:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								%%
							 | 
						
					
						
							
								
									
										
										
										
											2012-02-03 01:52:58 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2010-10-28 05:14:19 +08:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								-module(rabbit_stomp_processor).
							 | 
						
					
						
							
								
									
										
										
										
											2011-01-31 21:00:15 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								-behaviour(gen_server2).
							 | 
						
					
						
							
								
									
										
										
										
											2010-10-28 05:14:19 +08:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2012-02-23 22:43:53 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								-export([start_link/1, process_frame/2, flush_and_die/1]).
							 | 
						
					
						
							
								
									
										
										
										
											2010-10-28 05:14:19 +08:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								-export([init/1, handle_call/3, handle_cast/2, handle_info/2,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								         code_change/3, terminate/2]).
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								-include_lib("amqp_client/include/amqp_client.hrl").
							 | 
						
					
						
							
								
									
										
										
										
											2013-02-16 00:11:17 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								-include_lib("amqp_client/include/routing_prefixes.hrl").
							 | 
						
					
						
							
								
									
										
										
										
											2010-10-28 05:14:19 +08:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								-include("rabbit_stomp_frame.hrl").
							 | 
						
					
						
							
								
									
										
										
										
											2011-06-06 18:03:17 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								-include("rabbit_stomp.hrl").
							 | 
						
					
						
							
								
									
										
										
										
											2011-11-25 20:11:22 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								-include("rabbit_stomp_headers.hrl").
							 | 
						
					
						
							
								
									
										
										
										
											2010-10-28 05:14:19 +08:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2012-02-20 21:09:07 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								-record(state, {session_id, channel, connection, subscriptions,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                version, start_heartbeat_fun, pending_receipts,
							 | 
						
					
						
							
								
									
										
										
										
											2013-02-16 00:11:17 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                config, route_state, reply_queues, frame_transformer,
							 | 
						
					
						
							
								
									
										
										
										
											2012-02-23 22:43:53 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                adapter_info, send_fun, ssl_login_name}).
							 | 
						
					
						
							
								
									
										
										
										
											2010-11-09 19:57:20 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2012-11-07 01:30:31 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								-record(subscription, {dest_hdr, channel, ack_mode, multi_ack, description}).
							 | 
						
					
						
							
								
									
										
										
										
											2010-11-09 22:12:59 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2011-02-01 19:30:50 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								-define(FLUSH_TIMEOUT, 60000).
							 | 
						
					
						
							
								
									
										
										
										
											2010-10-28 05:14:19 +08:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								%%----------------------------------------------------------------------------
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								%% Public API
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								%%----------------------------------------------------------------------------
							 | 
						
					
						
							
								
									
										
										
										
											2012-02-23 22:43:53 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								start_link(Args) ->
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    gen_server2:start_link(?MODULE, Args, []).
							 | 
						
					
						
							
								
									
										
										
										
											2010-10-28 05:14:19 +08:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2012-01-18 22:48:54 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								process_frame(Pid, Frame = #stomp_frame{command = "SEND"}) ->
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    credit_flow:send(Pid),
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    gen_server2:cast(Pid, {"SEND", Frame, self()});
							 | 
						
					
						
							
								
									
										
										
										
											2010-10-28 05:14:19 +08:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								process_frame(Pid, Frame = #stomp_frame{command = Command}) ->
							 | 
						
					
						
							
								
									
										
										
										
											2012-01-18 22:48:54 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    gen_server2:cast(Pid, {Command, Frame, noflow}).
							 | 
						
					
						
							
								
									
										
										
										
											2010-10-28 05:14:19 +08:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2011-08-24 21:50:48 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								flush_and_die(Pid) ->
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    gen_server2:cast(Pid, flush_and_die).
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2010-10-28 05:14:19 +08:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								%%----------------------------------------------------------------------------
							 | 
						
					
						
							
								
									
										
										
										
											2011-01-31 21:00:15 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								%% Basic gen_server2 callbacks
							 | 
						
					
						
							
								
									
										
										
										
											2010-10-28 05:14:19 +08:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								%%----------------------------------------------------------------------------
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2012-02-23 22:43:53 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								init([SendFun, AdapterInfo, StartHeartbeatFun, SSLLoginName, Configuration]) ->
							 | 
						
					
						
							
								
									
										
										
										
											2010-10-28 05:14:19 +08:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    process_flag(trap_exit, true),
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    {ok,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								     #state {
							 | 
						
					
						
							
								
									
										
										
										
											2010-11-11 05:09:20 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								       session_id          = none,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								       channel             = none,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								       connection          = none,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								       subscriptions       = dict:new(),
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								       version             = none,
							 | 
						
					
						
							
								
									
										
										
										
											2011-02-15 23:01:50 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								       start_heartbeat_fun = StartHeartbeatFun,
							 | 
						
					
						
							
								
									
										
										
										
											2011-06-06 18:03:17 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								       pending_receipts    = undefined,
							 | 
						
					
						
							
								
									
										
										
										
											2011-07-19 23:15:59 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								       config              = Configuration,
							 | 
						
					
						
							
								
									
										
										
										
											2013-02-16 00:11:17 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								       route_state          = routing_util:init_state(),
							 | 
						
					
						
							
								
									
										
										
										
											2011-08-25 19:41:26 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								       reply_queues        = dict:new(),
							 | 
						
					
						
							
								
									
										
										
										
											2012-02-18 01:52:15 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								       frame_transformer   = undefined,
							 | 
						
					
						
							
								
									
										
										
										
											2012-02-20 21:09:07 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								       adapter_info        = AdapterInfo,
							 | 
						
					
						
							
								
									
										
										
										
											2012-02-23 22:43:53 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								       send_fun            = SendFun,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								       ssl_login_name      = SSLLoginName},
							 | 
						
					
						
							
								
									
										
										
										
											2011-01-31 21:56:52 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								     hibernate,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								     {backoff, 1000, 1000, 10000}
							 | 
						
					
						
							
								
									
										
										
										
											2010-10-28 05:14:19 +08:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    }.
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								terminate(_Reason, State) ->
							 | 
						
					
						
							
								
									
										
										
										
											2011-08-25 19:35:38 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    close_connection(State).
							 | 
						
					
						
							
								
									
										
										
										
											2010-10-28 05:14:19 +08:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2011-08-24 21:50:48 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								handle_cast(flush_and_die, State) ->
							 | 
						
					
						
							
								
									
										
										
										
											2011-08-25 19:35:38 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    {stop, normal, close_connection(State)};
							 | 
						
					
						
							
								
									
										
										
										
											2010-10-28 05:14:19 +08:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2012-01-18 22:48:54 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								handle_cast({"STOMP", Frame, noflow}, State) ->
							 | 
						
					
						
							
								
									
										
										
										
											2011-07-14 00:35:21 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    process_connect(no_implicit, Frame, State);
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2012-01-18 22:48:54 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								handle_cast({"CONNECT", Frame, noflow}, State) ->
							 | 
						
					
						
							
								
									
										
										
										
											2011-07-14 00:35:21 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    process_connect(no_implicit, Frame, State);
							 | 
						
					
						
							
								
									
										
										
										
											2010-10-28 05:14:19 +08:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2011-06-06 18:23:24 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								handle_cast(Request, State = #state{channel = none,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                                     config = #stomp_configuration{
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                                      implicit_connect = true}}) ->
							 | 
						
					
						
							
								
									
										
										
										
											2012-02-20 23:10:14 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    {noreply, State1 = #state{channel = Ch}, _} =
							 | 
						
					
						
							
								
									
										
										
										
											2011-07-14 00:35:21 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        process_connect(implicit, #stomp_frame{headers = []}, State),
							 | 
						
					
						
							
								
									
										
										
										
											2012-02-20 23:10:14 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    case Ch of
							 | 
						
					
						
							
								
									
										
										
										
											2012-02-21 17:58:31 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        none -> {stop, normal, State1};
							 | 
						
					
						
							
								
									
										
										
										
											2012-02-20 23:10:14 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        _    -> handle_cast(Request, State1)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    end;
							 | 
						
					
						
							
								
									
										
										
										
											2011-08-24 21:50:48 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2011-06-06 18:23:24 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								handle_cast(_Request, State = #state{channel = none,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                                     config = #stomp_configuration{
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                                      implicit_connect = false}}) ->
							 | 
						
					
						
							
								
									
										
										
										
											2011-02-01 19:30:50 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    {noreply,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								     send_error("Illegal command",
							 | 
						
					
						
							
								
									
										
										
										
											2012-08-16 00:03:53 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                "You must log in using CONNECT first",
							 | 
						
					
						
							
								
									
										
										
										
											2011-02-01 19:30:50 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                State),
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								     hibernate};
							 | 
						
					
						
							
								
									
										
										
										
											2010-10-28 05:14:19 +08:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2012-01-18 22:48:54 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								handle_cast({Command, Frame, FlowPid},
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            State = #state{frame_transformer = FT}) ->
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    case FlowPid of
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        noflow -> ok;
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        _      -> credit_flow:ack(FlowPid)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    end,
							 | 
						
					
						
							
								
									
										
										
										
											2011-08-25 19:41:26 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    Frame1 = FT(Frame),
							 | 
						
					
						
							
								
									
										
										
										
											2010-11-26 19:10:43 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    process_request(
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								      fun(StateN) ->
							 | 
						
					
						
							
								
									
										
										
										
											2011-08-25 19:41:26 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								              case validate_frame(Command, Frame1, StateN) of
							 | 
						
					
						
							
								
									
										
										
										
											2011-07-21 01:20:14 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                  R = {error, _, _, _} -> R;
							 | 
						
					
						
							
								
									
										
										
										
											2011-08-25 19:41:26 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                  _                    -> handle_frame(Command, Frame1, StateN)
							 | 
						
					
						
							
								
									
										
										
										
											2011-07-21 01:20:14 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								              end
							 | 
						
					
						
							
								
									
										
										
										
											2010-11-26 19:10:43 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								      end,
							 | 
						
					
						
							
								
									
										
										
										
											2011-09-10 00:02:11 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								      fun(StateM) -> ensure_receipt(Frame1, StateM) end,
							 | 
						
					
						
							
								
									
										
										
										
											2011-01-11 02:43:41 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								      State);
							 | 
						
					
						
							
								
									
										
										
										
											2010-11-10 03:10:56 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2010-11-11 05:09:20 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								handle_cast(client_timeout, State) ->
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    {stop, client_timeout, State}.
							 | 
						
					
						
							
								
									
										
										
										
											2010-10-28 05:14:19 +08:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								handle_info(#'basic.consume_ok'{}, State) ->
							 | 
						
					
						
							
								
									
										
										
										
											2011-01-31 21:56:52 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    {noreply, State, hibernate};
							 | 
						
					
						
							
								
									
										
										
										
											2011-01-15 01:09:50 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								handle_info(#'basic.cancel_ok'{}, State) ->
							 | 
						
					
						
							
								
									
										
										
										
											2011-01-31 21:56:52 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    {noreply, State, hibernate};
							 | 
						
					
						
							
								
									
										
										
										
											2011-02-16 17:56:39 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								handle_info(#'basic.ack'{delivery_tag = Tag, multiple = IsMulti}, State) ->
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    {noreply, flush_pending_receipts(Tag, IsMulti, State), hibernate};
							 | 
						
					
						
							
								
									
										
										
										
											2010-10-28 05:14:19 +08:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								handle_info({Delivery = #'basic.deliver'{},
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								             #amqp_msg{props = Props, payload = Payload}}, State) ->
							 | 
						
					
						
							
								
									
										
										
										
											2011-01-31 21:56:52 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    {noreply, send_delivery(Delivery, Props, Payload, State), hibernate};
							 | 
						
					
						
							
								
									
										
										
										
											2012-07-11 18:44:12 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								handle_info(#'basic.cancel'{consumer_tag = Ctag}, State) ->
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    {noreply, server_cancel_consumer(Ctag, State), hibernate};
							 | 
						
					
						
							
								
									
										
										
										
											2012-01-28 00:42:39 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								handle_info({'EXIT', Conn,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								             {shutdown, {server_initiated_close, Code, Explanation}}},
							 | 
						
					
						
							
								
									
										
										
										
											2012-01-28 00:00:08 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								            State = #state{connection = Conn}) ->
							 | 
						
					
						
							
								
									
										
										
										
											2012-01-20 22:35:48 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    amqp_death(Code, Explanation, State);
							 | 
						
					
						
							
								
									
										
										
										
											2012-01-28 00:00:08 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								handle_info({'EXIT', Conn, Reason}, State = #state{connection = Conn}) ->
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    send_error("AMQP connection died", "Reason: ~p", [Reason], State),
							 | 
						
					
						
							
								
									
										
										
										
											2012-01-20 22:35:48 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    {stop, {conn_died, Reason}, State};
							 | 
						
					
						
							
								
									
										
										
										
											2011-01-27 01:46:27 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								handle_info({inet_reply, _, ok}, State) ->
							 | 
						
					
						
							
								
									
										
										
										
											2011-01-31 21:56:52 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    {noreply, State, hibernate};
							 | 
						
					
						
							
								
									
										
										
										
											2012-01-18 22:48:54 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								handle_info({bump_credit, Msg}, State) ->
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    credit_flow:handle_bump_msg(Msg),
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    {noreply, State, hibernate};
							 | 
						
					
						
							
								
									
										
										
										
											2011-01-27 01:46:27 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								handle_info({inet_reply, _, Status}, State) ->
							 | 
						
					
						
							
								
									
										
										
										
											2011-01-31 21:01:34 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    {stop, Status, State}.
							 | 
						
					
						
							
								
									
										
										
										
											2010-10-28 05:14:19 +08:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2010-11-26 19:10:43 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								process_request(ProcessFun, SuccessFun, State) ->
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    Res = case catch ProcessFun(State) of
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								              {'EXIT',
							 | 
						
					
						
							
								
									
										
										
										
											2011-04-14 17:42:04 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								               {{shutdown,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                 {server_initiated_close, ReplyCode, Explanation}}, _}} ->
							 | 
						
					
						
							
								
									
										
										
										
											2011-01-17 18:38:43 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                  amqp_death(ReplyCode, Explanation, State);
							 | 
						
					
						
							
								
									
										
										
										
											2010-11-26 19:10:43 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								              {'EXIT', Reason} ->
							 | 
						
					
						
							
								
									
										
										
										
											2012-08-16 00:03:53 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                  priv_error("Processing error", "Processing error",
							 | 
						
					
						
							
								
									
										
										
										
											2010-11-26 19:10:43 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                              Reason, State);
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								              Result ->
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                  Result
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								          end,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    case Res of
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        {ok, Frame, NewState} ->
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            case Frame of
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                none -> ok;
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                _    -> send_frame(Frame, NewState)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            end,
							 | 
						
					
						
							
								
									
										
										
										
											2011-01-31 21:56:52 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								            {noreply, SuccessFun(NewState), hibernate};
							 | 
						
					
						
							
								
									
										
										
										
											2010-11-26 19:10:43 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        {error, Message, Detail, NewState} ->
							 | 
						
					
						
							
								
									
										
										
										
											2011-01-31 21:56:52 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								            {noreply, send_error(Message, Detail, NewState), hibernate};
							 | 
						
					
						
							
								
									
										
										
										
											2011-02-16 23:06:46 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        {stop, normal, NewState} ->
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            {stop, normal, SuccessFun(NewState)};
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        {stop, R, NewState} ->
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            {stop, R, NewState}
							 | 
						
					
						
							
								
									
										
										
										
											2010-11-26 19:10:43 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    end.
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2012-02-23 22:43:53 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								process_connect(Implicit, Frame,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                State = #state{channel        = none,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                               config         = Config,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                               ssl_login_name = SSLLoginName,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                               adapter_info   = AdapterInfo}) ->
							 | 
						
					
						
							
								
									
										
										
										
											2011-07-14 00:35:21 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    process_request(
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								      fun(StateN) ->
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								              case negotiate_version(Frame) of
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                  {ok, Version} ->
							 | 
						
					
						
							
								
									
										
										
										
											2011-08-25 19:41:26 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                      FT = frame_transformer(Version),
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                      Frame1 = FT(Frame),
							 | 
						
					
						
							
								
									
										
										
										
											2012-09-19 21:37:05 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                      {Username, Passwd} = creds(Frame1, SSLLoginName, Config),
							 | 
						
					
						
							
								
									
										
										
										
											2011-07-14 00:35:21 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                      {ok, DefaultVHost} =
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                          application:get_env(rabbit, default_vhost),
							 | 
						
					
						
							
								
									
										
										
										
											2012-07-03 02:12:42 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                      {ProtoName, _} = AdapterInfo#amqp_adapter_info.protocol,
							 | 
						
					
						
							
								
									
										
										
										
											2011-07-14 00:35:21 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                      Res = do_login(
							 | 
						
					
						
							
								
									
										
										
										
											2012-09-19 21:37:05 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                              Username, Passwd,
							 | 
						
					
						
							
								
									
										
										
										
											2012-02-21 00:07:18 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                              login_header(Frame1, ?HEADER_HOST, DefaultVHost),
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                              login_header(Frame1, ?HEADER_HEART_BEAT, "0,0"),
							 | 
						
					
						
							
								
									
										
										
										
											2012-07-03 02:12:42 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                              AdapterInfo#amqp_adapter_info{
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                                protocol = {ProtoName, Version}}, Version,
							 | 
						
					
						
							
								
									
										
										
										
											2012-02-21 00:07:18 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                              StateN#state{frame_transformer = FT}),
							 | 
						
					
						
							
								
									
										
										
										
											2011-07-14 00:35:21 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                      case {Res, Implicit} of
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                          {{ok, _, StateN1}, implicit} -> ok(StateN1);
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                          _                            -> Res
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                      end;
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                  {error, no_common_version} ->
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                      error("Version mismatch",
							 | 
						
					
						
							
								
									
										
										
										
											2012-08-16 00:03:53 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                            "Supported versions are ~s~n",
							 | 
						
					
						
							
								
									
										
										
										
											2011-07-14 00:35:21 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                            [string:join(?SUPPORTED_VERSIONS, ",")],
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                            StateN)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								              end
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								      end,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								      fun(StateM) -> StateM end,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								      State).
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2012-02-23 22:43:53 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								creds(Frame, SSLLoginName,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								      #stomp_configuration{default_login    = DefLogin,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                           default_passcode = DefPasscode}) ->
							 | 
						
					
						
							
								
									
										
										
										
											2012-09-19 21:37:05 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    PasswordCreds = {login_header(Frame, ?HEADER_LOGIN,    DefLogin),
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                     login_header(Frame, ?HEADER_PASSCODE, DefPasscode)},
							 | 
						
					
						
							
								
									
										
										
										
											2012-02-23 22:43:53 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    case {rabbit_stomp_frame:header(Frame, ?HEADER_LOGIN), SSLLoginName} of
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        {not_found, none}    -> PasswordCreds;
							 | 
						
					
						
							
								
									
										
										
										
											2012-09-19 21:37:05 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        {not_found, SSLName} -> {SSLName, none};
							 | 
						
					
						
							
								
									
										
										
										
											2012-02-23 22:43:53 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        _                    -> PasswordCreds
							 | 
						
					
						
							
								
									
										
										
										
											2012-02-21 00:07:18 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    end.
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								login_header(Frame, Key, Default) when is_binary(Default) ->
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    login_header(Frame, Key, binary_to_list(Default));
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								login_header(Frame, Key, Default) ->
							 | 
						
					
						
							
								
									
										
										
										
											2012-03-15 19:37:02 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    case rabbit_stomp_frame:header(Frame, Key, Default) of
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        undefined -> undefined;
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        Hdr       -> list_to_binary(Hdr)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    end.
							 | 
						
					
						
							
								
									
										
										
										
											2012-02-21 00:07:18 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2011-07-21 01:20:14 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								%%----------------------------------------------------------------------------
							 | 
						
					
						
							
								
									
										
										
										
											2011-08-25 19:41:26 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								%% Frame Transformation
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								%%----------------------------------------------------------------------------
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								frame_transformer("1.0") -> fun rabbit_stomp_util:trim_headers/1;
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								frame_transformer(_) -> fun(Frame) -> Frame end.
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								%%----------------------------------------------------------------------------
							 | 
						
					
						
							
								
									
										
										
										
											2011-07-21 01:20:14 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								%% Frame Validation
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								%%----------------------------------------------------------------------------
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								validate_frame(Command, Frame, State)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								  when Command =:= "SUBSCRIBE" orelse Command =:= "UNSUBSCRIBE" ->
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    Hdr = fun(Name) -> rabbit_stomp_frame:header(Frame, Name) end,
							 | 
						
					
						
							
								
									
										
										
										
											2011-11-25 20:11:22 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    case {Hdr(?HEADER_PERSISTENT), Hdr(?HEADER_ID)} of
							 | 
						
					
						
							
								
									
										
										
										
											2011-07-21 01:20:14 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        {{ok, "true"}, not_found} ->
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            error("Missing Header",
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                  "Header 'id' is required for durable subscriptions", State);
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        _ ->
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            ok(State)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    end;
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								validate_frame(_Command, _Frame, State) ->
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    ok(State).
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2010-10-28 05:14:19 +08:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								%%----------------------------------------------------------------------------
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								%% Frame handlers
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								%%----------------------------------------------------------------------------
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								handle_frame("DISCONNECT", _Frame, State) ->
							 | 
						
					
						
							
								
									
										
										
										
											2011-08-25 19:35:38 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    {stop, normal, close_connection(State)};
							 | 
						
					
						
							
								
									
										
										
										
											2010-10-28 05:14:19 +08:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								handle_frame("SUBSCRIBE", Frame, State) ->
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    with_destination("SUBSCRIBE", Frame, State, fun do_subscribe/4);
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2011-01-06 23:54:05 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								handle_frame("UNSUBSCRIBE", Frame, State) ->
							 | 
						
					
						
							
								
									
										
										
										
											2011-01-18 20:35:53 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    ConsumerTag = rabbit_stomp_util:consumer_tag(Frame),
							 | 
						
					
						
							
								
									
										
										
										
											2011-07-21 01:20:14 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    cancel_subscription(ConsumerTag, Frame, State);
							 | 
						
					
						
							
								
									
										
										
										
											2010-10-28 05:14:19 +08:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								handle_frame("SEND", Frame, State) ->
							 | 
						
					
						
							
								
									
										
										
										
											2011-11-25 20:49:56 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    without_headers(?HEADERS_NOT_ON_SEND, "SEND", Frame, State,
							 | 
						
					
						
							
								
									
										
										
										
											2012-01-20 22:34:56 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        fun (_Command, Frame1, State1) ->
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            with_destination("SEND", Frame1, State1, fun do_send/4)
							 | 
						
					
						
							
								
									
										
										
										
											2011-11-25 20:49:56 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        end);
							 | 
						
					
						
							
								
									
										
										
										
											2010-10-28 05:14:19 +08:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2011-01-11 19:25:44 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								handle_frame("ACK", Frame, State) ->
							 | 
						
					
						
							
								
									
										
										
										
											2011-01-11 21:57:59 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    ack_action("ACK", Frame, State, fun create_ack_method/2);
							 | 
						
					
						
							
								
									
										
										
										
											2011-01-11 19:25:44 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								handle_frame("NACK", Frame, State) ->
							 | 
						
					
						
							
								
									
										
										
										
											2011-01-11 21:57:59 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    ack_action("NACK", Frame, State, fun create_nack_method/2);
							 | 
						
					
						
							
								
									
										
										
										
											2010-10-28 05:14:19 +08:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								handle_frame("BEGIN", Frame, State) ->
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    transactional_action(Frame, "BEGIN", fun begin_transaction/2, State);
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								handle_frame("COMMIT", Frame, State) ->
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    transactional_action(Frame, "COMMIT", fun commit_transaction/2, State);
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								handle_frame("ABORT", Frame, State) ->
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    transactional_action(Frame, "ABORT", fun abort_transaction/2, State);
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								handle_frame(Command, _Frame, State) ->
							 | 
						
					
						
							
								
									
										
										
										
											2010-11-26 19:10:43 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    error("Bad command",
							 | 
						
					
						
							
								
									
										
										
										
											2012-08-16 00:03:53 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								          "Could not interpret command ~p~n",
							 | 
						
					
						
							
								
									
										
										
										
											2011-08-24 21:50:48 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								          [Command],
							 | 
						
					
						
							
								
									
										
										
										
											2010-11-26 19:10:43 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								          State).
							 | 
						
					
						
							
								
									
										
										
										
											2010-10-28 05:14:19 +08:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								%%----------------------------------------------------------------------------
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								%% Internal helpers for processing frames callbacks
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								%%----------------------------------------------------------------------------
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2011-01-11 21:57:59 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								ack_action(Command, Frame,
							 | 
						
					
						
							
								
									
										
										
										
											2012-11-07 01:30:31 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								           State = #state{subscriptions = Subs,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                          version       = Version}, MethodFun) ->
							 | 
						
					
						
							
								
									
										
										
										
											2012-11-07 23:33:05 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    AckHeader = rabbit_stomp_util:ack_header_name(Version),
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    case rabbit_stomp_frame:header(Frame, AckHeader) of
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        {ok, AckValue} ->
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            case rabbit_stomp_util:parse_message_id(AckValue) of
							 | 
						
					
						
							
								
									
										
										
										
											2011-01-11 21:57:59 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                {ok, {ConsumerTag, _SessionId, DeliveryTag}} ->
							 | 
						
					
						
							
								
									
										
										
										
											2012-11-08 22:37:25 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                    case dict:find(ConsumerTag, Subs) of
							 | 
						
					
						
							
								
									
										
										
										
											2012-11-09 01:16:34 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                        {ok, Sub = #subscription{channel = SubChannel}} ->
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                            Method = MethodFun(DeliveryTag, Sub),
							 | 
						
					
						
							
								
									
										
										
										
											2012-11-08 22:37:25 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                            case transactional(Frame) of
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                                {yes, Transaction} ->
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                                    extend_transaction(Transaction,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                                                       {SubChannel, Method},
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                                                       State);
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                                no ->
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                                    amqp_channel:call(SubChannel, Method),
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                                    ok(State)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                            end;
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                        error ->
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                            error("Subscription not found",
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                                  "Message with id ~p has no subscription",
							 | 
						
					
						
							
								
									
										
										
										
											2012-11-14 20:00:27 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                                  [AckValue],
							 | 
						
					
						
							
								
									
										
										
										
											2012-11-08 22:37:25 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                                  State)
							 | 
						
					
						
							
								
									
										
										
										
											2010-10-28 05:14:19 +08:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                    end;
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                _ ->
							 | 
						
					
						
							
								
									
										
										
										
											2012-11-07 23:33:05 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                   error("Invalid header",
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                         "~p must include a valid ~p header~n",
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                         [Command, AckHeader],
							 | 
						
					
						
							
								
									
										
										
										
											2010-11-26 19:10:43 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                         State)
							 | 
						
					
						
							
								
									
										
										
										
											2010-10-28 05:14:19 +08:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            end;
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        not_found ->
							 | 
						
					
						
							
								
									
										
										
										
											2012-11-07 23:33:05 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								            error("Missing header",
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                  "~p must include the ~p header~n",
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                  [Command, AckHeader],
							 | 
						
					
						
							
								
									
										
										
										
											2010-11-26 19:10:43 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                  State)
							 | 
						
					
						
							
								
									
										
										
										
											2011-01-11 19:25:44 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    end.
							 | 
						
					
						
							
								
									
										
										
										
											2010-10-28 05:14:19 +08:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								%%----------------------------------------------------------------------------
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								%% Internal helpers for processing frames callbacks
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								%%----------------------------------------------------------------------------
							 | 
						
					
						
							
								
									
										
										
										
											2012-07-11 18:44:12 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								server_cancel_consumer(ConsumerTag, State = #state{subscriptions = Subs}) ->
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    case dict:find(ConsumerTag, Subs) of
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        error ->
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            error("Server cancelled unknown subscription",
							 | 
						
					
						
							
								
									
										
										
										
											2012-08-16 00:03:53 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                  "Consumer tag ~p is not associated with a subscription.~n",
							 | 
						
					
						
							
								
									
										
										
										
											2012-07-11 18:44:12 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                  [ConsumerTag],
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                  State);
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        {ok, Subscription = #subscription{description = Description}} ->
							 | 
						
					
						
							
								
									
										
										
										
											2012-08-01 17:46:24 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								            Id = case rabbit_stomp_util:tag_to_id(ConsumerTag) of
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                     {ok,    {_, Id1}} -> Id1;
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                     {error, {_, Id1}} -> "Unknown[" ++ Id1 ++ "]"
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                 end,
							 | 
						
					
						
							
								
									
										
										
										
											2012-07-11 18:44:12 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								            send_error_frame("Server cancelled subscription",
							 | 
						
					
						
							
								
									
										
										
										
											2012-08-01 17:46:24 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                             [{?HEADER_SUBSCRIPTION, Id}],
							 | 
						
					
						
							
								
									
										
										
										
											2012-08-16 00:03:53 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                             "The server has canceled a subscription.~n"
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                             "No more messages will be delivered for ~p.~n",
							 | 
						
					
						
							
								
									
										
										
										
											2012-07-11 18:44:12 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                             [Description],
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                             State),
							 | 
						
					
						
							
								
									
										
										
										
											2012-08-01 17:46:24 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								            tidy_canceled_subscription(ConsumerTag, Subscription,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                                       #stomp_frame{}, State)
							 | 
						
					
						
							
								
									
										
										
										
											2012-07-11 18:44:12 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    end.
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2012-02-21 02:09:45 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								cancel_subscription({error, invalid_prefix}, _Frame, State) ->
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    error("Invalid id",
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								          "UNSUBSCRIBE 'id' may not start with ~s~n",
							 | 
						
					
						
							
								
									
										
										
										
											2012-02-21 21:06:35 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								          [?TEMP_QUEUE_ID_PREFIX],
							 | 
						
					
						
							
								
									
										
										
										
											2012-02-21 02:09:45 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								          State);
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2011-07-21 01:20:14 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								cancel_subscription({error, _}, _Frame, State) ->
							 | 
						
					
						
							
								
									
										
										
										
											2011-01-06 23:54:05 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    error("Missing destination or id",
							 | 
						
					
						
							
								
									
										
										
										
											2012-08-16 00:03:53 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								          "UNSUBSCRIBE must include a 'destination' or 'id' header",
							 | 
						
					
						
							
								
									
										
										
										
											2011-01-06 23:54:05 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								          State);
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2011-07-21 01:20:14 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								cancel_subscription({ok, ConsumerTag, Description}, Frame,
							 | 
						
					
						
							
								
									
										
										
										
											2012-07-11 18:44:12 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                    State = #state{subscriptions = Subs}) ->
							 | 
						
					
						
							
								
									
										
										
										
											2011-01-06 23:54:05 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    case dict:find(ConsumerTag, Subs) of
							 | 
						
					
						
							
								
									
										
										
										
											2011-01-18 18:23:36 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        error ->
							 | 
						
					
						
							
								
									
										
										
										
											2011-01-06 23:54:05 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								            error("No subscription found",
							 | 
						
					
						
							
								
									
										
										
										
											2012-08-16 00:03:53 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                  "UNSUBSCRIBE must refer to an existing subscription.~n"
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                  "Subscription to ~p not found.~n",
							 | 
						
					
						
							
								
									
										
										
										
											2011-01-19 00:24:42 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                  [Description],
							 | 
						
					
						
							
								
									
										
										
										
											2011-01-06 23:54:05 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                  State);
							 | 
						
					
						
							
								
									
										
										
										
											2012-08-01 17:46:24 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        {ok, Subscription = #subscription{channel = SubChannel,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                                          description = Descr}} ->
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            case amqp_channel:call(SubChannel,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                                   #'basic.cancel'{
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                                     consumer_tag = ConsumerTag}) of
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                #'basic.cancel_ok'{consumer_tag = ConsumerTag} ->
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                    tidy_canceled_subscription(ConsumerTag, Subscription,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                                               Frame, State);
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                _ ->
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                    error("Failed to cancel subscription",
							 | 
						
					
						
							
								
									
										
										
										
											2012-08-16 00:03:53 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                          "UNSUBSCRIBE to ~p failed.~n",
							 | 
						
					
						
							
								
									
										
										
										
											2012-08-01 17:46:24 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                          [Descr],
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                          State)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            end
							 | 
						
					
						
							
								
									
										
										
										
											2011-01-06 23:54:05 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    end.
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2012-08-01 17:46:24 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								tidy_canceled_subscription(ConsumerTag, #subscription{dest_hdr = DestHdr,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                                                      channel = SubChannel},
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                           Frame, State = #state{channel = MainChannel,
							 | 
						
					
						
							
								
									
										
										
										
											2012-08-07 18:02:27 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                                                 subscriptions = Subs}) ->
							 | 
						
					
						
							
								
									
										
										
										
											2012-08-01 17:46:24 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    ok = ensure_subchannel_closed(SubChannel, MainChannel),
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    Subs1 = dict:erase(ConsumerTag, Subs),
							 | 
						
					
						
							
								
									
										
										
										
											2013-02-16 00:11:17 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    {ok, Dest} = routing_util:parse_endpoint(DestHdr),
							 | 
						
					
						
							
								
									
										
										
										
											2012-08-01 17:46:24 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    maybe_delete_durable_sub(Dest, Frame, State#state{subscriptions = Subs1}).
							 | 
						
					
						
							
								
									
										
										
										
											2011-07-21 01:20:14 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2012-07-11 18:44:12 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								maybe_delete_durable_sub({topic, Name}, Frame,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                         State = #state{channel = Channel}) ->
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    case rabbit_stomp_frame:boolean_header(Frame,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                                           ?HEADER_PERSISTENT, false) of
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        true ->
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            {ok, Id} = rabbit_stomp_frame:header(Frame, ?HEADER_ID),
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            QName = rabbit_stomp_util:durable_subscription_queue(Name, Id),
							 | 
						
					
						
							
								
									
										
										
										
											2013-02-16 00:11:17 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								            amqp_channel:call(Channel, #'queue.delete'{queue  = list_to_binary(QName),
							 | 
						
					
						
							
								
									
										
										
										
											2012-07-11 18:44:12 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                                                       nowait = false}),
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            ok(State);
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        false ->
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            ok(State)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    end;
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								maybe_delete_durable_sub(_Destination, _Frame, State) ->
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    ok(State).
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2011-07-21 01:20:14 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								ensure_subchannel_closed(SubChannel, MainChannel)
							 | 
						
					
						
							
								
									
										
										
										
											2011-01-20 17:37:57 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								  when SubChannel == MainChannel ->
							 | 
						
					
						
							
								
									
										
										
										
											2011-07-21 01:20:14 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    ok;
							 | 
						
					
						
							
								
									
										
										
										
											2011-01-10 21:35:43 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2011-07-21 01:20:14 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								ensure_subchannel_closed(SubChannel, _MainChannel) ->
							 | 
						
					
						
							
								
									
										
										
										
											2011-01-10 21:35:43 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    amqp_channel:close(SubChannel),
							 | 
						
					
						
							
								
									
										
										
										
											2011-07-21 01:20:14 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    ok.
							 | 
						
					
						
							
								
									
										
										
										
											2011-01-10 21:35:43 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2010-10-28 05:14:19 +08:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								with_destination(Command, Frame, State, Fun) ->
							 | 
						
					
						
							
								
									
										
										
										
											2011-11-25 20:11:22 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    case rabbit_stomp_frame:header(Frame, ?HEADER_DESTINATION) of
							 | 
						
					
						
							
								
									
										
										
										
											2010-10-28 05:14:19 +08:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        {ok, DestHdr} ->
							 | 
						
					
						
							
								
									
										
										
										
											2013-02-16 00:11:17 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								            case routing_util:parse_endpoint(DestHdr) of
							 | 
						
					
						
							
								
									
										
										
										
											2010-10-28 05:14:19 +08:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                {ok, Destination} ->
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                    Fun(Destination, DestHdr, Frame, State);
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                {error, {invalid_destination, Type, Content}} ->
							 | 
						
					
						
							
								
									
										
										
										
											2010-11-26 19:10:43 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                    error("Invalid destination",
							 | 
						
					
						
							
								
									
										
										
										
											2012-08-16 00:03:53 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                          "'~s' is not a valid ~p destination~n",
							 | 
						
					
						
							
								
									
										
										
										
											2010-11-26 19:10:43 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                          [Content, Type],
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                          State);
							 | 
						
					
						
							
								
									
										
										
										
											2010-10-28 05:14:19 +08:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                {error, {unknown_destination, Content}} ->
							 | 
						
					
						
							
								
									
										
										
										
											2010-11-26 19:10:43 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                    error("Unknown destination",
							 | 
						
					
						
							
								
									
										
										
										
											2012-08-16 00:03:53 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                          "'~s' is not a valid destination.~n"
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                          "Valid destination types are: ~s.~n",
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                          [Content,
							 | 
						
					
						
							
								
									
										
										
										
											2013-02-16 00:11:17 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                           string:join(routing_util:all_dest_prefixes(),
							 | 
						
					
						
							
								
									
										
										
										
											2012-08-16 00:03:53 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                                       ", ")], State)
							 | 
						
					
						
							
								
									
										
										
										
											2010-10-28 05:14:19 +08:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            end;
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        not_found ->
							 | 
						
					
						
							
								
									
										
										
										
											2010-11-26 19:10:43 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								            error("Missing destination",
							 | 
						
					
						
							
								
									
										
										
										
											2012-08-16 00:03:53 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                  "~p must include a 'destination' header~n",
							 | 
						
					
						
							
								
									
										
										
										
											2010-11-26 19:10:43 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                  [Command],
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                  State)
							 | 
						
					
						
							
								
									
										
										
										
											2010-10-28 05:14:19 +08:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    end.
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2011-11-25 20:49:56 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								without_headers([Hdr | Hdrs], Command, Frame, State, Fun) ->
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    case rabbit_stomp_frame:header(Frame, Hdr) of
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        {ok, _} ->
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            error("Invalid header",
							 | 
						
					
						
							
								
									
										
										
										
											2012-08-16 00:03:53 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                  "'~s' is not allowed on '~s'.~n",
							 | 
						
					
						
							
								
									
										
										
										
											2011-11-25 20:49:56 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                  [Hdr, Command],
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                  State);
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        not_found ->
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            without_headers(Hdrs, Command, Frame, State, Fun)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    end;
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								without_headers([], Command, Frame, State, Fun) ->
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    Fun(Command, Frame, State).
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2011-06-06 18:03:17 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								do_login(undefined, _, _, _, _, _, State) ->
							 | 
						
					
						
							
								
									
										
										
										
											2012-08-16 00:03:53 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    error("Bad CONNECT", "Missing login or passcode header(s)", State);
							 | 
						
					
						
							
								
									
										
										
										
											2012-09-19 21:37:05 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								do_login(Username, Passwd, VirtualHost, Heartbeat, AdapterInfo, Version,
							 | 
						
					
						
							
								
									
										
										
										
											2012-02-21 00:07:18 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								         State) ->
							 | 
						
					
						
							
								
									
										
										
										
											2012-09-19 21:37:05 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    case amqp_connection:start(
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								           #amqp_params_direct{username     = Username,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                               password     = Passwd,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                               virtual_host = VirtualHost,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                               adapter_info = AdapterInfo}) of
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        {ok, Connection} ->
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            link(Connection),
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            {ok, Channel} = amqp_connection:open_channel(Connection),
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            SessionId = rabbit_guid:string(rabbit_guid:gen_secure(), "session"),
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            {{SendTimeout, ReceiveTimeout}, State1} =
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                ensure_heartbeats(Heartbeat, State),
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            ok("CONNECTED",
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								               [{?HEADER_SESSION, SessionId},
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                {?HEADER_HEART_BEAT,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                 io_lib:format("~B,~B", [SendTimeout, ReceiveTimeout])},
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                {?HEADER_SERVER, server_header()},
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                {?HEADER_VERSION, Version}],
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								               "",
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								               State1#state{session_id = SessionId,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                            channel    = Channel,
							 | 
						
					
						
							
								
									
										
										
										
											2012-11-07 01:30:31 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                            connection = Connection,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                            version    = Version});
							 | 
						
					
						
							
								
									
										
										
										
											2012-09-19 21:37:05 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        {error, auth_failure} ->
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            rabbit_log:warning("STOMP login failed for user ~p~n",
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                               [binary_to_list(Username)]),
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            error("Bad CONNECT", "Access refused for user '" ++
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                  binary_to_list(Username) ++ "'~n", [], State);
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        {error, access_refused} ->
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            rabbit_log:warning("STOMP login failed - access_refused "
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                               "(vhost access not allowed)~n"),
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            error("Bad CONNECT", "Virtual host '" ++
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                                 binary_to_list(VirtualHost) ++
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                                 "' access denied", State)
							 | 
						
					
						
							
								
									
										
										
										
											2011-06-06 18:03:17 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    end.
							 | 
						
					
						
							
								
									
										
										
										
											2010-10-28 05:14:19 +08:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2012-02-24 18:31:58 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								server_header() ->
							 | 
						
					
						
							
								
									
										
										
										
											2012-07-03 01:57:32 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    {ok, Product} = application:get_key(rabbit, id),
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    {ok, Version} = application:get_key(rabbit, vsn),
							 | 
						
					
						
							
								
									
										
										
										
											2012-02-24 18:31:58 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    rabbit_misc:format("~s/~s", [Product, Version]).
							 | 
						
					
						
							
								
									
										
										
										
											2011-06-03 23:32:03 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2010-10-28 05:14:19 +08:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								do_subscribe(Destination, DestHdr, Frame,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								             State = #state{subscriptions = Subs,
							 | 
						
					
						
							
								
									
										
										
										
											2013-02-16 00:11:17 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                            route_state   = RouteState,
							 | 
						
					
						
							
								
									
										
										
										
											2010-10-28 05:14:19 +08:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                            connection    = Connection,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                            channel       = MainChannel}) ->
							 | 
						
					
						
							
								
									
										
										
										
											2011-08-22 21:05:09 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    Prefetch =
							 | 
						
					
						
							
								
									
										
										
										
											2012-07-11 18:44:12 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        rabbit_stomp_frame:integer_header(Frame, ?HEADER_PREFETCH_COUNT,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                                          undefined),
							 | 
						
					
						
							
								
									
										
										
										
											2010-11-09 22:12:59 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    Channel = case Prefetch of
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                  undefined ->
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                      MainChannel;
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                  _ ->
							 | 
						
					
						
							
								
									
										
										
										
											2010-10-28 05:14:19 +08:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                      {ok, Channel1} = amqp_connection:open_channel(Connection),
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                      amqp_channel:call(Channel1,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                                        #'basic.qos'{prefetch_size  = 0,
							 | 
						
					
						
							
								
									
										
										
										
											2010-11-09 22:12:59 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                                                     prefetch_count = Prefetch,
							 | 
						
					
						
							
								
									
										
										
										
											2010-10-28 05:14:19 +08:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                                                     global         = false}),
							 | 
						
					
						
							
								
									
										
										
										
											2010-11-09 22:12:59 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                      Channel1
							 | 
						
					
						
							
								
									
										
										
										
											2010-10-28 05:14:19 +08:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								              end,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2010-11-09 22:12:59 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    {AckMode, IsMulti} = rabbit_stomp_util:ack_mode(Frame),
							 | 
						
					
						
							
								
									
										
										
										
											2010-10-28 05:14:19 +08:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2013-02-16 00:11:17 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    {ok, Queue, RouteState1} =
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								      ensure_endpoint(source, Destination, Frame, Channel, RouteState),
							 | 
						
					
						
							
								
									
										
										
										
											2010-10-28 05:14:19 +08:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2011-01-19 00:24:42 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    {ok, ConsumerTag, Description} = rabbit_stomp_util:consumer_tag(Frame),
							 | 
						
					
						
							
								
									
										
										
										
											2010-10-28 05:14:19 +08:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    amqp_channel:subscribe(Channel,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                           #'basic.consume'{
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                             queue        = Queue,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                             consumer_tag = ConsumerTag,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                             no_local     = false,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                             no_ack       = (AckMode == auto),
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                             exclusive    = false},
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                           self()),
							 | 
						
					
						
							
								
									
										
										
										
											2013-02-16 00:11:17 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    ExchangeAndKey = routing_util:parse_routing(Destination),
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    ok = routing_util:ensure_binding(Queue, ExchangeAndKey, Channel),
							 | 
						
					
						
							
								
									
										
										
										
											2010-10-28 05:14:19 +08:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2010-11-26 19:10:43 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    ok(State#state{subscriptions =
							 | 
						
					
						
							
								
									
										
										
										
											2011-01-11 02:43:41 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                       dict:store(ConsumerTag,
							 | 
						
					
						
							
								
									
										
										
										
											2011-01-19 00:24:42 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                                  #subscription{dest_hdr    = DestHdr,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                                                channel     = Channel,
							 | 
						
					
						
							
								
									
										
										
										
											2012-11-07 01:30:31 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                                                ack_mode    = AckMode,
							 | 
						
					
						
							
								
									
										
										
										
											2011-01-19 00:24:42 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                                                multi_ack   = IsMulti,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                                                description = Description},
							 | 
						
					
						
							
								
									
										
										
										
											2012-01-19 03:38:44 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                                  Subs),
							 | 
						
					
						
							
								
									
										
										
										
											2013-02-16 00:11:17 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                   route_state = RouteState1}).
							 | 
						
					
						
							
								
									
										
										
										
											2010-10-28 05:14:19 +08:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								do_send(Destination, _DestHdr,
							 | 
						
					
						
							
								
									
										
										
										
											2010-10-28 19:57:58 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        Frame = #stomp_frame{body_iolist = BodyFragments},
							 | 
						
					
						
							
								
									
										
										
										
											2013-02-16 00:11:17 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        State = #state{channel = Channel, route_state = RouteState}) ->
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    {ok, _Q, RouteState1} = ensure_endpoint(dest, Destination, Frame, Channel, RouteState),
							 | 
						
					
						
							
								
									
										
										
										
											2010-10-28 05:14:19 +08:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2012-01-19 03:38:44 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    {Frame1, State1} =
							 | 
						
					
						
							
								
									
										
										
										
											2013-02-16 00:11:17 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        ensure_reply_to(Frame, State#state{route_state = RouteState1}),
							 | 
						
					
						
							
								
									
										
										
										
											2010-10-28 05:14:19 +08:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2011-07-19 23:15:59 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    Props = rabbit_stomp_util:message_properties(Frame1),
							 | 
						
					
						
							
								
									
										
										
										
											2010-10-28 05:14:19 +08:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    {Exchange, RoutingKey} =
							 | 
						
					
						
							
								
									
										
										
										
											2013-02-16 00:11:17 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        routing_util:parse_routing(Destination),
							 | 
						
					
						
							
								
									
										
										
										
											2010-10-28 05:14:19 +08:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    Method = #'basic.publish'{
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								      exchange = list_to_binary(Exchange),
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								      routing_key = list_to_binary(RoutingKey),
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								      mandatory = false,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								      immediate = false},
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2011-07-19 23:15:59 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    case transactional(Frame1) of
							 | 
						
					
						
							
								
									
										
										
										
											2010-10-28 05:14:19 +08:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        {yes, Transaction} ->
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            extend_transaction(Transaction,
							 | 
						
					
						
							
								
									
										
										
										
											2011-02-16 19:54:13 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                               fun(StateN) ->
							 | 
						
					
						
							
								
									
										
										
										
											2011-07-19 23:15:59 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                                       maybe_record_receipt(Frame1, StateN)
							 | 
						
					
						
							
								
									
										
										
										
											2011-02-16 19:54:13 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                               end,
							 | 
						
					
						
							
								
									
										
										
										
											2010-10-28 05:14:19 +08:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                               {Method, Props, BodyFragments},
							 | 
						
					
						
							
								
									
										
										
										
											2011-07-19 23:15:59 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                               State1);
							 | 
						
					
						
							
								
									
										
										
										
											2010-10-28 05:14:19 +08:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        no ->
							 | 
						
					
						
							
								
									
										
										
										
											2011-02-16 17:56:39 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								            ok(send_method(Method, Props, BodyFragments,
							 | 
						
					
						
							
								
									
										
										
										
											2011-07-19 23:15:59 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                           maybe_record_receipt(Frame1, State1)))
							 | 
						
					
						
							
								
									
										
										
										
											2010-10-28 05:14:19 +08:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    end.
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2011-01-11 21:57:59 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								create_ack_method(DeliveryTag, #subscription{multi_ack = IsMulti}) ->
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    #'basic.ack'{delivery_tag = DeliveryTag,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                 multiple     = IsMulti}.
							 | 
						
					
						
							
								
									
										
										
										
											2011-01-11 19:25:44 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2011-01-17 20:35:45 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								create_nack_method(DeliveryTag, #subscription{multi_ack = IsMulti}) ->
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    #'basic.nack'{delivery_tag = DeliveryTag,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                  multiple     = IsMulti}.
							 | 
						
					
						
							
								
									
										
										
										
											2011-01-11 19:25:44 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2010-11-09 19:57:20 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								negotiate_version(Frame) ->
							 | 
						
					
						
							
								
									
										
										
										
											2011-12-01 20:51:02 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    ClientVers = re:split(rabbit_stomp_frame:header(
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                            Frame, ?HEADER_ACCEPT_VERSION, "1.0"),
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                          ",", [{return, list}]),
							 | 
						
					
						
							
								
									
										
										
										
											2010-11-09 19:57:20 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    rabbit_stomp_util:negotiate_version(ClientVers, ?SUPPORTED_VERSIONS).
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2010-10-28 05:14:19 +08:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2010-10-28 19:04:40 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								send_delivery(Delivery = #'basic.deliver'{consumer_tag = ConsumerTag},
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								              Properties, Body,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								              State = #state{session_id    = SessionId,
							 | 
						
					
						
							
								
									
										
										
										
											2012-11-07 01:30:31 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                             subscriptions = Subs,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                             version       = Version}) ->
							 | 
						
					
						
							
								
									
										
										
										
											2011-01-13 22:18:25 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    case dict:find(ConsumerTag, Subs) of
							 | 
						
					
						
							
								
									
										
										
										
											2012-11-07 01:30:31 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        {ok, #subscription{ack_mode = AckMode}} ->
							 | 
						
					
						
							
								
									
										
										
										
											2011-01-13 22:18:25 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								            send_frame(
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								              "MESSAGE",
							 | 
						
					
						
							
								
									
										
										
										
											2012-11-07 01:30:31 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								              rabbit_stomp_util:headers(SessionId, Delivery, Properties,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                                        AckMode, Version),
							 | 
						
					
						
							
								
									
										
										
										
											2011-01-13 22:18:25 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								              Body,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								              State);
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        error ->
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            send_error("Subscription not found",
							 | 
						
					
						
							
								
									
										
										
										
											2011-01-19 00:24:42 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                       "There is no current subscription with tag '~s'.",
							 | 
						
					
						
							
								
									
										
										
										
											2011-01-13 22:18:25 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                       [ConsumerTag],
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                       State)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    end.
							 | 
						
					
						
							
								
									
										
										
										
											2010-10-28 05:14:19 +08:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2011-01-06 23:54:05 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								send_method(Method, Channel, State) ->
							 | 
						
					
						
							
								
									
										
										
										
											2010-10-28 05:14:19 +08:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    amqp_channel:call(Channel, Method),
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    State.
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								send_method(Method, State = #state{channel = Channel}) ->
							 | 
						
					
						
							
								
									
										
										
										
											2011-01-13 23:24:25 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    send_method(Method, Channel, State).
							 | 
						
					
						
							
								
									
										
										
										
											2010-10-28 05:14:19 +08:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								send_method(Method, Properties, BodyFragments,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            State = #state{channel = Channel}) ->
							 | 
						
					
						
							
								
									
										
										
										
											2011-01-15 01:09:50 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    send_method(Method, Channel, Properties, BodyFragments, State).
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2012-01-18 22:48:54 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								send_method(Method = #'basic.publish'{}, Channel, Properties, BodyFragments,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            State) ->
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    amqp_channel:cast_flow(
							 | 
						
					
						
							
								
									
										
										
										
											2011-02-09 18:24:48 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								      Channel, Method,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								      #amqp_msg{props   = Properties,
							 | 
						
					
						
							
								
									
										
										
										
											2011-02-23 01:24:59 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                payload = list_to_binary(BodyFragments)}),
							 | 
						
					
						
							
								
									
										
										
										
											2010-10-28 05:14:19 +08:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    State.
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2011-08-25 19:35:38 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								%% Closing the connection will close the channel and subchannels
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								close_connection(State = #state{connection = Connection}) ->
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    %% ignore noproc or other exceptions to avoid debris
							 | 
						
					
						
							
								
									
										
										
										
											2011-08-25 00:05:54 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    catch amqp_connection:close(Connection),
							 | 
						
					
						
							
								
									
										
										
										
											2011-02-16 20:10:09 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    State#state{channel = none, connection = none, subscriptions = none}.
							 | 
						
					
						
							
								
									
										
										
										
											2010-10-28 05:14:19 +08:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2011-07-19 23:15:59 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								%%----------------------------------------------------------------------------
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								%% Reply-To
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								%%----------------------------------------------------------------------------
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								ensure_reply_to(Frame = #stomp_frame{headers = Headers}, State) ->
							 | 
						
					
						
							
								
									
										
										
										
											2011-11-25 20:11:22 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    case rabbit_stomp_frame:header(Frame, ?HEADER_REPLY_TO) of
							 | 
						
					
						
							
								
									
										
										
										
											2011-07-19 23:15:59 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        not_found ->
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            {Frame, State};
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        {ok, ReplyTo} ->
							 | 
						
					
						
							
								
									
										
										
										
											2013-02-16 00:11:17 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								            {ok, Destination} = routing_util:parse_endpoint(ReplyTo),
							 | 
						
					
						
							
								
									
										
										
										
											2011-07-19 23:15:59 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								            case Destination of
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                {temp_queue, TempQueueId} ->
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                    {ReplyQueue, State1} =
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                        ensure_reply_queue(TempQueueId, State),
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                    {Frame#stomp_frame{
							 | 
						
					
						
							
								
									
										
										
										
											2011-12-01 20:51:02 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                       headers = lists:keyreplace(
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                                   ?HEADER_REPLY_TO, 1, Headers,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                                   {?HEADER_REPLY_TO, ReplyQueue})},
							 | 
						
					
						
							
								
									
										
										
										
											2011-07-19 23:15:59 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                     State1};
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                _ ->
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                    {Frame, State}
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            end
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    end.
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								ensure_reply_queue(TempQueueId, State = #state{channel       = Channel,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                                               reply_queues  = RQS,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                                               subscriptions = Subs}) ->
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    case dict:find(TempQueueId, RQS) of
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        {ok, RQ} ->
							 | 
						
					
						
							
								
									
										
										
										
											2012-10-03 18:11:51 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								            {binary_to_list(RQ), State};
							 | 
						
					
						
							
								
									
										
										
										
											2011-07-19 23:15:59 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        error ->
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            #'queue.declare_ok'{queue = Queue} =
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                amqp_channel:call(Channel,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                                  #'queue.declare'{auto_delete = true,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                                                   exclusive   = true}),
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2012-02-21 02:09:45 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								            ConsumerTag = rabbit_stomp_util:consumer_tag_reply_to(TempQueueId),
							 | 
						
					
						
							
								
									
										
										
										
											2012-02-16 01:56:11 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								            #'basic.consume_ok'{} =
							 | 
						
					
						
							
								
									
										
										
										
											2011-07-19 23:15:59 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                amqp_channel:subscribe(Channel,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                                       #'basic.consume'{
							 | 
						
					
						
							
								
									
										
										
										
											2012-02-16 01:56:11 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                                         queue        = Queue,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                                         consumer_tag = ConsumerTag,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                                         no_ack       = true,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                                         nowait       = false},
							 | 
						
					
						
							
								
									
										
										
										
											2011-07-19 23:15:59 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                                       self()),
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2012-10-03 18:11:51 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								            Destination = binary_to_list(Queue),
							 | 
						
					
						
							
								
									
										
										
										
											2011-07-19 23:15:59 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            %% synthesise a subscription to the reply queue destination
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            Subs1 = dict:store(ConsumerTag,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                               #subscription{dest_hdr    = Destination,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                                             channel     = Channel,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                                             multi_ack   = false},
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                               Subs),
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            {Destination, State#state{
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                            reply_queues  = dict:store(TempQueueId, Queue, RQS),
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                            subscriptions = Subs1}}
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    end.
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2011-02-16 17:56:39 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								%%----------------------------------------------------------------------------
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								%% Receipt Handling
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								%%----------------------------------------------------------------------------
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								ensure_receipt(Frame = #stomp_frame{command = Command}, State) ->
							 | 
						
					
						
							
								
									
										
										
										
											2011-11-25 20:49:56 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    case rabbit_stomp_frame:header(Frame, ?HEADER_RECEIPT) of
							 | 
						
					
						
							
								
									
										
										
										
											2011-02-16 17:56:39 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        {ok, Id}  -> do_receipt(Command, Id, State);
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        not_found -> State
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    end.
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								do_receipt("SEND", _, State) ->
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    %% SEND frame receipts are handled when messages are confirmed
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    State;
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								do_receipt(_Frame, ReceiptId, State) ->
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    send_frame("RECEIPT", [{"receipt-id", ReceiptId}], "", State).
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								maybe_record_receipt(Frame, State = #state{channel          = Channel,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                                           pending_receipts = PR}) ->
							 | 
						
					
						
							
								
									
										
										
										
											2011-11-25 20:49:56 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    case rabbit_stomp_frame:header(Frame, ?HEADER_RECEIPT) of
							 | 
						
					
						
							
								
									
										
										
										
											2011-02-16 17:56:39 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        {ok, Id} ->
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            PR1 = case PR of
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                      undefined ->
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                          amqp_channel:register_confirm_handler(
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                            Channel, self()),
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                          #'confirm.select_ok'{} =
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                              amqp_channel:call(Channel, #'confirm.select'{}),
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                          gb_trees:empty();
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                      _ ->
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                          PR
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                  end,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            SeqNo = amqp_channel:next_publish_seqno(Channel),
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            State#state{pending_receipts = gb_trees:insert(SeqNo, Id, PR1)};
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        not_found ->
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            State
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    end.
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								flush_pending_receipts(DeliveryTag, IsMulti,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                       State = #state{pending_receipts = PR}) ->
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    {Receipts, PR1} = accumulate_receipts(DeliveryTag, IsMulti, PR),
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    State1 = lists:foldl(fun(ReceiptId, StateN) ->
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                                 do_receipt(none, ReceiptId, StateN)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                         end, State, Receipts),
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    State1#state{pending_receipts = PR1}.
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								accumulate_receipts(DeliveryTag, false, PR) ->
							 | 
						
					
						
							
								
									
										
										
										
											2011-02-25 01:12:21 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    case gb_trees:lookup(DeliveryTag, PR) of
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        {value, ReceiptId} -> {[ReceiptId], gb_trees:delete(DeliveryTag, PR)};
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        none               -> {[], PR}
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    end;
							 | 
						
					
						
							
								
									
										
										
										
											2011-08-26 01:43:24 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2011-02-16 17:56:39 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								accumulate_receipts(DeliveryTag, true, PR) ->
							 | 
						
					
						
							
								
									
										
										
										
											2011-08-26 20:10:44 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    case gb_trees:is_empty(PR) of
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        true  -> {[], PR};
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        false -> accumulate_receipts1(DeliveryTag,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                                      gb_trees:take_smallest(PR), [])
							 | 
						
					
						
							
								
									
										
										
										
											2011-02-25 01:12:21 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    end.
							 | 
						
					
						
							
								
									
										
										
										
											2011-02-16 17:56:39 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2011-08-26 01:43:24 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								accumulate_receipts1(DeliveryTag, {Key, Value, PR}, Acc)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								  when Key > DeliveryTag ->
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    {lists:reverse(Acc), gb_trees:insert(Key, Value, PR)};
							 | 
						
					
						
							
								
									
										
										
										
											2011-02-16 17:56:39 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								accumulate_receipts1(DeliveryTag, {_Key, Value, PR}, Acc) ->
							 | 
						
					
						
							
								
									
										
										
										
											2011-08-26 01:43:24 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    Acc1 = [Value | Acc],
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    case gb_trees:is_empty(PR) of
							 | 
						
					
						
							
								
									
										
										
										
											2011-09-10 00:02:11 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        true  -> {lists:reverse(Acc1), PR};
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        false -> accumulate_receipts1(DeliveryTag,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                                      gb_trees:take_smallest(PR), Acc1)
							 | 
						
					
						
							
								
									
										
										
										
											2011-08-26 01:43:24 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    end.
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2011-02-16 17:56:39 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2010-10-28 05:14:19 +08:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								%%----------------------------------------------------------------------------
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								%% Transaction Support
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								%%----------------------------------------------------------------------------
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								transactional(Frame) ->
							 | 
						
					
						
							
								
									
										
										
										
											2012-07-11 18:44:12 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    case rabbit_stomp_frame:header(Frame, ?HEADER_TRANSACTION) of
							 | 
						
					
						
							
								
									
										
										
										
											2011-09-10 00:02:11 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        {ok, Transaction} -> {yes, Transaction};
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        not_found         -> no
							 | 
						
					
						
							
								
									
										
										
										
											2010-10-28 05:14:19 +08:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    end.
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								transactional_action(Frame, Name, Fun, State) ->
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    case transactional(Frame) of
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        {yes, Transaction} ->
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            Fun(Transaction, State);
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        no ->
							 | 
						
					
						
							
								
									
										
										
										
											2010-11-26 19:10:43 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								            error("Missing transaction",
							 | 
						
					
						
							
								
									
										
										
										
											2012-08-16 00:03:53 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                  "~p must include a 'transaction' header~n",
							 | 
						
					
						
							
								
									
										
										
										
											2011-08-24 21:50:48 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                  [Name],
							 | 
						
					
						
							
								
									
										
										
										
											2010-11-26 19:10:43 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                  State)
							 | 
						
					
						
							
								
									
										
										
										
											2010-10-28 05:14:19 +08:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    end.
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								with_transaction(Transaction, State, Fun) ->
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    case get({transaction, Transaction}) of
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        undefined ->
							 | 
						
					
						
							
								
									
										
										
										
											2010-11-26 19:10:43 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								            error("Bad transaction",
							 | 
						
					
						
							
								
									
										
										
										
											2012-08-16 00:03:53 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                  "Invalid transaction identifier: ~p~n",
							 | 
						
					
						
							
								
									
										
										
										
											2010-11-26 19:10:43 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                  [Transaction],
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                  State);
							 | 
						
					
						
							
								
									
										
										
										
											2010-10-28 05:14:19 +08:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        Actions ->
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            Fun(Actions, State)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    end.
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								begin_transaction(Transaction, State) ->
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    put({transaction, Transaction}, []),
							 | 
						
					
						
							
								
									
										
										
										
											2010-11-26 19:10:43 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    ok(State).
							 | 
						
					
						
							
								
									
										
										
										
											2010-10-28 05:14:19 +08:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2011-02-16 19:54:13 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								extend_transaction(Transaction, Callback, Action, State) ->
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    extend_transaction(Transaction, {callback, Callback, Action}, State).
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2010-10-28 05:14:19 +08:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								extend_transaction(Transaction, Action, State0) ->
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    with_transaction(
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								      Transaction, State0,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								      fun (Actions, State) ->
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								              put({transaction, Transaction}, [Action | Actions]),
							 | 
						
					
						
							
								
									
										
										
										
											2010-11-26 19:10:43 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								              ok(State)
							 | 
						
					
						
							
								
									
										
										
										
											2010-10-28 05:14:19 +08:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								      end).
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								commit_transaction(Transaction, State0) ->
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    with_transaction(
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								      Transaction, State0,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								      fun (Actions, State) ->
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								              FinalState = lists:foldr(fun perform_transaction_action/2,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                                       State,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                                       Actions),
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								              erase({transaction, Transaction}),
							 | 
						
					
						
							
								
									
										
										
										
											2011-01-11 02:43:41 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								              ok(FinalState)
							 | 
						
					
						
							
								
									
										
										
										
											2010-10-28 05:14:19 +08:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								      end).
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								abort_transaction(Transaction, State0) ->
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    with_transaction(
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								      Transaction, State0,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								      fun (_Actions, State) ->
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								              erase({transaction, Transaction}),
							 | 
						
					
						
							
								
									
										
										
										
											2010-11-26 19:10:43 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								              ok(State)
							 | 
						
					
						
							
								
									
										
										
										
											2010-10-28 05:14:19 +08:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								      end).
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2011-02-16 19:54:13 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								perform_transaction_action({callback, Callback, Action}, State) ->
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    perform_transaction_action(Action, Callback(State));
							 | 
						
					
						
							
								
									
										
										
										
											2010-10-28 05:14:19 +08:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								perform_transaction_action({Method}, State) ->
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    send_method(Method, State);
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								perform_transaction_action({Channel, Method}, State) ->
							 | 
						
					
						
							
								
									
										
										
										
											2011-01-15 01:09:50 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    send_method(Method, Channel, State);
							 | 
						
					
						
							
								
									
										
										
										
											2010-10-28 05:14:19 +08:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								perform_transaction_action({Method, Props, BodyFragments}, State) ->
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    send_method(Method, Props, BodyFragments, State).
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2010-11-10 03:10:56 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								%%--------------------------------------------------------------------
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								%% Heartbeat Management
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								%%--------------------------------------------------------------------
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2010-11-11 05:09:20 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								ensure_heartbeats(Heartbeats,
							 | 
						
					
						
							
								
									
										
										
										
											2012-02-20 21:09:07 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                  State = #state{start_heartbeat_fun = SHF,
							 | 
						
					
						
							
								
									
										
										
										
											2012-02-20 23:12:12 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                                 send_fun            = RawSendFun}) ->
							 | 
						
					
						
							
								
									
										
										
										
											2010-11-10 03:10:56 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    [CX, CY] = [list_to_integer(X) ||
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                   X <- re:split(Heartbeats, ",", [{return, list}])],
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2012-02-20 23:12:12 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    SendFun = fun() -> RawSendFun(sync, <<$\n>>) end,
							 | 
						
					
						
							
								
									
										
										
										
											2010-11-11 05:09:20 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    Pid = self(),
							 | 
						
					
						
							
								
									
										
										
										
											2011-09-10 00:02:11 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    ReceiveFun = fun() -> gen_server2:cast(Pid, client_timeout) end,
							 | 
						
					
						
							
								
									
										
										
										
											2010-11-10 03:10:56 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2010-11-18 18:10:16 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    {SendTimeout, ReceiveTimeout} =
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        {millis_to_seconds(CY), millis_to_seconds(CX)},
							 | 
						
					
						
							
								
									
										
										
										
											2010-11-11 05:09:20 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2012-02-20 21:09:07 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    SHF(SendTimeout, SendFun, ReceiveTimeout, ReceiveFun),
							 | 
						
					
						
							
								
									
										
										
										
											2010-11-11 05:09:20 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    {{SendTimeout * 1000 , ReceiveTimeout * 1000}, State}.
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2011-09-10 00:02:11 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								millis_to_seconds(M) when M =< 0   -> 0;
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								millis_to_seconds(M) when M < 1000 -> 1;
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								millis_to_seconds(M)               -> M div 1000.
							 | 
						
					
						
							
								
									
										
										
										
											2010-11-10 03:10:56 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2010-10-28 05:14:19 +08:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								%%----------------------------------------------------------------------------
							 | 
						
					
						
							
								
									
										
										
										
											2013-02-16 00:11:17 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								%% Queue Setup
							 | 
						
					
						
							
								
									
										
										
										
											2010-10-28 05:14:19 +08:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								%%----------------------------------------------------------------------------
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2013-02-16 00:11:17 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								ensure_endpoint(source, {topic, Name}, Frame, Channel, State) ->
							 | 
						
					
						
							
								
									
										
										
										
											2013-02-20 02:23:13 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    Params =
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        case rabbit_stomp_frame:boolean_header(
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								               Frame, ?HEADER_PERSISTENT, false) of
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            true ->
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                [{queue_name_gen,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                    fun () ->
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                        {ok, Id} = rabbit_stomp_frame:header(Frame, ?HEADER_ID),
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                        list_to_binary(rabbit_stomp_util:durable_subscription_queue(Name, Id))
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                    end},
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                 {durable, true}];
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            false ->
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                [{durable, false}];
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        end,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    routing_util:ensure_endpoint(source, Channel, {topic, Name}, Params, State);
							 | 
						
					
						
							
								
									
										
										
										
											2013-02-16 00:11:17 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								ensure_endpoint(Direction, Endpoint, _Frame, Channel, State) ->
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    routing_util:ensure_endpoint(Direction, Channel, Endpoint, State).
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2010-11-26 19:10:43 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								%%----------------------------------------------------------------------------
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								%% Success/error handling
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								%%----------------------------------------------------------------------------
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								ok(State) ->
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    {ok, none, State}.
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								ok(Command, Headers, BodyFragments, State) ->
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    {ok, #stomp_frame{command     = Command,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                      headers     = Headers,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                      body_iolist = BodyFragments}, State}.
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2011-01-17 18:38:43 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								amqp_death(ReplyCode, Explanation, State) ->
							 | 
						
					
						
							
								
									
										
										
										
											2012-07-03 02:32:06 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    ErrorName = amqp_connection:error_atom(ReplyCode),
							 | 
						
					
						
							
								
									
										
										
										
											2012-02-02 23:51:33 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    ErrorDesc = rabbit_misc:format("~s~n", [Explanation]),
							 | 
						
					
						
							
								
									
										
										
										
											2012-02-01 01:07:07 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    log_error(ErrorName, ErrorDesc, none),
							 | 
						
					
						
							
								
									
										
										
										
											2012-01-31 22:35:48 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    {stop, normal, send_error(atom_to_list(ErrorName), ErrorDesc, State)}.
							 | 
						
					
						
							
								
									
										
										
										
											2010-11-26 19:10:43 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								error(Message, Detail, State) ->
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    priv_error(Message, Detail, none, State).
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								error(Message, Format, Args, State) ->
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    priv_error(Message, Format, Args, none, State).
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								priv_error(Message, Detail, ServerPrivateDetail, State) ->
							 | 
						
					
						
							
								
									
										
										
										
											2012-02-01 00:32:56 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    log_error(Message, Detail, ServerPrivateDetail),
							 | 
						
					
						
							
								
									
										
										
										
											2010-11-26 19:10:43 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    {error, Message, Detail, State}.
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								priv_error(Message, Format, Args, ServerPrivateDetail, State) ->
							 | 
						
					
						
							
								
									
										
										
										
											2012-02-02 23:51:33 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    priv_error(Message, rabbit_misc:format(Format, Args), ServerPrivateDetail,
							 | 
						
					
						
							
								
									
										
										
										
											2012-02-01 00:32:56 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								               State).
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								log_error(Message, Detail, ServerPrivateDetail) ->
							 | 
						
					
						
							
								
									
										
										
										
											2012-01-27 06:16:37 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    rabbit_log:error("STOMP error frame sent:~n"
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                     "Message: ~p~n"
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                     "Detail: ~p~n"
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                     "Server private detail: ~p~n",
							 | 
						
					
						
							
								
									
										
										
										
											2012-02-01 00:40:46 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                     [Message, Detail, ServerPrivateDetail]).
							 | 
						
					
						
							
								
									
										
										
										
											2010-11-26 19:10:43 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2010-10-28 05:14:19 +08:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								%%----------------------------------------------------------------------------
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								%% Frame sending utilities
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								%%----------------------------------------------------------------------------
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								send_frame(Command, Headers, BodyFragments, State) ->
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    send_frame(#stomp_frame{command     = Command,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                            headers     = Headers,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                            body_iolist = BodyFragments},
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								               State).
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2012-02-20 23:12:12 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								send_frame(Frame, State = #state{send_fun = SendFun}) ->
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    SendFun(async, rabbit_stomp_frame:serialize(Frame)),
							 | 
						
					
						
							
								
									
										
										
										
											2011-01-27 01:46:27 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    State.
							 | 
						
					
						
							
								
									
										
										
										
											2010-10-28 05:14:19 +08:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2012-07-11 18:44:12 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								send_error_frame(Message, ExtraHeaders, Format, Args, State) ->
							 | 
						
					
						
							
								
									
										
										
										
											2012-08-07 18:02:27 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    send_error_frame(Message, ExtraHeaders, rabbit_misc:format(Format, Args),
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                     State).
							 | 
						
					
						
							
								
									
										
										
										
											2012-07-11 18:44:12 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								send_error_frame(Message, ExtraHeaders, Detail, State) ->
							 | 
						
					
						
							
								
									
										
										
										
											2010-10-28 05:14:19 +08:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    send_frame("ERROR", [{"message", Message},
							 | 
						
					
						
							
								
									
										
										
										
											2010-11-09 19:57:20 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                         {"content-type", "text/plain"},
							 | 
						
					
						
							
								
									
										
										
										
											2012-08-07 18:02:27 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                         {"version", string:join(?SUPPORTED_VERSIONS, ",")}] ++
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                        ExtraHeaders,
							 | 
						
					
						
							
								
									
										
										
										
											2012-07-11 18:44:12 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                        Detail, State).
							 | 
						
					
						
							
								
									
										
										
										
											2010-10-28 05:14:19 +08:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2012-07-11 18:44:12 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								send_error(Message, Detail, State) ->
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    send_error_frame(Message, [], Detail, State).
							 | 
						
					
						
							
								
									
										
										
										
											2012-08-07 18:02:27 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2011-01-13 22:18:25 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								send_error(Message, Format, Args, State) ->
							 | 
						
					
						
							
								
									
										
										
										
											2012-02-02 23:51:33 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    send_error(Message, rabbit_misc:format(Format, Args), State).
							 | 
						
					
						
							
								
									
										
										
										
											2011-01-13 22:18:25 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2010-10-28 05:14:19 +08:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								%%----------------------------------------------------------------------------
							 | 
						
					
						
							
								
									
										
										
										
											2011-01-31 21:00:15 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								%% Skeleton gen_server2 callbacks
							 | 
						
					
						
							
								
									
										
										
										
											2010-10-28 05:14:19 +08:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								%%----------------------------------------------------------------------------
							 | 
						
					
						
							
								
									
										
										
										
											2011-02-10 00:35:03 +08:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								handle_call(_Msg, _From, State) ->
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    {noreply, State}.
							 | 
						
					
						
							
								
									
										
										
										
											2010-10-28 05:14:19 +08:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								code_change(_OldVsn, State, _Extra) ->
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    {ok, State}.
							 |