|
20 | 20 | cb_ret/0,
|
21 | 21 | cb_state/0
|
22 | 22 | ]).
|
| 23 | + |
23 | 24 | -type cb_ret() :: cb_ret_noreply() | cb_ret_reply().
|
24 | 25 | -type cb_state() :: term().
|
25 | 26 |
|
|
43 | 44 |
|
44 | 45 | -export([
|
45 | 46 | default_cb_ret/2,
|
46 |
| - handle_dgram_send_states/1 |
| 47 | + handle_dgram_send_states/1, |
| 48 | + handle_dgram_send_states/3, |
| 49 | + probe/2 |
47 | 50 | ]).
|
48 | 51 |
|
49 | 52 | -spec default_cb_ret(cb_ret(), State :: term()) ->
|
@@ -73,42 +76,86 @@ default_cb_ret({reply, Reply, NewCBState, Action}, State) ->
|
73 | 76 | default_cb_ret({reply, Reply, NewCBState}, State) ->
|
74 | 77 | {reply, Reply, State#{callback_state := NewCBState}}.
|
75 | 78 |
|
| 79 | +-spec probe(connection_handle(), timeout()) -> probe_res(). |
| 80 | +probe(Conn, Timeout) -> |
| 81 | + case quicer_nif:send_dgram(Conn, <<>>, _IsSync = 1) of |
| 82 | + {ok, _Len} -> |
| 83 | + handle_dgram_send_states(Conn, probe_dgram_send_cb(), Timeout); |
| 84 | + {error, E} -> |
| 85 | + {error, dgram_send_error, E}; |
| 86 | + E -> |
| 87 | + E |
| 88 | + end. |
| 89 | + |
76 | 90 | -spec handle_dgram_send_states(connection_handle()) ->
|
77 | 91 | ok
|
78 | 92 | | {error,
|
79 | 93 | dgram_send_canceled
|
80 | 94 | | dgram_send_unknown
|
81 | 95 | | dgram_send_lost_discarded}.
|
82 | 96 | handle_dgram_send_states(Conn) ->
|
83 |
| - handle_dgram_send_states(init, Conn). |
84 |
| -handle_dgram_send_states(init, Conn) -> |
| 97 | + handle_dgram_send_states(init, Conn, default_dgram_suspect_lost_cb(), 5000). |
| 98 | + |
| 99 | +-type lost_suspect_callback() :: |
| 100 | + {fun((connection_handle(), term(), term()) -> term()), term()} |
| 101 | + | {atom(), term()}. |
| 102 | +-spec handle_dgram_send_states(connection_handle(), lost_suspect_callback(), timeout()) -> any(). |
| 103 | +handle_dgram_send_states(Conn, {_CBFun, _CBState} = CB, Timeout) -> |
| 104 | + handle_dgram_send_states(init, Conn, CB, Timeout). |
| 105 | + |
| 106 | +handle_dgram_send_states(init, Conn, {Fun, CallbackState}, Timeout) -> |
85 | 107 | receive
|
86 | 108 | {quic, dgram_send_state, Conn, #{state := ?QUIC_DATAGRAM_SEND_SENT}} ->
|
87 |
| - handle_dgram_send_states(sent, Conn); |
88 |
| - {quic, dgram_send_state, Conn, #{state := ?QUIC_DATAGRAM_SEND_ACKNOWLEDGED}} -> |
89 |
| - %% @TODO unsure if it will hit here |
90 |
| - ok; |
91 |
| - {quic, dgram_send_state, Conn, #{state := E}} -> |
92 |
| - {error, E} |
| 109 | + NewCBState = Fun(Conn, ?QUIC_DATAGRAM_SEND_SENT, CallbackState), |
| 110 | + handle_dgram_send_states(sent, Conn, {Fun, NewCBState}, Timeout); |
| 111 | + {quic, dgram_send_state, Conn, #{state := Final}} -> |
| 112 | + Fun(Conn, Final, CallbackState) |
| 113 | + after 5000 -> |
| 114 | + Fun(Conn, timeout, CallbackState) |
93 | 115 | end;
|
94 |
| -handle_dgram_send_states(sent, Conn) -> |
| 116 | +handle_dgram_send_states(sent, Conn, {Fun, CallbackState}, Timeout) -> |
95 | 117 | receive
|
96 |
| - {quic, dgram_send_state, Conn, #{state := ?QUIC_DATAGRAM_SEND_ACKNOWLEDGED}} -> |
97 |
| - %% Happy Track |
98 |
| - ok; |
| 118 | + %% {quic, dgram_send_state, Conn, #{state := ?QUIC_DATAGRAM_SEND_ACKNOWLEDGED}} -> |
| 119 | + %% %% Happy Track |
| 120 | + %% Fun(Conn, ?QUIC_DATAGRAM_SEND_ACKNOWLEDGED, CallbackState); |
99 | 121 | {quic, dgram_send_state, Conn, #{state := ?QUIC_DATAGRAM_SEND_LOST_SUSPECT}} ->
|
100 |
| - %% Lost suspected |
| 122 | + %% Lost suspected, call the callback for the return hits. |
| 123 | + %% however, we still need to wait for the final state. |
| 124 | + NewCBState = Fun(Conn, ?QUIC_DATAGRAM_SEND_LOST_SUSPECT, CallbackState), |
101 | 125 | receive
|
102 |
| - {quic, dgram_send_state, Conn, #{ |
103 |
| - state := ?QUIC_DATAGRAM_SEND_ACKNOWLEDGED_SPURIOUS |
104 |
| - }} -> |
105 |
| - %% Lost recovered |
106 |
| - ok; |
107 | 126 | {quic, dgram_send_state, Conn, #{state := EState}} ->
|
108 |
| - %% Unrecoverable Errors. |
109 |
| - {error, EState} |
| 127 | + Fun(Conn, EState, NewCBState) |
| 128 | + after Timeout -> |
| 129 | + Fun(Conn, timeout, CallbackState) |
110 | 130 | end;
|
111 |
| - {quic, dgram_send_state, Conn, #{state := EState}} -> |
| 131 | + {quic, dgram_send_state, Conn, #{state := Final}} -> |
112 | 132 | %% Unrecoverable Errors.
|
113 |
| - {error, EState} |
| 133 | + Fun(Conn, Final, CallbackState) |
| 134 | + after Timeout -> |
| 135 | + Fun(Conn, timeout, CallbackState) |
114 | 136 | end.
|
| 137 | + |
| 138 | +%% Default Callback for Datagram Send lost suspected |
| 139 | +default_dgram_suspect_lost_cb() -> |
| 140 | + Fun = fun(_Conn, _, _CallbackState) -> |
| 141 | + %% just return ok, even it is lost, we don't care. |
| 142 | + ok |
| 143 | + end, |
| 144 | + {Fun, undefined}. |
| 145 | + |
| 146 | +probe_dgram_send_cb() -> |
| 147 | + Fun = fun |
| 148 | + (_Conn, ?QUIC_DATAGRAM_SEND_SENT, CallbackState) -> |
| 149 | + CallbackState#probe_state{sent_at = ts_ms()}; |
| 150 | + (_Conn, ?QUIC_DATAGRAM_SEND_LOST_SUSPECT, CallbackState) -> |
| 151 | + CallbackState#probe_state{suspect_lost_at = ts_ms()}; |
| 152 | + (_Conn, State, CallbackState) -> |
| 153 | + CallbackState#probe_state{ |
| 154 | + final_at = ts_ms(), |
| 155 | + final = State |
| 156 | + } |
| 157 | + end, |
| 158 | + {Fun, #probe_state{}}. |
| 159 | + |
| 160 | +ts_ms() -> |
| 161 | + erlang:monotonic_time(millisecond). |
0 commit comments