28
28
29
29
% %--------------------------------------------------------------------------
30
30
31
- -record (v1 , {parent , sock , connection , callback , recv_len , pending_recv ,
32
- connection_state , heartbeater , helper_sup ,
33
- channel_sup_sup_pid , buf , buf_len , throttle , proxy_socket ,
34
- tracked_channels }).
31
+ -record (v1 ,
32
+ {
33
+ parent ,
34
+ sock :: rabbit_net :socket (),
35
+ connection , callback , recv_len , pending_recv ,
36
+ connection_state , heartbeater , helper_sup ,
37
+ channel_sup_sup_pid , buf , buf_len , throttle , proxy_socket ,
38
+ tracked_channels ,
39
+ writer :: rabbit_types :option (pid ())
40
+ }).
35
41
36
42
-record (v1_connection , {name :: binary (),
37
43
host ,
@@ -385,64 +391,62 @@ parse_1_0_frame(Payload, _Channel) ->
385
391
_ -> {Perf , Rest }
386
392
end .
387
393
388
- handle_1_0_connection_frame (# 'v1_0.open' { max_frame_size = ClientFrameMax ,
389
- channel_max = ClientChannelMax ,
390
- idle_time_out = IdleTimeout ,
391
- hostname = Hostname } ,
392
- State = # v1 {
393
- connection_state = starting ,
394
- connection = Connection ,
395
- throttle = Throttle ,
396
- helper_sup = HelperSupPid ,
397
- sock = Sock }) ->
394
+ handle_1_0_connection_frame (
395
+ # 'v1_0.open' { max_frame_size = ClientFrameMax ,
396
+ channel_max = ClientChannelMax ,
397
+ idle_time_out = IdleTimeout ,
398
+ hostname = Hostname },
399
+ # v1 { connection_state = starting ,
400
+ connection = Connection ,
401
+ throttle = Throttle ,
402
+ helper_sup = HelperSupPid ,
403
+ sock = Sock } = State0 ) ->
398
404
ClientHeartbeatSec = case IdleTimeout of
399
- undefined -> 0 ;
405
+ undefined -> 0 ;
400
406
{uint , Interval } -> Interval div 1000
401
407
end ,
402
- FrameMax = case ClientFrameMax of
403
- undefined -> unlimited ;
404
- {_ , FM } -> FM
405
- end ,
408
+ FrameMax = case ClientFrameMax of
409
+ undefined -> unlimited ;
410
+ {_ , FM } -> FM
411
+ end ,
406
412
{ok , HeartbeatSec } = application :get_env (rabbit , heartbeat ),
407
- State1 =
408
- if (FrameMax =/= unlimited ) and (FrameMax < ? FRAME_1_0_MIN_SIZE ) ->
409
- protocol_error (? V_1_0_AMQP_ERROR_FRAME_SIZE_TOO_SMALL ,
410
- " frame_max=~w < ~w min size" ,
411
- [FrameMax , ? FRAME_1_0_MIN_SIZE ]);
412
- true ->
413
- SendFun =
414
- fun () ->
415
- Frame =
416
- amqp10_binary_generator :build_heartbeat_frame (),
417
- catch rabbit_net :send (Sock , Frame )
418
- end ,
419
-
420
- Parent = self (),
421
- ReceiveFun =
422
- fun () ->
423
- Parent ! heartbeat_timeout
424
- end ,
425
- % % [2.4.5] the value in idle-time-out SHOULD be half the peer's
426
- % % actual timeout threshold
427
- ReceiverHeartbeatSec = lists :min ([HeartbeatSec * 2 , 4294967 ]),
428
- % % TODO: only start heartbeat receive timer at next next frame
429
- Heartbeater =
430
- rabbit_heartbeat :start (HelperSupPid , Sock ,
431
- ClientHeartbeatSec , SendFun ,
432
- ReceiverHeartbeatSec , ReceiveFun ),
433
- State # v1 {connection_state = running ,
434
- connection = Connection # v1_connection {
435
- frame_max = FrameMax ,
436
- hostname = Hostname },
437
- heartbeater = Heartbeater }
438
- end ,
413
+ if (FrameMax =/= unlimited ) and (FrameMax < ? FRAME_1_0_MIN_SIZE ) ->
414
+ protocol_error (? V_1_0_AMQP_ERROR_FRAME_SIZE_TOO_SMALL ,
415
+ " frame_max=~w < ~w min size" ,
416
+ [FrameMax , ? FRAME_1_0_MIN_SIZE ]);
417
+ true ->
418
+ ok
419
+ end ,
420
+
421
+ SendFun = fun () ->
422
+ Frame = amqp10_binary_generator :build_heartbeat_frame (),
423
+ catch rabbit_net :send (Sock , Frame )
424
+ end ,
425
+ Parent = self (),
426
+ ReceiveFun = fun () ->
427
+ Parent ! heartbeat_timeout
428
+ end ,
429
+ % % [2.4.5] the value in idle-time-out SHOULD be half the peer's
430
+ % % actual timeout threshold
431
+ ReceiverHeartbeatSec = lists :min ([HeartbeatSec * 2 , 4294967 ]),
432
+ % % TODO: only start heartbeat receive timer at next next frame
433
+ Heartbeater = rabbit_heartbeat :start (
434
+ HelperSupPid , Sock ,
435
+ ClientHeartbeatSec , SendFun ,
436
+ ReceiverHeartbeatSec , ReceiveFun ),
437
+ State1 = State0 # v1 {connection_state = running ,
438
+ connection = Connection # v1_connection {
439
+ frame_max = FrameMax ,
440
+ hostname = Hostname },
441
+ heartbeater = Heartbeater },
442
+ State2 = start_writer (State1 ),
439
443
HostnameVal = case Hostname of
440
- undefined -> undefined ;
441
- null -> undefined ;
442
- {utf8 , Val } -> Val
444
+ undefined -> undefined ;
445
+ null -> undefined ;
446
+ {utf8 , Val } -> Val
443
447
end ,
444
448
rabbit_log :debug (" AMQP 1.0 connection.open frame: hostname = ~ts , extracted vhost = ~ts , idle_timeout = ~tp " ,
445
- [HostnameVal , vhost (Hostname ), HeartbeatSec * 1000 ]),
449
+ [HostnameVal , vhost (Hostname ), HeartbeatSec * 1000 ]),
446
450
% % TODO enforce channel_max
447
451
ok = send_on_channel0 (
448
452
Sock ,
@@ -452,20 +456,35 @@ handle_1_0_connection_frame(#'v1_0.open'{ max_frame_size = ClientFrameMax,
452
456
container_id = {utf8 , rabbit_nodes :cluster_name ()},
453
457
properties = server_properties ()}),
454
458
Conserve = rabbit_alarm :register (self (), {? MODULE , conserve_resources , []}),
459
+ State = State2 # v1 {throttle = Throttle # throttle {alarmed_by = Conserve }},
455
460
456
- Infos = infos (? EVENT_KEYS , State1 ),
461
+ Infos = infos (? EVENT_KEYS , State ),
457
462
ok = rabbit_core_metrics :connection_created (
458
463
proplists :get_value (pid , Infos ),
459
464
Infos ),
460
465
ok = rabbit_event :notify (connection_created , Infos ),
461
466
ok = rabbit_networking :register_connection (self ()),
462
467
463
- control_throttle (
464
- State1 # v1 {throttle = Throttle # throttle {alarmed_by = Conserve }});
468
+ control_throttle (State );
465
469
466
470
handle_1_0_connection_frame (_Frame , State ) ->
467
471
maybe_close (State # v1 {connection_state = closing }).
468
472
473
+ start_writer (# v1 {helper_sup = SupPid ,
474
+ sock = Sock ,
475
+ connection = # v1_connection {frame_max = FrameMax }} = State ) ->
476
+ ChildSpec = #{id => writer ,
477
+ start => {rabbit_amqp1_0_writer , start_link ,
478
+ [Sock , FrameMax , self ()]},
479
+ restart => transient ,
480
+ significant => true ,
481
+ shutdown => ? WORKER_WAIT ,
482
+ type => worker ,
483
+ modules => [rabbit_amqp1_0_writer ]
484
+ },
485
+ {ok , Pid } = supervisor :start_child (SupPid , ChildSpec ),
486
+ State # v1 {writer = Pid }.
487
+
469
488
handle_1_0_session_frame (Channel , Frame , State ) ->
470
489
case maps :get (Channel , State # v1 .tracked_channels , undefined ) of
471
490
undefined ->
@@ -640,8 +659,7 @@ send_on_channel0(Sock, Method) ->
640
659
send_on_channel0 (Sock , Method , amqp10_framing ).
641
660
642
661
send_on_channel0 (Sock , Method , Framing ) ->
643
- ok = rabbit_amqp1_0_writer :internal_send_command (
644
- Sock , 0 , Method , Framing ).
662
+ ok = rabbit_amqp1_0_writer :internal_send_command (Sock , Method , Framing ).
645
663
646
664
% % End 1-0
647
665
@@ -728,23 +746,27 @@ untrack_channel(Channel, State) ->
728
746
error -> State
729
747
end .
730
748
731
- send_to_new_1_0_session (Channel , Frame , State ) ->
732
- # v1 {sock = Sock ,
733
- channel_sup_sup_pid = ChanSupSup ,
734
- connection = # v1_connection {frame_max = FrameMax ,
735
- hostname = Hostname ,
736
- user = User }
737
- } = State ,
738
- % % Note: the equivalent, start_channel is in channel_sup_sup
739
-
740
- case rabbit_amqp1_0_session_sup_sup :start_session (
741
- % % NB subtract fixed frame header size
742
- ChanSupSup , {amqp10_framing , Sock , Channel ,
743
- case FrameMax of
744
- unlimited -> unlimited ;
745
- _ -> FrameMax - 8
746
- end ,
747
- self (), User , vhost (Hostname )}) of
749
+ send_to_new_1_0_session (
750
+ Channel , Frame ,
751
+ # v1 {channel_sup_sup_pid = ChanSupSup ,
752
+ connection = # v1_connection {frame_max = FrameMax0 ,
753
+ hostname = Hostname ,
754
+ user = User },
755
+ writer = WriterPid } = State ) ->
756
+ % % Subtract fixed frame header size.
757
+ FrameMax = case FrameMax0 of
758
+ unlimited -> unlimited ;
759
+ _ -> FrameMax0 - 8
760
+ end ,
761
+ ChildArg = {amqp10_framing ,
762
+ Channel ,
763
+ FrameMax ,
764
+ self (),
765
+ WriterPid ,
766
+ User ,
767
+ vhost (Hostname )},
768
+ % % The equivalent, start_channel is in channel_sup_sup.
769
+ case rabbit_amqp1_0_session_sup_sup :start_session (ChanSupSup , ChildArg ) of
748
770
{ok , _ChSupPid , ChFrPid } ->
749
771
erlang :monitor (process , ChFrPid ),
750
772
ModifiedState = track_channel (Channel , ChFrPid , State ),
0 commit comments