Skip to content

Commit a26641d

Browse files
authored
Merge pull request #70 from dpfens/change_entrypoint
Add WasmEntryPoint directive to change/specify entrypoints
2 parents c389304 + ebfaaea commit a26641d

File tree

5 files changed

+98
-3
lines changed

5 files changed

+98
-3
lines changed

mod_wasm/httpd.conf

+1
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,7 @@ LoadModule wasm_module modules/mod_wasm.so
187187
<Location /hello-wasm>
188188
SetHandler wasm-handler
189189
WasmModule /usr/local/apache2/wasm_modules/rust-wasm/hello_wasm.wasm
190+
WasmEntryPoint _start
190191
</Location>
191192

192193
###################################################################

mod_wasm/modules/wasm/mod_wasm.c

+20-1
Original file line numberDiff line numberDiff line change
@@ -435,6 +435,7 @@ static void register_hooks(apr_pool_t *p)
435435
#define WASM_DIRECTIVE_WASMMAPDIR "WasmMapDir"
436436
#define WASM_DIRECTIVE_WASMENABLECGI "WasmEnableCGI"
437437
#define WASM_DIRECTIVE_WASMMAPCGIFILENAMES "WasmMapCGIFileNames"
438+
#define WASM_DIRECTIVE_WASMENTRYPOINT "WasmEntryPoint"
438439

439440
static const char *wasm_directive_WasmModule(cmd_parms *cmd, void *mconfig, const char *word1)
440441
{
@@ -518,6 +519,17 @@ static const char *wasm_directive_WasmMapCGIFileNames(cmd_parms *cmd, void *mcon
518519
return NULL;
519520
}
520521

522+
static const char *wasm_directive_WasmEntryPoint(cmd_parms *cmd, void *mconfig, const char *entrypoint)
523+
{
524+
x_cfg *cfg = (x_cfg *) mconfig;
525+
int ret = wasm_config_entrypoint_set(cfg->loc, entrypoint);
526+
if ( ret != OK )
527+
ap_log_error(APLOG_MARK, APLOG_ERR, ret, NULL,
528+
"wasm_directive_WasmEntryPoint() - ERROR! Couldn't set entrypoint '%s' to Wasm config '%s'!", entrypoint, cfg->loc);
529+
530+
return NULL;
531+
}
532+
521533
/*
522534
* List of directives specific to our module.
523535
*/
@@ -542,7 +554,7 @@ static const command_rec directives[] =
542554
wasm_directive_WasmEnv,
543555
NULL,
544556
OR_OPTIONS,
545-
"Set environtment variable for the Wasm Module"
557+
"Set environment variable for the Wasm Module"
546558
),
547559
AP_INIT_TAKE1(
548560
WASM_DIRECTIVE_WASMDIR,
@@ -572,6 +584,13 @@ static const command_rec directives[] =
572584
OR_OPTIONS,
573585
"Whether SCRIPT_FILENAME should be mapped based on WasmMapDir mounts when running as a CGI"
574586
),
587+
AP_INIT_TAKE1(
588+
WASM_DIRECTIVE_WASMENTRYPOINT,
589+
wasm_directive_WasmEntryPoint,
590+
NULL,
591+
OR_OPTIONS,
592+
"Set entrypoint for the Wasm Module"
593+
),
575594
{NULL}
576595
};
577596

wasm_runtime/src/c_api.rs

+45
Original file line numberDiff line numberDiff line change
@@ -396,6 +396,38 @@ pub extern "C" fn wasm_executionctx_stdin_set(executionctx_id: *const c_char, bu
396396
}
397397

398398

399+
/// Set the entrypoint for loaded Wasm Module to an existing Wasm Config.
400+
///
401+
/// Wasm config must have been previously created.
402+
///
403+
/// In case of error, the reason is printed to stderr and returns -1.
404+
/// Otherwise, it returns 0.
405+
///
406+
/// Due to String management differences between C and Rust, this function uses `unsafe {}` code.
407+
/// So `config_id` and `entrypoint` must be a valid pointer to a null-terminated C char array. Otherwise, code might panic.
408+
/// In addition, `config_id` and `entrypoint` must contain valid ASCII chars that can be converted into UTF-8 encoding.
409+
///
410+
/// # Examples (C Code)
411+
///
412+
/// ```
413+
/// wasm_config_entrypoint_set("Drupal", "_start");
414+
/// wasm_config_entrypoint_set("WordPress", "run");
415+
/// ```
416+
#[no_mangle]
417+
pub extern "C" fn wasm_config_entrypoint_set(config_id: *const c_char, entrypoint: *const c_char) -> c_int {
418+
let config_id_str = const_c_char_to_str(config_id);
419+
let entrypoint_str = const_c_char_to_str(entrypoint);
420+
421+
match WasmConfig::set_entrypoint_for_config(config_id_str, entrypoint_str) {
422+
Ok(_) => 0,
423+
Err(e) => {
424+
eprintln!("ERROR! C-API: Couldn't set entrypoint for Wasm config \"{}\": {}", config_id_str, e);
425+
-1
426+
}
427+
}
428+
}
429+
430+
399431
/// Run the given Wasm execution context
400432
///
401433
/// In case of error, the reason is printed to stderr and returns -1.
@@ -638,4 +670,17 @@ mod tests {
638670
// assert
639671
assert_eq!(val, 0);
640672
}
673+
674+
#[test]
675+
fn wasm_config_entrypoint_set_general() {
676+
let config_id = CString::new("test_config").unwrap();
677+
678+
// test
679+
wasm_config_create(config_id.as_ptr());
680+
let entrypoint = CString::new("run").unwrap();
681+
let val = wasm_config_entrypoint_set(config_id.as_ptr(), entrypoint.as_ptr());
682+
683+
// asserts
684+
assert_eq!(val, 0);
685+
}
641686
}

wasm_runtime/src/config.rs

+28
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ use path_slash::PathBufExt as _;
1919
pub struct WasmConfig {
2020
pub id: String,
2121
pub module_id: String,
22+
pub entrypoint: String,
2223
pub wasi_args: Vec<String>,
2324
pub wasi_envs: Vec<(String, String)>,
2425
pub wasi_dirs: Vec<String>,
@@ -59,6 +60,7 @@ impl WasmConfig {
5960
wasi_envs: Vec::new(),
6061
wasi_dirs: Vec::new(),
6162
wasi_mapdirs: Vec::new(),
63+
entrypoint: "_start".to_string() // defaults to "_start"
6264
};
6365

6466
// insert created WasmConfig object into the HashMap
@@ -212,6 +214,32 @@ impl WasmConfig {
212214
Ok(())
213215
}
214216

217+
// Set the entrypoint for a loaded Wasm Module to an existing Wasm config
218+
///
219+
/// It checks for wrong `config_id`
220+
/// Returns Result<(), String>, so that in case of error the String will contain the reason.
221+
///
222+
pub fn set_entrypoint_for_config(config_id: &str, entrypoint: &str) -> Result<(), String> {
223+
224+
// get write access to the WasmConfig HashMap
225+
let mut configs = WASM_RUNTIME_CONFIGS.write()
226+
.expect("ERROR! Poisoned RwLock WASM_RUNTIME_CONFIGS on write()");
227+
228+
// check for existing config_id in the loaded configurations
229+
let wasm_config = match configs.get_mut(config_id) {
230+
Some(c) => c,
231+
None => {
232+
let error_msg = format!("Wasm config \'{}\' not found while setting entrypoint \'{}\'", config_id, entrypoint);
233+
return Err(error_msg);
234+
}
235+
};
236+
237+
// setting module in Wasm config
238+
wasm_config.entrypoint = entrypoint.to_string();
239+
240+
Ok(())
241+
}
242+
215243
pub fn get_mapped_path(config_id: &str, path: &str) -> Result<Option<String>, String> {
216244
let configs = WASM_RUNTIME_CONFIGS
217245
.read()

wasm_runtime/src/execution_ctx.rs

+4-2
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ pub struct WasmExecutionCtx {
2828
pub wasi_mapdirs: Vec<(String, String)>,
2929
pub wasi_stdin: Vec<u8>,
3030
pub wasi_stdout: Arc<RwLock<Vec<u8>>>,
31+
pub entrypoint: String
3132
}
3233

3334
impl WasmExecutionCtx {
@@ -65,6 +66,7 @@ impl WasmExecutionCtx {
6566
wasi_mapdirs: wasm_config.wasi_mapdirs.clone(),
6667
wasi_stdin: Vec::new(),
6768
wasi_stdout: Arc::new(RwLock::new(Vec::new())),
69+
entrypoint: wasm_config.entrypoint.clone()
6870
};
6971

7072
Self::try_insert(wasm_executionctx)
@@ -154,8 +156,8 @@ impl WasmExecutionCtx {
154156
}
155157
};
156158

157-
// invoke default "_start" function for the given Wasm execution context
158-
wasm_engine::invoke_wasm_function(&wasm_executionctx, "_start")?;
159+
// invoke entrypoint for the given Wasm execution context (default is "_start")
160+
wasm_engine::invoke_wasm_function(&wasm_executionctx, &wasm_executionctx.entrypoint)?;
159161

160162
// read stdout from the Wasm execution context and return it
161163
let wasm_module_stdout = Self::read_stdout(&wasm_executionctx);

0 commit comments

Comments
 (0)