anchor.diff:  	    ok
       end.
   
  +%% part of cancel_timer/2
   del_ref(_Ref, []) ->
       [];
   del_ref(Ref, [H | T]) when is_record(H, siptimer), H#siptimer.ref == Ref ->
  
positive.code: %%%-------------------------------------------------------------------
  %%% File     : siptimer.erl
  %%% Author   : Fredrik <ft@it.su.se>
  %%% Descrip. : Module to manage timers, for use in client and server
  %%%            transactions. Make it easier to cancel timers and
  %%%            revive them when we get provisional responses etc.
  
negative.code: get_timer2(Ref, [H | T]) when is_record(H, siptimer) ->
      get_timer2(Ref, T).
  
  %%--------------------------------------------------------------------
  %% Function: get_timers_appsignal_matching(AppSignal, TimerList)
  %%           AppSignal  = term()
  %%           TimerList  = siptimerlist record()
  %% Descrip.: Locate all timers in TimerList which have their
  %%           'appsignal' element matching AppSignal.
  %% Returns : list() of siptimer record()
  %%--------------------------------------------------------------------
  get_timers_appsignal_matching(AppSignal, TimerList) when is_record(TimerList, siptimerlist) ->
      get_timers_appsignal_matching2(AppSignal, TimerList#siptimerlist.list, []).
  
  get_timers_appsignal_matching2(Value, [#siptimer{appsignal = Value}=H | T], Res) ->
      get_timers_appsignal_matching2(Value, T, [H | Res]);
  get_timers_appsignal_matching2(Value, [H | T], Res) when is_record(H, siptimer) ->
      get_timers_appsignal_matching2(Value, T, Res);
  get_timers_appsignal_matching2(_Value, [], Res) ->
      lists:reverse(Res).
  
  
  %%--------------------------------------------------------------------
  %% Function: extract(Values, SipTimer)
  %%           Values = list() of atom(), ref | timeout | description |
  %%                    starttime | appsignal
  %%           TimerList  = siptimerlist record()
  %% Descrip.: Extract elements from a siptimer record().
  %% Returns : list() of term()
  %%--------------------------------------------------------------------
  extract(Values, SipTimer) when is_record(SipTimer, siptimer) ->
      extract(Values, SipTimer, []).
  
  extract([], SipTimer, Res) when is_record(SipTimer, siptimer) ->
      lists:reverse(Res);
  extract([ref | T], SipTimer, Res) when is_record(SipTimer, siptimer) ->
      extract(T, SipTimer, [SipTimer#siptimer.ref | Res]);
  extract([timeout | T], SipTimer, Res) when is_record(SipTimer, siptimer) ->
      extract(T, SipTimer, [SipTimer#siptimer.timeout | Res]);
  extract([description | T], SipTimer, Res) when is_record(SipTimer, siptimer) ->
      extract(T, SipTimer, [SipTimer#siptimer.description | Res]);
  extract([starttime | T], SipTimer, Res) when is_record(SipTimer, siptimer) ->
      extract(T, SipTimer, [SipTimer#siptimer.starttime | Res]);
  extract([appsignal | T], SipTimer, Res) when is_record(SipTimer, siptimer) ->
      extract(T, SipTimer, [SipTimer#siptimer.appsignal | Res]).
  
  %%--------------------------------------------------------------------
  %% Function: cancel_timers(Timers, TimerList)
  %%           Timers    = list() of siptimer record()
  %%           TimerList = siptimerlist record() | none
  %% Descrip.: Cancel a siptimer, return a new TimerList without the
  %%           cancelled siptimer.
  %% Returns : NewTimerList = siptimerlist record()
  %%--------------------------------------------------------------------
  cancel_timers([H | T], TimerList) when is_record(H, siptimer), is_record(TimerList, siptimerlist) ->
      Timer = H#siptimer.timer,
      Ref = H#siptimer.ref,
      Descr = H#siptimer.description,
      logger:log(debug, "Siptimer: Cancelling timer ~p:~p", [Ref, Descr]),
      case timer:cancel(Timer) of
  	{ok, cancel} -> ok;
  	{error, Reason} ->
  	    logger:log(error, "Siptimer: Warning: Cancel timer ~p:~p failed : ~p",
  		       [Ref, Descr, Reason])
      end,
      remove_queued_result({siptimer, Ref, Descr}),
      NewTimerList = make_siptimerlist( del_ref(Ref, TimerList#siptimerlist.list) ),
      cancel_timers(T, NewTimerList);
  cancel_timers([], TimerList) when is_record(TimerList, siptimerlist) ->
      TimerList.
  
  %%--------------------------------------------------------------------
  %% Function: cancel_all_timers(TimerList)
  %%           TimerList = siptimerlist record() | none
  %% Descrip.: Cancel all siptimers in TimerList.
  %% Returns : EmptyList = siptimerlist record()
  %%--------------------------------------------------------------------
  cancel_all_timers(TimerList) when is_record(TimerList, siptimerlist) ->
      EmptyList = empty(),
      logger:log(debug, "Siptimer: Cancelling all timers :"),
      cancel_timers(TimerList#siptimerlist.list, EmptyList),
      EmptyList.
  
  %%--------------------------------------------------------------------
  %% Function: cancel_timers_with_appsignal(AppSignal, TimerList)
  %%           AppSignal = term(), appsignal to match on
  %%           TimerList = siptimerlist record() | none
  %% Descrip.: Cancel all siptimers in TimerList that has an appsignal
  %%           matching AppSignal.
  %% Returns : NewTimerList = siptimerlist record()
  %%--------------------------------------------------------------------
  cancel_timers_with_appsignal(AppSignal, TimerList) when is_record(TimerList, siptimerlist) ->
      case get_timers_appsignal_matching(AppSignal, TimerList) of
  	[] ->
  	    %%    logger:log(debug, "Siptimer: No timers with AppSignal ~p found in TimerList :~n~p",
  	    %%	       [AppSignal, debugfriendly(TimerList)]),
  	    TimerList;
  	CancelTimers when is_list(CancelTimers) ->
  	    logger:log(debug, "Siptimer: Cancelling all timers with AppSignal ~p :", [AppSignal]),
  	    cancel_timers(CancelTimers, TimerList)
      end.
  
  debugfriendly(TimerList) when is_record(TimerList, siptimerlist) ->
      debugfriendly2(TimerList#siptimerlist.list, []).
  
  debugfriendly2([H | T], Res) when is_record(H, siptimer) ->
      RefStr = io_lib:format("~p", [H#siptimer.ref]),
      Descr = H#siptimer.description,
      SignalStr = io_lib:format("~p", [H#siptimer.appsignal]),
      Str = lists:concat([RefStr, ":", Descr, " -> ", SignalStr]),
      debugfriendly2(T, [Str | Res]);
  debugfriendly2([], Res) ->
      lists:reverse(Res).
  
  %%--------------------------------------------------------------------
  %% Function: timeout2str(Timeout)
  %%           Timeout = integer(), milliseconds
  %% Descrip.: Give string second representation of Timeout.
  %% Returns : TStr = string()
  %%--------------------------------------------------------------------
  timeout2str(500) ->
      "0.5";
  timeout2str(Timeout) ->
      integer_to_list(Timeout div 1000).
  
  %%--------------------------------------------------------------------
  %% Function: get_length(TimerList)
  %%           TimerList = siptimerlist record()
  %% Descrip.: Return the length of the list of siptimers contained in
  %%           the siptimerlist record().
  %% Returns : Len = integer()
  %%--------------------------------------------------------------------
  get_length(TimerList) when is_record(TimerList, siptimerlist) ->
      length(TimerList#siptimerlist.list).
  
  
  %%====================================================================
  %% Internal functions
  %%====================================================================
  
  make_siptimerlist([]) ->
      #siptimerlist{list=[]};
  make_siptimerlist(In) ->
      #siptimerlist{list=make_siptimerlist2(In, [])}.
  
  %% make_siptimerlist2/2 - part of make_siptimerlist/1.
  %% Make sure all elements are siptimer record().
  %% Returns : list() of siptimer record()
  make_siptimerlist2([H | T], Res) when is_record(H, siptimer) ->
      make_siptimerlist2(T, [H | Res]);
  make_siptimerlist2([], Res) ->
      lists:reverse(Res).
  
  %% Receive all messages matching Signal from this processes mailbox. When there
  %% are no more signals matching Signal, return ok. This is to remove any signals
  