Skip to content

Commit

Permalink
Merge pull request #208 from qzhuyan/dev/william/reg-nif-resource
Browse files Browse the repository at this point in the history
support multi execution registrations
  • Loading branch information
qzhuyan authored Aug 30, 2023
2 parents 0f861b1 + 8b179d0 commit bc0855f
Show file tree
Hide file tree
Showing 14 changed files with 509 additions and 32 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ jobs:
key: brew-${{ matrix.os }}-${{ matrix.otp }}
- name: prepare
run: |
#brew update
export HOMEBREW_NO_INSTALLED_DEPENDENTS_CHECK=1
brew install erlang@${{ matrix.otp }}
- name: install rebar3
run: |
Expand Down
2 changes: 2 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,8 @@ set(SOURCES
c_src/quicer_nif.c
c_src/quicer_nif.h
c_src/quicer_eterms.h
c_src/quicer_reg.c
c_src/quicer_reg.h
c_src/quicer_config.c
c_src/quicer_config.h
c_src/quicer_queue.c
Expand Down
29 changes: 29 additions & 0 deletions c_src/quicer_ctx.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,35 @@ limitations under the License.

// alloc/dealloc ctx should be done in the callbacks.

QuicerRegistrationCTX *
init_r_ctx()
{
QuicerRegistrationCTX *r_ctx
= enif_alloc_resource(ctx_reg_t, sizeof(QuicerRegistrationCTX));
if (!r_ctx)
{
return NULL;
}
CxPlatZeroMemory(r_ctx, sizeof(QuicerRegistrationCTX));
r_ctx->env = enif_alloc_env();
r_ctx->Registration = NULL;
r_ctx->is_released = FALSE;
return r_ctx;
}

void
deinit_r_ctx(QuicerRegistrationCTX *r_ctx)
{
enif_free_env(r_ctx->env);
}

void
destroy_r_ctx(QuicerRegistrationCTX *r_ctx)
{
r_ctx->is_released = TRUE;
enif_release_resource(r_ctx);
}

QuicerListenerCTX *
init_l_ctx()
{
Expand Down
15 changes: 15 additions & 0 deletions c_src/quicer_ctx.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,17 @@ limitations under the License.
#define _CTX_NIF_WRITE_
#define _CTX_NIF_READ_

/*
* Registration
*/
typedef struct QuicerRegistrationCTX
{
ErlNifEnv *env;
HQUIC Registration;
BOOLEAN is_released;
char name[UINT8_MAX + 1];
} QuicerRegistrationCTX;

/*
* Configuration
*/
Expand Down Expand Up @@ -123,6 +134,10 @@ typedef struct QuicerStreamSendCTX

typedef struct QuicerStreamSendCTX QuicerDgramSendCTX;

QuicerRegistrationCTX *init_r_ctx();
void deinit_r_ctx(QuicerRegistrationCTX *r_ctx);
void destroy_r_ctx(QuicerRegistrationCTX *r_ctx);

QuicerListenerCTX *init_l_ctx();
void deinit_l_ctx(QuicerListenerCTX *l_ctx);
void destroy_l_ctx(QuicerListenerCTX *l_ctx);
Expand Down
36 changes: 33 additions & 3 deletions c_src/quicer_nif.c
Original file line number Diff line number Diff line change
Expand Up @@ -493,11 +493,11 @@ ERL_NIF_TERM ATOM_UNDEFINED;
ATOM(ATOM_QUIC_EXECUTION_PROFILE_LOW_LATENCY, \
quic_execution_profile_low_latency); \
ATOM(ATOM_QUIC_EXECUTION_PROFILE_TYPE_MAX_THROUGHPUT, \
quic_execution_profile_type_max_throughput); \
quic_execution_profile_max_throughput); \
ATOM(ATOM_QUIC_EXECUTION_PROFILE_TYPE_SCAVENGER, \
quic_execution_profile_type_scavenger); \
quic_execution_profile_scavenger); \
ATOM(ATOM_QUIC_EXECUTION_PROFILE_TYPE_REAL_TIME, \
quic_execution_profile_type_real_time); \
quic_execution_profile_real_time); \
/*-----------------------------------------*/ \
/* msquic params starts */ \
/*-----------------------------------------*/ \
Expand Down Expand Up @@ -748,6 +748,7 @@ const QUIC_API_TABLE *MsQuic = NULL;
BOOLEAN isRegistered = false;
BOOLEAN isLibOpened = false;

ErlNifResourceType *ctx_reg_t = NULL;
ErlNifResourceType *ctx_listener_t = NULL;
ErlNifResourceType *ctx_connection_t = NULL;
ErlNifResourceType *ctx_stream_t = NULL;
Expand Down Expand Up @@ -897,6 +898,19 @@ resource_config_dealloc_callback(__unused_parm__ ErlNifEnv *env,
TP_CB_3(end, (uintptr_t)obj, 0);
}

void
resource_reg_dealloc_callback(__unused_parm__ ErlNifEnv *env, void *obj)
{
TP_CB_3(start, (uintptr_t)obj, 0);
QuicerRegistrationCTX *reg_ctx = (QuicerRegistrationCTX *)obj;
deinit_r_ctx(reg_ctx);
if (reg_ctx->Registration)
{
MsQuic->RegistrationClose(reg_ctx->Registration);
}
TP_CB_3(end, (uintptr_t)obj, 0);
}

/*
** on_load is called when the NIF library is loaded and no previously loaded
*library exists for this module.
Expand Down Expand Up @@ -935,6 +949,15 @@ on_load(ErlNifEnv *env,
.dtor = resource_config_dealloc_callback, .down = NULL, .stop = NULL
};

ErlNifResourceTypeInit regInit
= { .dtor = resource_reg_dealloc_callback, .down = NULL, .stop = NULL };

ctx_reg_t = enif_open_resource_type_x(env,
"registration_context_resource",
&regInit, // init callbacks
flags,
NULL);

ctx_config_t = enif_open_resource_type_x(env,
"config_context_resource",
&configInit, // init callbacks
Expand Down Expand Up @@ -1057,6 +1080,9 @@ closeLib(__unused_parm__ ErlNifEnv *env,
return ATOM_OK;
}

/*
** For global registration only
*/
static ERL_NIF_TERM
registration(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
{
Expand Down Expand Up @@ -1418,6 +1444,10 @@ static ErlNifFunc nif_funcs[] = {
{ "reg_open", 0, registration, 0 },
{ "reg_open", 1, registration, 0 },
{ "reg_close", 0, deregistration, 0 },
{ "new_registration", 2, new_registration2, 0},
{ "shutdown_registration", 1, shutdown_registration_x, 0},
{ "shutdown_registration", 3, shutdown_registration_x, 0},
{ "get_registration_name", 1, get_registration_name1, 0},
{ "listen", 2, listen2, 0},
{ "start_listener", 3, start_listener3, 0},
{ "stop_listener", 1, stop_listener1, 0},
Expand Down
2 changes: 2 additions & 0 deletions c_src/quicer_nif.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ limitations under the License.
#include "quicer_dgram.h"
#include "quicer_eterms.h"
#include "quicer_queue.h"
#include "quicer_reg.h"
#include "quicer_stream.h"
#include "quicer_tp.h"

Expand All @@ -44,6 +45,7 @@ extern const QUIC_API_TABLE *MsQuic;
extern QUIC_REGISTRATION_CONFIG GRegConfig;

// Context Types
extern ErlNifResourceType *ctx_reg_t;
extern ErlNifResourceType *ctx_listener_t;
extern ErlNifResourceType *ctx_connection_t;
extern ErlNifResourceType *ctx_stream_t;
Expand Down
144 changes: 144 additions & 0 deletions c_src/quicer_reg.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
/*--------------------------------------------------------------------
Copyright (c) 2023 EMQ Technologies Co., Ltd. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-------------------------------------------------------------------*/
#include "quicer_reg.h"
#include "quicer_nif.h"

ERL_NIF_TERM
new_registration2(ErlNifEnv *env,
__unused_parm__ int argc,
const ERL_NIF_TERM argv[])
{
QUIC_STATUS status = QUIC_STATUS_SUCCESS;
ERL_NIF_TERM ename = argv[0];
QUIC_REGISTRATION_CONFIG RegConfig
= { NULL, QUIC_EXECUTION_PROFILE_LOW_LATENCY };

TP_NIF_3(start, 0, status);
if (argc == 2)
{
ERL_NIF_TERM eprofile = argv[1];
if (IS_SAME_TERM(eprofile, ATOM_QUIC_EXECUTION_PROFILE_LOW_LATENCY))
{
RegConfig.ExecutionProfile = QUIC_EXECUTION_PROFILE_LOW_LATENCY;
}
else if (IS_SAME_TERM(eprofile,
ATOM_QUIC_EXECUTION_PROFILE_TYPE_MAX_THROUGHPUT))
{
RegConfig.ExecutionProfile
= QUIC_EXECUTION_PROFILE_TYPE_MAX_THROUGHPUT;
}
else if (IS_SAME_TERM(eprofile,
ATOM_QUIC_EXECUTION_PROFILE_TYPE_SCAVENGER))
{
RegConfig.ExecutionProfile = QUIC_EXECUTION_PROFILE_TYPE_SCAVENGER;
}
else if (IS_SAME_TERM(eprofile,
ATOM_QUIC_EXECUTION_PROFILE_TYPE_REAL_TIME))
{
RegConfig.ExecutionProfile = QUIC_EXECUTION_PROFILE_TYPE_REAL_TIME;
}
else
{
return ERROR_TUPLE_2(ATOM_BADARG);
}
}

QuicerRegistrationCTX *r_ctx = init_r_ctx();
if (!r_ctx)
{
ERROR_TUPLE_2(ATOM_ERROR_NOT_ENOUGH_MEMORY);
}

if (0 >= enif_get_string(
env, ename, r_ctx->name, UINT8_MAX + 1, ERL_NIF_LATIN1))
{
deinit_r_ctx(r_ctx);
destroy_r_ctx(r_ctx);
ERROR_TUPLE_2(ATOM_BADARG);
}

// Open Registration
if (QUIC_FAILED(
status = MsQuic->RegistrationOpen(&RegConfig, &r_ctx->Registration)))
{
// unlikely
TP_NIF_3(fail, 0, status);
deinit_r_ctx(r_ctx);
destroy_r_ctx(r_ctx);
return ERROR_TUPLE_2(ATOM_STATUS(status));
}
TP_NIF_3(success, 0, status);
return SUCCESS(enif_make_resource(env, r_ctx));
}

ERL_NIF_TERM
shutdown_registration_x(ErlNifEnv *env, int argc, const ERL_NIF_TERM *argv)
{
QuicerRegistrationCTX *r_ctx = NULL;
ErlNifUInt64 error_code = 0;
BOOLEAN silent = FALSE;
ERL_NIF_TERM ectx = argv[0];
if (!enif_get_resource(env, ectx, ctx_reg_t, (void **)&r_ctx))
{
return ERROR_TUPLE_2(ATOM_BADARG);
}

if (argc == 3)
{
ERL_NIF_TERM esilent = argv[1];
if (IS_SAME_TERM(ATOM_TRUE, esilent))
{
silent = TRUE;
}
else if (IS_SAME_TERM(ATOM_FALSE, esilent))
{
silent = FALSE;
}
else
{
return ERROR_TUPLE_2(ATOM_BADARG);
}

if (!enif_get_uint64(env, argv[2], &error_code))
{
return ERROR_TUPLE_2(ATOM_BADARG);
}
}

if (r_ctx->Registration && !r_ctx->is_released)
{
// void return, trigger callback, no blocking
MsQuic->RegistrationShutdown(r_ctx->Registration, silent, error_code);
destroy_r_ctx(r_ctx);
}

return ATOM_OK;
}

ERL_NIF_TERM
get_registration_name1(ErlNifEnv *env,
__unused_parm__ int argc,
const ERL_NIF_TERM argv[])
{
QuicerRegistrationCTX *r_ctx = NULL;
ERL_NIF_TERM ectx = argv[0];
if (!enif_get_resource(env, ectx, ctx_reg_t, (void **)&r_ctx))
{
return ERROR_TUPLE_2(ATOM_BADARG);
}

return SUCCESS(enif_make_string(env, r_ctx->name, ERL_NIF_LATIN1));
}
29 changes: 29 additions & 0 deletions c_src/quicer_reg.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/*--------------------------------------------------------------------
Copyright (c) 2023 EMQ Technologies Co., Ltd. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-------------------------------------------------------------------*/
#ifndef QUICER_REG_H_
#define QUICER_REG_H_
#include <erl_nif.h>

ERL_NIF_TERM
new_registration2(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]);

ERL_NIF_TERM
shutdown_registration_x(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]);

ERL_NIF_TERM
get_registration_name1(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]);

#endif // QUICER_REG_H_
5 changes: 5 additions & 0 deletions include/quicer_types.hrl
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,11 @@
conf_handle() |
reg_handle().

-type registration_profile() :: quic_execution_profile_low_latency |
quic_execution_profile_max_throughput |
quic_execution_profile_scavenger |
quic_execution_profile_realtime.

-type quic_handle_level() :: quic_tls | quic_configuration | false.

-type listen_on() :: inet:port_number() | string().
Expand Down
Loading

0 comments on commit bc0855f

Please sign in to comment.