diff --git a/c_src/quicer_connection.c b/c_src/quicer_connection.c index ca4d05e3..67353648 100644 --- a/c_src/quicer_connection.c +++ b/c_src/quicer_connection.c @@ -15,6 +15,7 @@ limitations under the License. -------------------------------------------------------------------*/ #include "quicer_connection.h" #include "quicer_ctx.h" +#include "quicer_dgram.h" #include "quicer_tls.h" #include #include @@ -26,15 +27,6 @@ EncodeHexBuffer(uint8_t *Buffer, uint8_t BufferLen, char *HexString); extern inline const char *QuicStatusToString(QUIC_STATUS Status); -static void handle_dgram_state_event(QuicerConnCTX *c_ctx, - QUIC_CONNECTION_EVENT *Event); - -static void handle_dgram_send_state_event(QuicerConnCTX *c_ctx, - QUIC_CONNECTION_EVENT *Event); - -static void handle_dgram_recv_event(QuicerConnCTX *c_ctx, - QUIC_CONNECTION_EVENT *Event); - static QUIC_STATUS handle_connection_event_connected(QuicerConnCTX *c_ctx, QUIC_CONNECTION_EVENT *Event); @@ -1039,60 +1031,6 @@ async_handshake_1(ErlNifEnv *env, return res; } -void -handle_dgram_state_event(QuicerConnCTX *c_ctx, QUIC_CONNECTION_EVENT *Event) -{ - if (Event->DATAGRAM_STATE_CHANGED.SendEnabled == 1) - { - ErlNifEnv *env = c_ctx->env; - int max_len = Event->DATAGRAM_STATE_CHANGED.MaxSendLength; - enif_send(NULL, - &(c_ctx->owner->Pid), - NULL, - enif_make_tuple3(env, - ATOM_QUIC, - ATOM_DGRAM_MAX_LEN, - enif_make_int(env, max_len))); - } -} - -void -handle_dgram_send_state_event(QuicerConnCTX *c_ctx, - QUIC_CONNECTION_EVENT *Event) -{ - ErlNifEnv *env = c_ctx->env; - if (Event->DATAGRAM_SEND_STATE_CHANGED.State == QUIC_DATAGRAM_SEND_SENT) - { - QuicerDgramSendCTX *dgram_send_ctx - = (QuicerDgramSendCTX *)(Event->DATAGRAM_SEND_STATE_CHANGED - .ClientContext); - enif_send(NULL, - &dgram_send_ctx->caller, - NULL, - enif_make_tuple3(env, - ATOM_QUIC, - ATOM_SEND_DGRAM_COMPLETE, - enif_make_resource(env, c_ctx))); - destroy_dgram_send_ctx(dgram_send_ctx); - } -} - -void -handle_dgram_recv_event(QuicerConnCTX *c_ctx, QUIC_CONNECTION_EVENT *Event) -{ - ErlNifEnv *env = c_ctx->env; - ErlNifBinary bin; - ERL_NIF_TERM report; - enif_alloc_binary(Event->DATAGRAM_RECEIVED.Buffer->Length, &bin); - CxPlatCopyMemory(bin.data, - Event->DATAGRAM_RECEIVED.Buffer->Buffer, - Event->DATAGRAM_RECEIVED.Buffer->Length); - bin.size = Event->DATAGRAM_RECEIVED.Buffer->Length; - report = enif_make_tuple3( - env, ATOM_QUIC, ATOM_DGRAM, enif_make_binary(env, &bin)); - enif_send(NULL, &(c_ctx->owner->Pid), NULL, report); -} - /* handle conn connected event and deliver the message to the conn owner {quic, connected, connection_handle(), #{ is_resumed := boolean() , alpns = binary() | undefined @@ -1412,8 +1350,7 @@ static QUIC_STATUS handle_connection_event_datagram_state_changed(QuicerConnCTX *c_ctx, QUIC_CONNECTION_EVENT *Event) { - assert(QUIC_CONNECTION_EVENT_DATAGRAM_STATE_CHANGED == Event->Type); - handle_dgram_state_event(c_ctx, Event); + handle_dgram_state_changed_event(c_ctx, Event); return QUIC_STATUS_SUCCESS; } diff --git a/c_src/quicer_dgram.c b/c_src/quicer_dgram.c index 7450400c..f039b515 100644 --- a/c_src/quicer_dgram.c +++ b/c_src/quicer_dgram.c @@ -16,6 +16,8 @@ limitations under the License. #include "quicer_dgram.h" +static ERL_NIF_TERM atom_dgram_send_state(uint16_t state); + ERL_NIF_TERM send_dgram(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) { @@ -100,3 +102,117 @@ send_dgram(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) return SUCCESS(ETERM_UINT_64(bin->size)); } } + +void +handle_dgram_state_changed_event(QuicerConnCTX *c_ctx, + QUIC_CONNECTION_EVENT *Event) +{ + assert(QUIC_CONNECTION_EVENT_DATAGRAM_STATE_CHANGED == Event->Type); + ErlNifEnv *env = c_ctx->env; + uint16_t max_len = Event->DATAGRAM_STATE_CHANGED.MaxSendLength; + + ERL_NIF_TERM ConnHandle = enif_make_resource(c_ctx->env, c_ctx); + ERL_NIF_TERM props_name[] = { ATOM_DGRAM_MAX_LEN, ATOM_DGRAM_SEND_ENABLED }; + ERL_NIF_TERM props_value[] + = { enif_make_uint(env, max_len), + ATOM_BOOLEAN(Event->DATAGRAM_STATE_CHANGED.SendEnabled) }; + + ERL_NIF_TERM report = make_event_with_props(c_ctx->env, + ATOM_DGRAM_STATE_CHANGED, + ConnHandle, + props_name, + props_value, + 2); + + enif_send(NULL, &(c_ctx->owner->Pid), NULL, report); +} + +void +handle_dgram_send_state_event(QuicerConnCTX *c_ctx, + QUIC_CONNECTION_EVENT *Event) +{ + assert(QUIC_CONNECTION_EVENT_DATAGRAM_SEND_STATE_CHANGED == Event->Type); + // result of previous unreliable datagram send + QUIC_DATAGRAM_SEND_STATE state = Event->DATAGRAM_SEND_STATE_CHANGED.State; + QuicerDgramSendCTX *dgram_send_ctx + = (QuicerDgramSendCTX *)(Event->DATAGRAM_SEND_STATE_CHANGED + .ClientContext); + + ERL_NIF_TERM ConnHandle = enif_make_resource(c_ctx->env, c_ctx); + ERL_NIF_TERM props_name[] = { ATOM_STATE }; + ERL_NIF_TERM props_value[] = { atom_dgram_send_state(state) }; + ERL_NIF_TERM report = make_event_with_props(c_ctx->env, + ATOM_DGRAM_SEND_STATE, + ConnHandle, + props_name, + props_value, + 1); + enif_send(NULL, &dgram_send_ctx->caller, NULL, report); + + if (QUIC_DATAGRAM_SEND_LOST_DISCARDED == state + || QUIC_DATAGRAM_SEND_ACKNOWLEDGED == state + || QUIC_DATAGRAM_SEND_ACKNOWLEDGED_SPURIOUS == state + || QUIC_DATAGRAM_SEND_CANCELED == state) + { + // Destroy only when in final state + destroy_dgram_send_ctx(dgram_send_ctx); + } +} + +void +handle_dgram_recv_event(QuicerConnCTX *c_ctx, QUIC_CONNECTION_EVENT *Event) +{ + ErlNifEnv *env = c_ctx->env; + ERL_NIF_TERM bin; + ERL_NIF_TERM report; + + size_t len = Event->DATAGRAM_RECEIVED.Buffer->Length; + unsigned char *buff = enif_make_new_binary(env, len, &bin); + if (buff) + { + CxPlatCopyMemory(buff, Event->DATAGRAM_RECEIVED.Buffer->Buffer, len); + + ERL_NIF_TERM ConnHandle = enif_make_resource(c_ctx->env, c_ctx); + report = enif_make_tuple4( + env, + ATOM_QUIC, + bin, + ConnHandle, + enif_make_uint(env, Event->DATAGRAM_RECEIVED.Flags)); + enif_send(NULL, &c_ctx->owner->Pid, NULL, report); + } +} + +ERL_NIF_TERM +atom_dgram_send_state(uint16_t state) +{ + ERL_NIF_TERM ret = ATOM_UNDEFINED; + switch (state) + { + case QUIC_DATAGRAM_SEND_UNKNOWN: + ret = ATOM_QUIC_DATAGRAM_SEND_UNKNOWN; + break; + case QUIC_DATAGRAM_SEND_SENT: + ret = ATOM_QUIC_DATAGRAM_SEND_SENT; + break; + case QUIC_DATAGRAM_SEND_LOST_SUSPECT: + ret = ATOM_QUIC_DATAGRAM_SEND_LOST_SUSPECT; + break; + case QUIC_DATAGRAM_SEND_LOST_DISCARDED: + ret = ATOM_QUIC_DATAGRAM_SEND_LOST_DISCARDED; + break; + case QUIC_DATAGRAM_SEND_ACKNOWLEDGED: + ret = ATOM_QUIC_DATAGRAM_SEND_ACKNOWLEDGED; + break; + case QUIC_DATAGRAM_SEND_ACKNOWLEDGED_SPURIOUS: + ret = ATOM_QUIC_DATAGRAM_SEND_ACKNOWLEDGED_SPURIOUS; + break; + case QUIC_DATAGRAM_SEND_CANCELED: + ret = ATOM_QUIC_DATAGRAM_SEND_CANCELED; + break; + default: + ret = ATOM_UNDEFINED; + break; + } + return ret; +} diff --git a/c_src/quicer_dgram.h b/c_src/quicer_dgram.h index 6eee1d38..dabb50d5 100644 --- a/c_src/quicer_dgram.h +++ b/c_src/quicer_dgram.h @@ -21,4 +21,12 @@ limitations under the License. ERL_NIF_TERM send_dgram(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]); -#endif // __QUICER_DGRAM_H_ \ No newline at end of file +void handle_dgram_send_state_event(QuicerConnCTX *c_ctx, + QUIC_CONNECTION_EVENT *Event); +void handle_dgram_state_changed_event(QuicerConnCTX *c_ctx, + QUIC_CONNECTION_EVENT *Event); + +void handle_dgram_recv_event(QuicerConnCTX *c_ctx, + QUIC_CONNECTION_EVENT *Event); + +#endif // __QUICER_DGRAM_H_ diff --git a/c_src/quicer_eterms.h b/c_src/quicer_eterms.h index d925d0bd..d0839657 100644 --- a/c_src/quicer_eterms.h +++ b/c_src/quicer_eterms.h @@ -304,11 +304,14 @@ extern ERL_NIF_TERM ATOM_STREAMS_AVAILABLE; extern ERL_NIF_TERM ATOM_PEER_NEEDS_STREAMS; extern ERL_NIF_TERM ATOM_START_COMPLETE; extern ERL_NIF_TERM ATOM_SEND_COMPLETE; +extern ERL_NIF_TERM ATOM_DGRAM_SEND_STATE; extern ERL_NIF_TERM ATOM_SEND_DGRAM_COMPLETE; extern ERL_NIF_TERM ATOM_EINVAL; extern ERL_NIF_TERM ATOM_QUIC; extern ERL_NIF_TERM ATOM_DGRAM; +extern ERL_NIF_TERM ATOM_DGRAM_STATE_CHANGED; extern ERL_NIF_TERM ATOM_DGRAM_MAX_LEN; +extern ERL_NIF_TERM ATOM_DGRAM_SEND_ENABLED; extern ERL_NIF_TERM ATOM_PASSIVE; extern ERL_NIF_TERM ATOM_QUIC_EVENT_MASK; extern ERL_NIF_TERM ATOM_NST_RECEIVED; @@ -362,6 +365,7 @@ extern ERL_NIF_TERM ATOM_IS_ORPHAN; extern ERL_NIF_TERM ATOM_BIDI_STREAMS; extern ERL_NIF_TERM ATOM_UNIDI_STREAMS; extern ERL_NIF_TERM ATOM_STATUS; +extern ERL_NIF_TERM ATOM_STATE; extern ERL_NIF_TERM ATOM_STREAM_ID; extern ERL_NIF_TERM ATOM_IS_PEER_ACCEPTED; extern ERL_NIF_TERM ATOM_IS_CONN_SHUTDOWN; @@ -376,6 +380,16 @@ extern ERL_NIF_TERM ATOM_CLIENT_ALPNS; extern ERL_NIF_TERM ATOM_CRYPTO_BUFFER; extern ERL_NIF_TERM ATOM_UNDEFINED; + +// Datagram Send State +extern ERL_NIF_TERM ATOM_QUIC_DATAGRAM_SEND_UNKNOWN; +extern ERL_NIF_TERM ATOM_QUIC_DATAGRAM_SEND_SENT; +extern ERL_NIF_TERM ATOM_QUIC_DATAGRAM_SEND_LOST_SUSPECT; +extern ERL_NIF_TERM ATOM_QUIC_DATAGRAM_SEND_LOST_DISCARDED; +extern ERL_NIF_TERM ATOM_QUIC_DATAGRAM_SEND_ACKNOWLEDGED; +extern ERL_NIF_TERM ATOM_QUIC_DATAGRAM_SEND_ACKNOWLEDGED_SPURIOUS; +extern ERL_NIF_TERM ATOM_QUIC_DATAGRAM_SEND_CANCELED; + /*----------------------------------------------------------*/ /* ATOMS ends here */ /*----------------------------------------------------------*/ diff --git a/c_src/quicer_nif.c b/c_src/quicer_nif.c index 594b60f8..1f32d068 100644 --- a/c_src/quicer_nif.c +++ b/c_src/quicer_nif.c @@ -321,6 +321,7 @@ ERL_NIF_TERM ATOM_STREAMS_AVAILABLE; ERL_NIF_TERM ATOM_PEER_NEEDS_STREAMS; ERL_NIF_TERM ATOM_START_COMPLETE; ERL_NIF_TERM ATOM_SEND_COMPLETE; +ERL_NIF_TERM ATOM_DGRAM_SEND_STATE; ERL_NIF_TERM ATOM_SEND_DGRAM_COMPLETE; ERL_NIF_TERM ATOM_EINVAL; ERL_NIF_TERM ATOM_QUIC; @@ -329,7 +330,9 @@ ERL_NIF_TERM ATOM_QUIC_EVENT_MASK; ERL_NIF_TERM ATOM_NST_RECEIVED; ERL_NIF_TERM ATOM_NST; ERL_NIF_TERM ATOM_DGRAM; +ERL_NIF_TERM ATOM_DGRAM_STATE_CHANGED; ERL_NIF_TERM ATOM_DGRAM_MAX_LEN; +ERL_NIF_TERM ATOM_DGRAM_SEND_ENABLED; ERL_NIF_TERM ATOM_DEBUG; ERL_NIF_TERM ATOM_ONCE; ERL_NIF_TERM ATOM_NEW_CONN; @@ -379,6 +382,7 @@ ERL_NIF_TERM ATOM_IS_ORPHAN; ERL_NIF_TERM ATOM_BIDI_STREAMS; ERL_NIF_TERM ATOM_UNIDI_STREAMS; ERL_NIF_TERM ATOM_STATUS; +ERL_NIF_TERM ATOM_STATE; ERL_NIF_TERM ATOM_STREAM_ID; ERL_NIF_TERM ATOM_IS_PEER_ACCEPTED; ERL_NIF_TERM ATOM_IS_CONN_SHUTDOWN; @@ -394,6 +398,15 @@ ERL_NIF_TERM ATOM_CLIENT_ALPNS; ERL_NIF_TERM ATOM_CRYPTO_BUFFER; ERL_NIF_TERM ATOM_UNDEFINED; +// Datagram Send State +ERL_NIF_TERM ATOM_QUIC_DATAGRAM_SEND_UNKNOWN; +ERL_NIF_TERM ATOM_QUIC_DATAGRAM_SEND_SENT; +ERL_NIF_TERM ATOM_QUIC_DATAGRAM_SEND_LOST_SUSPECT; +ERL_NIF_TERM ATOM_QUIC_DATAGRAM_SEND_LOST_DISCARDED; +ERL_NIF_TERM ATOM_QUIC_DATAGRAM_SEND_ACKNOWLEDGED; +ERL_NIF_TERM ATOM_QUIC_DATAGRAM_SEND_ACKNOWLEDGED_SPURIOUS; +ERL_NIF_TERM ATOM_QUIC_DATAGRAM_SEND_CANCELED; + // Mirror 'status' in msquic_linux.h /* @@ -682,6 +695,7 @@ ERL_NIF_TERM ATOM_UNDEFINED; ATOM(ATOM_PEER_NEEDS_STREAMS, peer_needs_streams); \ ATOM(ATOM_START_COMPLETE, start_completed); \ ATOM(ATOM_SEND_COMPLETE, send_complete); \ + ATOM(ATOM_DGRAM_SEND_STATE, dgram_send_state); \ ATOM(ATOM_SEND_DGRAM_COMPLETE, send_dgram_completed); \ ATOM(ATOM_EINVAL, einval); \ ATOM(ATOM_QUIC, quic); \ @@ -690,7 +704,9 @@ ERL_NIF_TERM ATOM_UNDEFINED; ATOM(ATOM_NST_RECEIVED, nst_received); \ ATOM(ATOM_NST, nst); \ ATOM(ATOM_DGRAM, dgram); \ + ATOM(ATOM_DGRAM_STATE_CHANGED, dgram_state_changed); \ ATOM(ATOM_DGRAM_MAX_LEN, dgram_max_len); \ + ATOM(ATOM_DGRAM_SEND_ENABLED, dgram_send_enabled); \ ATOM(ATOM_DEBUG, debug); \ ATOM(ATOM_ONCE, once); \ ATOM(ATOM_NEW_CONN, new_conn); \ @@ -727,6 +743,7 @@ ERL_NIF_TERM ATOM_UNDEFINED; ATOM(ATOM_BIDI_STREAMS, bidi_streams); \ ATOM(ATOM_UNIDI_STREAMS, unidi_streams); \ ATOM(ATOM_STATUS, status); \ + ATOM(ATOM_STATE, state); \ ATOM(ATOM_STREAM_ID, stream_id); \ ATOM(ATOM_IS_PEER_ACCEPTED, is_peer_accepted); \ ATOM(ATOM_IS_CONN_SHUTDOWN, is_conn_shutdown); \ @@ -739,6 +756,14 @@ ERL_NIF_TERM ATOM_UNDEFINED; ATOM(ATOM_SERVER_NAME, server_name); \ ATOM(ATOM_CLIENT_ALPNS, client_alpns); \ ATOM(ATOM_CRYPTO_BUFFER, crypto_buffer); \ + ATOM(ATOM_QUIC_DATAGRAM_SEND_UNKNOWN, dgram_send_unknown); \ + ATOM(ATOM_QUIC_DATAGRAM_SEND_SENT, dgram_send_sent); \ + ATOM(ATOM_QUIC_DATAGRAM_SEND_LOST_SUSPECT, dgram_send_lost_suspect); \ + ATOM(ATOM_QUIC_DATAGRAM_SEND_LOST_DISCARDED, dgram_send_lost_discarded); \ + ATOM(ATOM_QUIC_DATAGRAM_SEND_ACKNOWLEDGED, dgram_send_acknowledged); \ + ATOM(ATOM_QUIC_DATAGRAM_SEND_ACKNOWLEDGED_SPURIOUS, \ + dgram_send_acknowledged_spurious); \ + ATOM(ATOM_QUIC_DATAGRAM_SEND_CANCELED, dgram_send_canceled); \ ATOM(ATOM_UNDEFINED, undefined); HQUIC GRegistration = NULL; diff --git a/docs/messages_to_owner.md b/docs/messages_to_owner.md index c5d8293a..0aaf72e0 100644 --- a/docs/messages_to_owner.md +++ b/docs/messages_to_owner.md @@ -70,8 +70,9 @@ Otherwise, start stream will be queued. Also see [peer_accepted](#peer_accepted) ### active received data -Data received in binary format. +Stream data received in binary format with stream handle +also see [DATAGRAM received data]. ```erlang {quic, binary(), stream_handle(), #{ absolute_offset := integer() @@ -304,26 +305,23 @@ Peer wants to open more streams but cannot due to flow control ### DATAGRAM state changed -@TODO convert it to the new format and use some atom state ```erlang -{quic, dgram, connection_handle(), MaxLen::integer()} +{quic, dgram_state_changed, connection_handle(), #{ dgram_send_enabled := boolean(), dgram_max_len := uint64()}} ``` -### DATAGRAM received +### DATAGRAM received data -@TODO convert it to the new format +with connection handle and integer flag ```erlang -{quic, binary(), {dgram, connection_handle()}, flag :: integer()} +{quic, binary(), connection_handle(), flag :: non_neg_integer()} ``` -### DATAGRAM send state changed - -@TODO use some atom state +### DATAGRAM send completed, success or fail. ```erlang -{quic, send_dgram_completed, connection_handle(), State::integer()} +{quic, dgram_send_state, connection_handle(), #{state := datagram_send_state()}} ``` ### Connection resumed diff --git a/include/quicer.hrl b/include/quicer.hrl index 1a48a59c..485c77f2 100644 --- a/include/quicer.hrl +++ b/include/quicer.hrl @@ -123,6 +123,15 @@ -define(QUIC_RECEIVE_FLAG_0_RTT , 16#0001). -define(QUIC_RECEIVE_FLAG_FIN , 16#0002). +%% QUIC DATAGRAM_SEND_STATE +-define(QUIC_DATAGRAM_SEND_UNKNOWN, dgram_send_unknown). %% Not yet sent. +-define(QUIC_DATAGRAM_SEND_SENT, dgram_send_sent). %% Sent and awaiting acknowledegment +-define(QUIC_DATAGRAM_SEND_LOST_SUSPECT, dgram_send_lost_suspect). %% Suspected as lost, but still tracked +-define(QUIC_DATAGRAM_SEND_LOST_DISCARDED, dgram_send_lost_discarded). %% Lost and not longer being tracked +-define(QUIC_DATAGRAM_SEND_ACKNOWLEDGED, dgram_send_acknowledged). %% Acknowledged +-define(QUIC_DATAGRAM_SEND_ACKNOWLEDGED_SPURIOUS, dgram_send_acknowledged_spurious). %% Acknowledged after being suspected lost +-define(QUIC_DATAGRAM_SEND_CANCELED, dgram_send_canceled). + -record(quic_data, { offset = 0 :: non_neg_integer(), size = 0 :: non_neg_integer(), diff --git a/include/quicer_types.hrl b/include/quicer_types.hrl index ae76e8e4..51033269 100644 --- a/include/quicer_types.hrl +++ b/include/quicer_types.hrl @@ -378,4 +378,12 @@ %% @doc binary data with offset and size info -type quic_data() :: #quic_data{}. +-type datagram_send_state() :: ?QUIC_DATAGRAM_SEND_UNKNOWN %% Not sent yet + | ?QUIC_DATAGRAM_SEND_SENT %% Sent but not acked yet + | ?QUIC_DATAGRAM_SEND_LOST_SUSPECT %% Suspected lost but still tracked + | ?QUIC_DATAGRAM_SEND_LOST_DISCARDED %% Lost and no longer tracked + | ?QUIC_DATAGRAM_SEND_ACKNOWLEDGED %% Acknowledged + | ?QUIC_DATAGRAM_SEND_ACKNOWLEDGED_SPURIOUS %% Acknowledged after being suspected lost + | ?QUIC_DATAGRAM_SEND_CANCELED. %% Send cancelled + -endif. %% QUICER_TYPES_HRL diff --git a/src/quicer.erl b/src/quicer.erl index fc654589..95b8b51c 100644 --- a/src/quicer.erl +++ b/src/quicer.erl @@ -727,11 +727,20 @@ do_recv(Stream, Count, Buff) -> {error, dgram_send_error, atom_reason()}. send_dgram(Conn, Data) -> case quicer_nif:send_dgram(Conn, Data, _IsSync = 1) of - %% @todo make ref + %% @todo we need find tuned event mask {ok, _Len} = OK -> receive - {quic, send_dgram_completed, Conn} -> - OK + {quic, dgram_send_state, Conn, #{state := ?QUIC_DATAGRAM_SEND_SENT}} -> + receive + {quic, dgram_send_state, Conn, #{state := ?QUIC_DATAGRAM_SEND_ACKNOWLEDGED}} -> + OK; + {quic, dgram_send_state, Conn, #{state := Other}} -> + {error, dgram_send_error, Other} + end; + {quic, dgram_send_state, Conn, #{state := ?QUIC_DATAGRAM_SEND_ACKNOWLEDGED}} -> + OK; + {quic, dgram_send_state, Conn, #{state := Other}} -> + {error, dgram_send_error, Other} end; E -> E @@ -1151,7 +1160,6 @@ flush(QuicEventName, Handle) when is_atom(QuicEventName) -> %% Event must come, do not timeout end. - -ifdef(TEST). -include_lib("eunit/include/eunit.hrl"). diff --git a/src/quicer_connection.erl b/src/quicer_connection.erl index 72894d0c..2d0560fc 100644 --- a/src/quicer_connection.erl +++ b/src/quicer_connection.erl @@ -409,6 +409,11 @@ handle_info({quic, nst_received, C, TicketBin}, ?tp_ignore_side_effects_in_prod(debug, #{module => ?MODULE, conn => C, event => nst_received, ticket => TicketBin}), default_cb_ret(M:nst_received(C, TicketBin, CBState), State); +handle_info({quic, dgram_state_changed, C, Flags}, + #{callback := M, callback_state := CBState} = State) -> + ?tp_ignore_side_effects_in_prod(debug, #{module => ?MODULE, conn => C, event => dgram_state_changed, flags => Flags}), + default_cb_ret(M:datagram_state_changed(C, Flags, CBState), State); + %%% ============================================================== %%% Handle messages for link/monitor %%% ============================================================== diff --git a/test/example_client_connection.erl b/test/example_client_connection.erl index 5b83e89f..85c5af32 100644 --- a/test/example_client_connection.erl +++ b/test/example_client_connection.erl @@ -40,6 +40,7 @@ , resumed/3 , nst_received/3 , new_stream/3 + , datagram_state_changed/3 ]). start_link(Host, Port, {_COpts, _SOpts} = Opts)-> @@ -94,6 +95,10 @@ new_stream(Stream, Flags, #{ conn := Conn, streams := Streams Other end. +datagram_state_changed(_Conn, _Flags, S) -> + ?tp(debug, #{module => ?MODULE, conn => _Conn, flags => state, event => dgram_state_changed}), + {ok, S}. + shutdown(_Conn, _ErrorCode, S) -> {ok, S}. diff --git a/test/example_server_connection.erl b/test/example_server_connection.erl index faa1b73a..a5bcf9ab 100644 --- a/test/example_server_connection.erl +++ b/test/example_server_connection.erl @@ -47,6 +47,7 @@ , resumed/3 , nst_received/3 , new_stream/3 + , datagram_state_changed/3 ]). init(ConnOpts) when is_list(ConnOpts) -> @@ -121,3 +122,6 @@ peer_needs_streams(C, #{bidi_streams := Current}, S) -> %% for https://github.com/microsoft/msquic/issues/3120 peer_needs_streams(_C, undefined, S) -> {ok, S}. + +datagram_state_changed(_C, _Flags, S) -> + {ok, S}. diff --git a/test/quicer_SUITE.erl b/test/quicer_SUITE.erl index c9c2e02e..2cd78455 100644 --- a/test/quicer_SUITE.erl +++ b/test/quicer_SUITE.erl @@ -769,6 +769,7 @@ tc_stream_client_send_binary(Config) -> {ok, Stm} = quicer:start_stream(Conn, []), {ok, 4} = quicer:send(Stm, <<"ping">>), flush_streams_available(Conn), + flush_datagram_state_changed(Conn), receive {quic, <<"pong">>, _, _} -> ok = quicer:close_stream(Stm), @@ -792,6 +793,7 @@ tc_stream_client_send_iolist(Config) -> {ok, Stm} = quicer:start_stream(Conn, []), {ok, 4} = quicer:send(Stm, ["p", ["i", ["n"]], <<"g">>]), flush_streams_available(Conn), + flush_datagram_state_changed(Conn), receive {quic, <<"pong">>, _, _} -> ok = quicer:close_stream(Stm), @@ -815,6 +817,7 @@ tc_stream_client_async_send(Config) -> {ok, Stm} = quicer:start_stream(Conn, []), {ok, 4} = quicer:async_send(Stm, <<"ping">>), flush_streams_available(Conn), + flush_datagram_state_changed(Conn), receive {quic, <<"pong">>, _, _} -> ok = quicer:close_stream(Stm), @@ -936,6 +939,7 @@ tc_stream_active_switch_to_passive(Config) -> {ok, Stm} = quicer:start_stream(Conn, [{active, true}]), {ok, 11} = quicer:send(Stm, <<"ping_active">>), flush_streams_available(Conn), + flush_datagram_state_changed(Conn), {error, einval} = quicer:recv(Stm, 0), receive {quic, <<"ping_active">>, Stm, _} -> ok @@ -1224,6 +1228,7 @@ tc_dgram_client_send(Config) -> {ok, 4} = quicer:send(Stm, <<"ping">>), {ok, 4} = quicer:send_dgram(Conn, <<"ping">>), flush_streams_available(Conn), + flush_datagram_state_changed(Conn), dgram_client_recv_loop(Conn, false, false), SPid ! done, ok = ensure_server_exit_normal(Ref) @@ -1236,11 +1241,11 @@ dgram_client_recv_loop(Conn, true, true) -> dgram_client_recv_loop(Conn, ReceivedOnStream, ReceivedViaDgram) -> receive - {quic, dgram, <<"pong">>} -> + {quic, <<"pong">>, Conn, Flag} when is_integer(Flag) -> dgram_client_recv_loop(Conn, ReceivedOnStream, true); - {quic, <<"pong">>, _, _} -> + {quic, <<"pong">>, _Stream, Flag} -> dgram_client_recv_loop(Conn, true, ReceivedViaDgram); - {quic, dgram_max_len, _} -> + {quic, dgram_state_changed, Conn, #{dgram_send_enabled := true, dgram_max_len := _Size}} -> dgram_client_recv_loop(Conn, ReceivedOnStream, ReceivedViaDgram); Other -> ct:fail("Unexpected Msg ~p", [Other]) @@ -2314,7 +2319,7 @@ tc_stream_start_flag_shutdown_on_fail(Config) -> #{status := Reason, stream_id := StreamID}} -> ct:fail("Stream ~pstart complete with other reason: ~p", [StreamID, Reason]) end, - + flush_datagram_state_changed(Conn), %% Expect a send_shutdown_complete receive {quic, send_shutdown_complete, Stm, false } -> ok end, @@ -3153,7 +3158,7 @@ ping_pong_server_dgram_loop(L, Conn, Stm) -> ct:pal("send stream pong"), {ok, 4} = quicer:send(Stm, <<"pong">>), ping_pong_server_dgram_loop(L, Conn, Stm); - {quic, dgram, <<"ping">>} -> + {quic, <<"ping">>, Conn, Flag} when is_integer(Flag) -> ct:pal("send dgram pong"), {ok, 4} = quicer:send_dgram(Conn, <<"pong">>), ping_pong_server_dgram_loop(L, Conn, Stm); @@ -3377,6 +3382,11 @@ flush_streams_available(Conn) -> #{bidi_streams := _, unidi_streams := _}} -> ok end. +flush_datagram_state_changed(Conn) -> + receive + {quic, dgram_state_changed, Conn, _} -> ok + end. + filename(Path, F, A) -> filename:join(Path, str(io_lib:format(F, A))). str(Arg) ->