anchor.diff:      [tcp_accept,
        tcp_connect,
        sctp_accept,
  -     sctp_connect].
  +     sctp_connect,
  +     reconnect].
   
   init_per_suite(Config) ->
       [{sctp, have_sctp()} | Config].
  
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: 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.
  
  %% ===========================================================================
  %% ===========================================================================
  