nquic_receiver (nquic v1.0.0)

View Source

QUIC packet receiver process.

Each receiver owns one UDP socket and runs an async recv loop using completion-based I/O. Multiple receivers can share the same port via SO_REUSEPORT. Incoming packets are dispatched via ETS lookup: existing connections get a direct message (fast path), new connections are spawned in a separate process (slow path).

Summary

Functions

bump_rate/1

-spec bump_rate(#state{socket :: nquic_socket:t(),
                       select_info :: nquic_socket:select_info() | undefined,
                       dispatch_table :: nquic_dispatch:t(),
                       listener :: pid(),
                       opts :: map(),
                       static_key :: binary(),
                       max_new_conns_per_sec :: non_neg_integer(),
                       rate_count :: non_neg_integer(),
                       rate_window_start :: integer(),
                       retry :: boolean(),
                       retry_token_lifetime :: pos_integer(),
                       ecn :: boolean(),
                       gro :: boolean()}) ->
                   #state{socket :: nquic_socket:t(),
                          select_info :: nquic_socket:select_info() | undefined,
                          dispatch_table :: nquic_dispatch:t(),
                          listener :: pid(),
                          opts :: map(),
                          static_key :: binary(),
                          max_new_conns_per_sec :: non_neg_integer(),
                          rate_count :: non_neg_integer(),
                          rate_window_start :: integer(),
                          retry :: boolean(),
                          retry_token_lifetime :: pos_integer(),
                          ecn :: boolean(),
                          gro :: boolean()}.

check_rate_limit/1

-spec check_rate_limit(#state{socket :: nquic_socket:t(),
                              select_info :: nquic_socket:select_info() | undefined,
                              dispatch_table :: nquic_dispatch:t(),
                              listener :: pid(),
                              opts :: map(),
                              static_key :: binary(),
                              max_new_conns_per_sec :: non_neg_integer(),
                              rate_count :: non_neg_integer(),
                              rate_window_start :: integer(),
                              retry :: boolean(),
                              retry_token_lifetime :: pos_integer(),
                              ecn :: boolean(),
                              gro :: boolean()}) ->
                          {boolean(),
                           #state{socket :: nquic_socket:t(),
                                  select_info :: nquic_socket:select_info() | undefined,
                                  dispatch_table :: nquic_dispatch:t(),
                                  listener :: pid(),
                                  opts :: map(),
                                  static_key :: binary(),
                                  max_new_conns_per_sec :: non_neg_integer(),
                                  rate_count :: non_neg_integer(),
                                  rate_window_start :: integer(),
                                  retry :: boolean(),
                                  retry_token_lifetime :: pos_integer(),
                                  ecn :: boolean(),
                                  gro :: boolean()}}.

dispatch_packet/3

-spec dispatch_packet(nquic_socket:sockaddr(),
                      binary(),
                      #state{socket :: nquic_socket:t(),
                             select_info :: nquic_socket:select_info() | undefined,
                             dispatch_table :: nquic_dispatch:t(),
                             listener :: pid(),
                             opts :: map(),
                             static_key :: binary(),
                             max_new_conns_per_sec :: non_neg_integer(),
                             rate_count :: non_neg_integer(),
                             rate_window_start :: integer(),
                             retry :: boolean(),
                             retry_token_lifetime :: pos_integer(),
                             ecn :: boolean(),
                             gro :: boolean()}) ->
                         #state{socket :: nquic_socket:t(),
                                select_info :: nquic_socket:select_info() | undefined,
                                dispatch_table :: nquic_dispatch:t(),
                                listener :: pid(),
                                opts :: map(),
                                static_key :: binary(),
                                max_new_conns_per_sec :: non_neg_integer(),
                                rate_count :: non_neg_integer(),
                                rate_window_start :: integer(),
                                retry :: boolean(),
                                retry_token_lifetime :: pos_integer(),
                                ecn :: boolean(),
                                gro :: boolean()}.

fast_dispatch/2

-spec fast_dispatch(binary(), nquic_dispatch:t()) -> {ok, pid()} | slow.

get_dcid/1

-spec get_dcid(#long_header{type :: initial | handshake | rtt0 | retry | version_negotiation,
                            version :: 0..4294967295,
                            dcid :: nquic:connection_id(),
                            scid :: nquic:connection_id(),
                            token :: binary() | undefined,
                            payload_len :: non_neg_integer() | undefined,
                            packet_number :: nquic_packet_number:t() | undefined,
                            pn_len :: 1..4 | undefined} |
               #short_header{dcid :: nquic:connection_id(),
                             packet_number :: nquic_packet_number:t() | undefined,
                             key_phase :: boolean(),
                             spin :: 0..1,
                             pn_len :: 1..4 | undefined}) ->
                  binary().

get_port(Pid)

-spec get_port(pid()) -> {ok, inet:port_number()} | {error, nquic_error:any_reason()}.

Return the port number this receiver's socket is bound to.

handle_call/3

-spec handle_call(get_port | term(),
                  gen_server:from(),
                  #state{socket :: nquic_socket:t(),
                         select_info :: nquic_socket:select_info() | undefined,
                         dispatch_table :: nquic_dispatch:t(),
                         listener :: pid(),
                         opts :: map(),
                         static_key :: binary(),
                         max_new_conns_per_sec :: non_neg_integer(),
                         rate_count :: non_neg_integer(),
                         rate_window_start :: integer(),
                         retry :: boolean(),
                         retry_token_lifetime :: pos_integer(),
                         ecn :: boolean(),
                         gro :: boolean()}) ->
                     {reply,
                      term(),
                      #state{socket :: nquic_socket:t(),
                             select_info :: nquic_socket:select_info() | undefined,
                             dispatch_table :: nquic_dispatch:t(),
                             listener :: pid(),
                             opts :: map(),
                             static_key :: binary(),
                             max_new_conns_per_sec :: non_neg_integer(),
                             rate_count :: non_neg_integer(),
                             rate_window_start :: integer(),
                             retry :: boolean(),
                             retry_token_lifetime :: pos_integer(),
                             ecn :: boolean(),
                             gro :: boolean()}}.

handle_cast(Msg, State)

-spec handle_cast(term(),
                  #state{socket :: nquic_socket:t(),
                         select_info :: nquic_socket:select_info() | undefined,
                         dispatch_table :: nquic_dispatch:t(),
                         listener :: pid(),
                         opts :: map(),
                         static_key :: binary(),
                         max_new_conns_per_sec :: non_neg_integer(),
                         rate_count :: non_neg_integer(),
                         rate_window_start :: integer(),
                         retry :: boolean(),
                         retry_token_lifetime :: pos_integer(),
                         ecn :: boolean(),
                         gro :: boolean()}) ->
                     {noreply,
                      #state{socket :: nquic_socket:t(),
                             select_info :: nquic_socket:select_info() | undefined,
                             dispatch_table :: nquic_dispatch:t(),
                             listener :: pid(),
                             opts :: map(),
                             static_key :: binary(),
                             max_new_conns_per_sec :: non_neg_integer(),
                             rate_count :: non_neg_integer(),
                             rate_window_start :: integer(),
                             retry :: boolean(),
                             retry_token_lifetime :: pos_integer(),
                             ecn :: boolean(),
                             gro :: boolean()}}.

handle_info/2

-spec handle_info(term(),
                  #state{socket :: nquic_socket:t(),
                         select_info :: nquic_socket:select_info() | undefined,
                         dispatch_table :: nquic_dispatch:t(),
                         listener :: pid(),
                         opts :: map(),
                         static_key :: binary(),
                         max_new_conns_per_sec :: non_neg_integer(),
                         rate_count :: non_neg_integer(),
                         rate_window_start :: integer(),
                         retry :: boolean(),
                         retry_token_lifetime :: pos_integer(),
                         ecn :: boolean(),
                         gro :: boolean()}) ->
                     {noreply,
                      #state{socket :: nquic_socket:t(),
                             select_info :: nquic_socket:select_info() | undefined,
                             dispatch_table :: nquic_dispatch:t(),
                             listener :: pid(),
                             opts :: map(),
                             static_key :: binary(),
                             max_new_conns_per_sec :: non_neg_integer(),
                             rate_count :: non_neg_integer(),
                             rate_window_start :: integer(),
                             retry :: boolean(),
                             retry_token_lifetime :: pos_integer(),
                             ecn :: boolean(),
                             gro :: boolean()}}.

init(Opts)

-spec init(map()) ->
              {ok,
               #state{socket :: nquic_socket:t(),
                      select_info :: nquic_socket:select_info() | undefined,
                      dispatch_table :: nquic_dispatch:t(),
                      listener :: pid(),
                      opts :: map(),
                      static_key :: binary(),
                      max_new_conns_per_sec :: non_neg_integer(),
                      rate_count :: non_neg_integer(),
                      rate_window_start :: integer(),
                      retry :: boolean(),
                      retry_token_lifetime :: pos_integer(),
                      ecn :: boolean(),
                      gro :: boolean()}} |
              {stop, term()}.

maybe_retry/3

-spec maybe_retry(binary() | undefined,
                  nquic_socket:sockaddr(),
                  #state{socket :: nquic_socket:t(),
                         select_info :: nquic_socket:select_info() | undefined,
                         dispatch_table :: nquic_dispatch:t(),
                         listener :: pid(),
                         opts :: map(),
                         static_key :: binary(),
                         max_new_conns_per_sec :: non_neg_integer(),
                         rate_count :: non_neg_integer(),
                         rate_window_start :: integer(),
                         retry :: boolean(),
                         retry_token_lifetime :: pos_integer(),
                         ecn :: boolean(),
                         gro :: boolean()}) ->
                     proceed | {retry, nquic:connection_id()} | send_retry.

slow_dispatch(Source, Bin, Table, State)

-spec slow_dispatch(nquic_socket:sockaddr(),
                    binary(),
                    nquic_dispatch:t(),
                    #state{socket :: nquic_socket:t(),
                           select_info :: nquic_socket:select_info() | undefined,
                           dispatch_table :: nquic_dispatch:t(),
                           listener :: pid(),
                           opts :: map(),
                           static_key :: binary(),
                           max_new_conns_per_sec :: non_neg_integer(),
                           rate_count :: non_neg_integer(),
                           rate_window_start :: integer(),
                           retry :: boolean(),
                           retry_token_lifetime :: pos_integer(),
                           ecn :: boolean(),
                           gro :: boolean()}) ->
                       #state{socket :: nquic_socket:t(),
                              select_info :: nquic_socket:select_info() | undefined,
                              dispatch_table :: nquic_dispatch:t(),
                              listener :: pid(),
                              opts :: map(),
                              static_key :: binary(),
                              max_new_conns_per_sec :: non_neg_integer(),
                              rate_count :: non_neg_integer(),
                              rate_window_start :: integer(),
                              retry :: boolean(),
                              retry_token_lifetime :: pos_integer(),
                              ecn :: boolean(),
                              gro :: boolean()}.

start_link(Opts)

-spec start_link(map()) -> {ok, pid()} | ignore | {error, term()}.

Start a receiver process with the given options.

terminate/2

-spec terminate(term(),
                #state{socket :: nquic_socket:t(),
                       select_info :: nquic_socket:select_info() | undefined,
                       dispatch_table :: nquic_dispatch:t(),
                       listener :: pid(),
                       opts :: map(),
                       static_key :: binary(),
                       max_new_conns_per_sec :: non_neg_integer(),
                       rate_count :: non_neg_integer(),
                       rate_window_start :: integer(),
                       retry :: boolean(),
                       retry_token_lifetime :: pos_integer(),
                       ecn :: boolean(),
                       gro :: boolean()}) ->
                   ok.