Stream: general

Topic: Run a C program which needs HTTP/Socket request on Wasm now


view this post on Zulip Ringz (Jul 23 2024 at 08:18):

I have a C program which can send HTTP requests to other services, how can I run it on Wasm now?
I found that even though WasmEdge supports most of the Socket API now, all the mainstream existing C to Wasm compiles don't support compiling Socket API, including Emscripten, Wasi-sdk.
Is there any other way to achieve it? Or maybe we need to wait until the wasi-http or wasi-socket proposals are accepted and implemented in the C to Wasm compiles?
Also, I found that rust compiler supports some key Socket APIs which are not in wasi-preview1, e.g., sock_setsockopt, sock_connect. So I was confused about why the toolchains for Wasm in Rust are more mature than those in C/C++. Is it related to the special features of Rust or what?

view this post on Zulip Victor Adossi (Jul 25 2024 at 16:45):

Sockets are implemented in wasi-libc, and while there is a recent issue with wasi-sdk not having the wasm32-wasip2 target, wasi-sdk 22 has the target now. You'll still need to do some adapting to get there it looks like but it should be possible.

Could you try targeting wasm32-wasip2 target with wasi-sdk 22?

This implements socket, connect, recv, send, etc. in terms of wasi-sockets for the wasm32-wasi-preview2 target. I've introduced a new public header file: __wasi_snapshot.h, which will define a prep...
Hi, I write a C program which will send an HTTP request to a server and it can run successfully when compiling it to machine code. When I try to use wasi-sdk to compile it, I encounter the followin...
Summary This is a proposal to add wasi-sockets support to wasi-libc as a first step towards full WASI Preview 2 support. This includes adding a new wasm32-wasi-preview2 build target to differentiat...

view this post on Zulip celine santosh (Jul 27 2024 at 20:58):

Hi

I have a go program which makes a tcp connection
conn, err := net.Dial("tcp", "216.58.206.46:80")

but this is not executing successfully and I encounter some nil pointer error even though the program executes successfully separately. So is this because of the reason above, that the network calls from a Go program compiled to WebAssembly (Wasm) and executed in a WASI environment will not work because the necessary system calls are not available in WASI Preview 1. Also for compilers like tinyGo and standard Go compiler, they still have limitations to support wasi preview 2?

view this post on Zulip Ralph (Jul 29 2024 at 12:17):

as of july 2: "It's a milestone day for Gophers and WebAssembly: the wasi-preview-2 feature branch of TinyGo has landed in TinyGo's dev branch, bringing WASI P2 support to TinyGo!"

view this post on Zulip Ringz (Jul 29 2024 at 14:42):

Hi

I try to compile with --target=wasm32-wasip2 option using wasi-sdk and successfully get the wasm code.
But the compiled result cannot successfully run on the existing wasm runtimes.

For WasmEdge, as the HTTP requests are related to wasi-socket proposal, WasmEdge is working for it.
https://github.com/WasmEdge/WasmEdge/issues/2939
For Wasmtime, I open an issue about it.
https://github.com/bytecodealliance/wasmtime/issues/9034

Summary This issue replaced #2806. This issue will be marked as finished once all preview2 proposals are implemented and verified. WasmEdge would love to have native support for the WASI preview2, ...
Hi, I have a C program which would send a HTTP request to a server, and use wasi-sdk-23 to compile it to wasm code, but fail to run it on Wasmtime, the error message is connect: Permission denied. ...

view this post on Zulip celine santosh (Jul 30 2024 at 21:49):

Ralph said:

as of july 2: "It's a milestone day for Gophers and WebAssembly: the wasi-preview-2 feature branch of TinyGo has landed in TinyGo's dev branch, bringing WASI P2 support to TinyGo!"

I have checked out the dev branch of tiny go.I have a go program which attempts to make a tcp connection to an ip. I have compiled this go program to Wasm module using tinyGo (dev branch which has wasip2 support) and target as wasip2. Now I am executing this in wasmtime . But wasmtime throws an error.

Error: failed to parse WebAssembly module

Caused by:

expected a WebAssembly module but was given a WebAssembly component

I thought the problem is because of the network call, so I changed the program to a simple program which does simple file operations. This runs successfully with wasip1 and this same program gives the same error as above with target wasip2. Even though the tinyGo dev branch has wasip2 support it's not running successfully when it comes in integration with wasmtime.
Any idea on this?

view this post on Zulip Pat Hickey (Jul 30 2024 at 21:50):

can you show what you invoked that gave that error?

view this post on Zulip celine santosh (Jul 31 2024 at 07:04):

Pat Hickey said:

can you show what you invoked that gave that error?

package main

import (
    "fmt"
    "io/ioutil"
    "net/http"
    "os"
)

func main() {
    fmt.Println("I am from Go app")

    // Make a simple HTTP GET request
    resp, err := http.Get("http://example.com")
    if err != nil {
        fmt.Println("Error:", err)
        os.Exit(1)
    }

    // Read the response body
    body, err := ioutil.ReadAll(resp.Body)
    if err != nil {
        fmt.Println("Error reading response body:", err)
        os.Exit(1)
    }
    resp.Body.Close()

    fmt.Printf("Response status: %s\n", resp.Status)
    fmt.Printf("Response body: %s\n", body)
}

Running this go program separately gives output. but when in conjunction with wasmtime gives error
Error: failed to parse WebAssembly module

Caused by:

expected a WebAssembly module but was given a WebAssembly component

view this post on Zulip Ralph (Jul 31 2024 at 07:05):

I think we're asking for the wasmtime execution command line you used

view this post on Zulip Ralph (Jul 31 2024 at 07:05):

wasmtime serve? run? -S common or some other variation

view this post on Zulip Ralph (Jul 31 2024 at 07:06):

also, would love results of wasmtime --version

view this post on Zulip Ralph (Jul 31 2024 at 07:07):

I'd also love the tinygo compilation line -- did I miss that?

view this post on Zulip celine santosh (Jul 31 2024 at 07:33):

Actually I am not using wasmtime cli , I have pulled the latest main branch https://github.com/bytecodealliance/wasmtime
and I am running this. because as part of my project I will have to do some modifications like overwrite wasi calls etc.
So in this codebase I have added a directory under examples for my app and ran the command
cargo run

here is my main.rs file

use anyhow::Result;
use wasi_common::WasiCtx;
use wasi_common::sync::WasiCtxBuilder;
use wasmtime::*;
use wasi_common::sync::{ambient_authority, Dir};


fn main() -> Result<()> {
    // Define the WASI functions globally on the `Config`.
    let engine = Engine::default();
    let mut linker = Linker::new(&engine);
    wasi_common::sync::add_to_linker(&mut linker, |s| s)?;



    // Create a WASI context and put it in a Store; all instances in the store
    // share this context. `WasiCtxBuilder` provides a number of ways to
    // configure what the target program will have access to.
    let wasi = WasiCtxBuilder::new()
        .inherit_stdio()
        .inherit_args()?
        .build();
    let mut store = Store::new(&engine, wasi);

    // Load our WebAssembly modules.
    let module_rust_app = Module::from_file(&engine, "/Users/celinesantosh/Desktop/sem_5/rust_app/target/wasm32-wasi/release/rust_app.wasm")?;
    let module_go_app = Module::from_file(&engine, "/Users/celinesantosh/Desktop/sem_5/go_program/go_app.wasm")?;

    // Instantiate the Rust app module.
    let instance_rust_app = linker.instantiate(&mut store, &module_rust_app)?;
    // Instantiate the Go app module.
    let instance_go_app = linker.instantiate(&mut store, &module_go_app)?;

    // Get the `_start` function from the Rust app instance.
    let start_rust_app = instance_rust_app.get_typed_func::<(), ()>(&mut store, "_start")?;
    // Get the `_start` function from the Go app instance.
    let start_go_app = instance_go_app.get_typed_func::<(), ()>(&mut store, "_start")?;

    // Call the `_start` function on both modules.
    start_rust_app.call(&mut store, ())?;
    start_go_app.call(&mut store, ())?;

    Ok(())
}

TinyGo compilation :
/Users/celinesantosh/Desktop/sem_5/tinygo/build/tinygo build -o go_app.wasm -target=wasip2 main.go

Thanks

A fast and secure runtime for WebAssembly. Contribute to bytecodealliance/wasmtime development by creating an account on GitHub.

view this post on Zulip Joel Dice (Jul 31 2024 at 14:21):

In your main.rs file, you're using the Wasmtime Module API and the WASIp1 support in wasi_common. That won't work for WASIp2 components. Please make sure you're using a recent version of Wasmtime and use the wasmtime::component API, along with wasmtime-wasi, which now supports WASIp2 by default.

Search for CliLinker::Component in this file for an example of how to run a WASIp2 CLI component.

A fast and secure runtime for WebAssembly. Contribute to bytecodealliance/wasmtime development by creating an account on GitHub.

view this post on Zulip celine santosh (Aug 01 2024 at 11:44):

Joel Dice said:

In your main.rs file, you're using the Wasmtime Module API and the WASIp1 support in wasi_common. That won't work for WASIp2 components. Please make sure you're using a recent version of Wasmtime and use the wasmtime::component API, along with wasmtime-wasi, which now supports WASIp2 by default.

Search for CliLinker::Component in this file for an example of how to run a WASIp2 CLI component.

Thanks for the explanation.
Are there any examples for creating the main.rs file with wasi preview2?
I can see a lot of examples with wasi preview1 in the repo though.

view this post on Zulip Joel Dice (Aug 01 2024 at 15:39):

Rust nightly now supports the wasm32-wasip2 target, so you can consider using that. For Rust stable, you can either use cargo-component (although I don't know of a wasi:cli example for cargo-component offhand) or convert the WASIp1 module produced by cargo build --target=wasm32-wasi into a WASIp2 component using wasm-tools component new --adapt wasi_snapshot_preview1.command.wasm target/wasm32-wasi/release/$APP_NAME.wasm after downloading wasi_snapshot_preview1.command.wasm.

A Cargo subcommand for creating WebAssembly components based on the component model proposal. - bytecodealliance/cargo-component

Last updated: Dec 23 2024 at 12:05 UTC