anchor.diff:  connect(Prot) ->
       T = {Prot, make_ref()},
       [] = ?util:run([{?MODULE, [init, X, T]} || X <- [gen_accept, connect]]).
  +
  +%% ===========================================================================
  +%% reconnect/1
  +%%
  +%% Exercise reconnection behaviour: that a connecting transport
  +%% doesn't try to establish a new connection until the old one is
  +%% broken.
  +
  +reconnect() ->
  +    [{timetrap, {minutes, 4}}].
  +
  +reconnect({listen, Ref}) ->
  +    SvcName = make_ref(),
  +    ok = start_service(SvcName),
  +    LRef = ?util:listen(SvcName, tcp, [{watchdog_timer, 6000}]),
  +    [_] = diameter_reg:wait({diameter_tcp, listener, {LRef, '_'}}),
  +    true = diameter_reg:add_new({?MODULE, Ref, LRef}),
  +
  +    %% Wait for partner to request transport death: kill to force the
  +    %% peer to reconnect.
  +    TPid = abort(SvcName, LRef, Ref),
  +
  +    exit(TPid, kill),
  +
  +    abort(SvcName, LRef, Ref);
  +
  +reconnect({connect, Ref}) ->
  +    SvcName = make_ref(),
  +    true = diameter:subscribe(SvcName),
  +    ok = start_service(SvcName),
  +    [{{_, _, LRef}, Pid}] = diameter_reg:wait({?MODULE, Ref, '_'}),
  +    CRef = ?util:connect(SvcName, tcp, LRef, [{reconnect_timer, 2000},
  +                                              {watchdog_timer, 6000}]),
  +
  +    %% Tell partner to kill transport after seeing that there are no
  +    %% reconnection attempts.
  +    abort(SvcName, Pid, Ref),
  +
  +    %% Transport does down and is reestablished.
  +    ?RECV(#diameter_event{service = SvcName, info = {down, CRef, _, _}}),
  +    ?RECV(#diameter_event{service = SvcName, info = {reconnect, CRef, _}}),
  +    ?RECV(#diameter_event{service = SvcName, info = {up, CRef, _, _, _}}),
  +
  +    %% Kill again.
  +    abort(SvcName, Pid, Ref),
  +
  +    %% Wait for partner to die.
  +    MRef = erlang:monitor(process, Pid),
  +    ?RECV({'DOWN', MRef, process, _, _});
  +
  +reconnect(_) ->
  +    Ref = make_ref(),
  +    [] = ?util:run([{?MODULE, [reconnect, {T, Ref}]}
  +                    || T <- [listen, connect]]).
  +
  +start_service(SvcName) ->
  +    OH = io_lib:format("~p-~p-~p", tuple_to_list(now())),
  +    Opts = [{application, [{dictionary, diameter_gen_base_rfc6733},
  +                           {module, diameter_callback}]},
  +            {'Origin-Host', OH},
  +            {'Origin-Realm', OH ++ ".org"},
  +            {'Vendor-Id', 0},
  +            {'Product-Name', "x"},
  +            {'Auth-Application-Id', [0]}],
  +    diameter:start_service(SvcName, Opts).
  +
  +abort(SvcName, Pid, Ref)
  +  when is_pid(Pid) ->
  +    receive
  +        #diameter_event{service = SvcName, info = {reconnect, _, _}} = E ->
  +            erlang:error(E)
  +    after 45000 ->
  +            ok
  +    end,
  +    Pid ! {abort, Ref};
  +
  +abort(SvcName, LRef, Ref)
  +  when is_reference(LRef) ->
  +    ?RECV({abort, Ref}),
  +    [[{ref, LRef}, {type, listen}, {options, _}, {accept, [_,_] = Ts} | _]]
  +                                                 %% assert on two accepting
  +        = diameter:service_info(SvcName, transport),
  +    [TPid] = [P || [{watchdog, {_,_,okay}}, {peer, {P,_}} | _] <- Ts],
  +    TPid.
   
   %% ===========================================================================
   %% ===========================================================================
  
positive.code: %%
  %% %CopyrightBegin%
  %%
  %% Copyright Ericsson AB 2010-2011. All Rights Reserved.
  %%
  %% The contents of this file are subject to the Erlang Public License,
  %% Version 1.1, (the "License"); you may not use this file except in
  
negative.code:     [tcp_accept,
       tcp_connect,
       sctp_accept,
       sctp_connect,
       reconnect].
  
  init_per_suite(Config) ->
      [{sctp, have_sctp()} | Config].
  