Repository: mitmproxy/mitmproxy

Issue:
"ValueError: math domain error" in table mode when displaying a server replay flow
#### Problem Description
`mitmproxy` crashes when it tries to display a replayed flows in a table mode.
With active server replay, flow's duration is negative, so `math.log2` receives a negative value which is illegal.

Traceback:
```
  File "mitmproxy/master.py", line 86, in run_loop
  File "site-packages/urwid/main_loop.py", line 286, in run
  File "site-packages/urwid/main_loop.py", line 384, in _run
  File "site-packages/urwid/main_loop.py", line 1484, in run
  File "site-packages/urwid/compat.py", line 58, in reraise
  File "asyncio/events.py", line 88, in _run
  File "site-packages/urwid/main_loop.py", line 1443, in faux_idle_callback
  File "site-packages/urwid/main_loop.py", line 572, in entering_idle
  File "site-packages/urwid/main_loop.py", line 586, in draw_screen
  File "site-packages/urwid/widget.py", line 144, in cached_render
  File "site-packages/urwid/container.py", line 1086, in render
  File "site-packages/urwid/widget.py", line 144, in cached_render
  File "site-packages/urwid/decoration.py", line 226, in render
  File "site-packages/urwid/widget.py", line 144, in cached_render
  File "site-packages/urwid/container.py", line 1086, in render
  File "site-packages/urwid/widget.py", line 144, in cached_render
  File "site-packages/urwid/listbox.py", line 471, in render
  File "site-packages/urwid/listbox.py", line 356, in calculate_visible
  File "mitmproxy/tools/console/flowlist.py", line 57, in get_focus
  File "mitmproxy/tools/console/flowlist.py", line 12, in __init__
  File "mitmproxy/tools/console/flowlist.py", line 22, in get_text
  File "mitmproxy/tools/console/common.py", line 561, in format_flow
  File "mitmproxy/tools/console/common.py", line 488, in raw_format_table
ValueError: math domain error
```

#### Steps to reproduce the behavior:
1. Start `mitmproxy` with table layout active
2. Make an HTTP call
3. Add the call to server replay
4. Make the call again

#### System Information
```
Mitmproxy: 5.0.1 binary
Python:    3.7.5
OpenSSL:   OpenSSL 1.1.0j  20 Nov 2018
Platform:  Linux-5.0.0-38-generic-x86_64-with-debian-buster-sid
```



Discussion:
Should we set it to 0, whenever `f.response.timestamp_end < f.request.timestamp_start` ? 
The number will be incorrect, but it won't crash anymore.
> Should we set it to 0, whenever f.response.timestamp_end < f.request.timestamp_start ?

It is an option, because seeing times like `-321075ms` is kind of misleading.

Another one is just take maximum of 0 and flow's duration, because the problem code is used for getting color.
I would be fine with either setting this to 0 in the console code or with refreshing the `timestamp_` attributes in the server playback addons. PRs welcome! 😃 

Resolving patch:
diff --git a/mitmproxy/tools/console/common.py b/mitmproxy/tools/console/common.py
--- a/mitmproxy/tools/console/common.py
+++ b/mitmproxy/tools/console/common.py
@@ -543,7 +543,7 @@ def format_flow(f, focus, extended=False, hostheader=False, cols=False, layout='
 
         duration = None
         if f.response.timestamp_end and f.request.timestamp_start:
-            duration = f.response.timestamp_end - f.request.timestamp_start
+            duration = max([f.response.timestamp_end - f.request.timestamp_start, 0])
 
         d.update(dict(
             resp_code=f.response.status_code,


Test patch: