anchor.diff:                       data = [] :: [{RSN::non_neg_integer(),
                                       TS::non_neg_integer(),
                                       Data::binary()}],
  -                     state = closed :: 'closed' | 'established' | 'error'
  +                     state = closed :: 'closed' | 'established' |
  +                                       'error' | 'finished'
                       }).
   
   -spec init(TS::non_neg_integer(), #tcp{}) -> #tcp_stream{}.
   init(TS, #tcp{syn=true, seq_no=ISN, data= D}) ->
       #tcp_stream{isn=ISN, start_time=TS,
                   data = [{0, TS, D}],
  -                state = established}.
  +                state = established};
  +init(_TS, #tcp{}) ->
  +    #tcp_stream{state = error}.
   
  -update(TS, Pkt = #tcp{seq_no = S, data = Data},
  +
  +update(TS, Pkt = #tcp{seq_no = S, data = Data, ack = true},
          S0 = #tcp_stream{isn=ISN,
                           data=Acc, state=established}) ->
       RelativeSN = S - ISN,
  
positive.code:             I =< Idx,
              Idx =< J ].
  
  %%====================================================================
  %% Internal functions
  %%====================================================================
  
negative.code: relative_time(TS, #tcp_stream{start_time=T0}) ->
      TS - T0.
  
  -spec analyze(Module::atom(), #tcp_stream{}) ->
                       {'error', 'broken_stream'} |
                       {[{Message::term(),
                          {StartIdx::non_neg_integer(),
                           StopIdx::non_neg_integer()},
                          {StartTime::non_neg_integer(),
                           Duration::non_neg_integer()}}],
                        Oddballs::[{Timestamp::non_neg_integer(),
                                    'retransmit' | 'missing_packet'}]}.
  analyze(_, #tcp_stream{state=error}) ->
      {error, broken_stream};
  analyze(Module, #tcp_stream{} = S) ->
      Stream = {_, Offsets} = reassemble(S),
      {analyze_timings(Module, Stream, 0),
       oddballs(Offsets)}.
  
  analyze_timings(Module, {Stream, Offsets}, Idx) when Idx < byte_size(Stream) ->
      <<_:Idx/binary, Buf/binary>> = Stream,
      case Module:decode(Buf) of
          {complete, Term, Rest} ->
              NewIdx = byte_size(Stream) - byte_size(Rest),
              IdxRange = {Idx, NewIdx - 1},
              [{Term, IdxRange, analyze_timing(IdxRange, Offsets)}
               | analyze_timings(Module, {Stream, Offsets}, NewIdx)];
          {partial, _BytesNeeded} ->
              IdxRange = {Idx, byte_size(Stream)},
              [{partial, IdxRange, analyze_timing(IdxRange, Offsets)}]
      end;
  analyze_timings(_, _, _) -> [].
  
  analyze_timing({StartIdx, StopIdx}, Offsets) ->
      StartTS = lists:min(ts_range(StartIdx, Offsets)),
  