Skip to content

Commit

Permalink
Remove globals (#89)
Browse files Browse the repository at this point in the history
@achille-roussel 

This removes all of the various global maps and fixes #87

---------

Co-authored-by: Brendan Burns <[email protected]>
  • Loading branch information
brendandburns and brendanburns committed Jul 27, 2023
1 parent 8d274b9 commit 43bb9af
Show file tree
Hide file tree
Showing 13 changed files with 218 additions and 153 deletions.
9 changes: 5 additions & 4 deletions cmd/wasirun/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,7 @@ func run(wasmFile string, args []string) error {
defer system.Close(ctx)

importWasi := false
var wasiHTTP *wasi_http.WasiHTTP = nil
switch wasiHttp {
case "auto":
importWasi = wasi_http.DetectWasiHttp(wasmModule)
Expand All @@ -237,7 +238,8 @@ func run(wasmFile string, args []string) error {
return fmt.Errorf("invalid value for -http '%v', expected 'auto', 'v1' or 'none'", wasiHttp)
}
if importWasi {
if err := wasi_http.Instantiate(ctx, runtime); err != nil {
wasiHTTP = wasi_http.MakeWasiHTTP()
if err := wasiHTTP.Instantiate(ctx, runtime); err != nil {
return err
}
}
Expand All @@ -247,9 +249,8 @@ func run(wasmFile string, args []string) error {
return err
}
if len(wasiHttpAddr) > 0 {
http.HandleFunc(wasiHttpPath, func(w http.ResponseWriter, r *http.Request) {
wasi_http.HandleHTTP(w, r, instance)
})
handler := wasiHTTP.MakeHandler(instance)
http.Handle(wasiHttpPath, handler)
return http.ListenAndServe(wasiHttpAddr, nil)
}
return instance.Close(ctx)
Expand Down
6 changes: 4 additions & 2 deletions imports/wasi_http/default_http/http.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,17 @@ package default_http
import (
"context"

"github.com/stealthrocket/wasi-go/imports/wasi_http/types"
"github.com/tetratelabs/wazero"
)

const ModuleName = "default-outgoing-HTTP"

func Instantiate(ctx context.Context, r wazero.Runtime) error {
func Instantiate(ctx context.Context, r wazero.Runtime, req *types.Requests, res *types.Responses, f *types.FieldsCollection) error {
handler := &Handler{req, res, f}
_, err := r.NewHostModuleBuilder(ModuleName).
NewFunctionBuilder().WithFunc(requestFn).Export("request").
NewFunctionBuilder().WithFunc(handleFn).Export("handle").
NewFunctionBuilder().WithFunc(handler.handleFn).Export("handle").
Instantiate(ctx)
return err
}
14 changes: 10 additions & 4 deletions imports/wasi_http/default_http/request.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,23 +8,29 @@ import (
"github.com/tetratelabs/wazero/api"
)

type Handler struct {
req *types.Requests
res *types.Responses
f *types.FieldsCollection
}

// Request handles HTTP serving. It's currently unimplemented
func requestFn(_ context.Context, mod api.Module, a, b, c, d, e, f, g, h, j, k, l, m, n, o uint32) int32 {
return 0
}

// Handle handles HTTP client calls.
// The remaining parameters (b..h) are for the HTTP Options, currently unimplemented.
func handleFn(_ context.Context, mod api.Module, request, b, c, d, e, f, g, h uint32) uint32 {
req, ok := types.GetRequest(request)
func (handler *Handler) handleFn(_ context.Context, mod api.Module, request, b, c, d, e, f, g, h uint32) uint32 {
req, ok := handler.req.GetRequest(request)
if !ok {
log.Printf("Failed to get request: %v\n", request)
return 0
}
r, err := req.MakeRequest()
r, err := req.MakeRequest(handler.f)
if err != nil {
log.Println(err.Error())
return 0
}
return types.MakeResponse(r)
return handler.res.MakeResponse(r)
}
48 changes: 41 additions & 7 deletions imports/wasi_http/http.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,38 @@ import (
"github.com/tetratelabs/wazero/api"
)

func Instantiate(ctx context.Context, rt wazero.Runtime) error {
if err := types.Instantiate(ctx, rt); err != nil {
type WasiHTTP struct {
s *streams.Streams
f *types.FieldsCollection
r *types.Requests
rs *types.Responses
o *types.OutResponses
}

func MakeWasiHTTP() *WasiHTTP {
s := streams.MakeStreams()
f := types.MakeFields()
r := types.MakeRequests(s, f)
rs := types.MakeResponses(s, f)
o := types.MakeOutresponses()

return &WasiHTTP{
s: s,
f: f,
r: r,
rs: rs,
o: o,
}
}

func (w *WasiHTTP) Instantiate(ctx context.Context, rt wazero.Runtime) error {
if err := types.Instantiate(ctx, rt, w.s, w.r, w.rs, w.f, w.o); err != nil {
return err
}
if err := streams.Instantiate(ctx, rt); err != nil {
if err := streams.Instantiate(ctx, rt, w.s); err != nil {
return err
}
if err := default_http.Instantiate(ctx, rt); err != nil {
if err := default_http.Instantiate(ctx, rt, w.r, w.rs, w.f); err != nil {
return err
}
return nil
Expand All @@ -41,7 +65,17 @@ func DetectWasiHttp(module wazero.CompiledModule) bool {
return hasWasiHttp
}

func HandleHTTP(w http.ResponseWriter, r *http.Request, m api.Module) {
handler := server.WasmServer{Module: m}
handler.ServeHTTP(w, r)
func (w *WasiHTTP) MakeHandler(m api.Module) http.Handler {
return server.WasmServer{
Module: m,
Requests: w.r,
Responses: w.rs,
Fields: w.f,
OutParams: w.o,
}
}

func (w *WasiHTTP) HandleHTTP(writer http.ResponseWriter, req *http.Request, m api.Module) {
handler := w.MakeHandler(m)
handler.ServeHTTP(writer, req)
}
11 changes: 5 additions & 6 deletions imports/wasi_http/http_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ import (

"github.com/stealthrocket/wasi-go"
"github.com/stealthrocket/wasi-go/imports"
"github.com/stealthrocket/wasi-go/imports/wasi_http/server"
"github.com/tetratelabs/wazero"
"github.com/tetratelabs/wazero/sys"
)
Expand Down Expand Up @@ -103,7 +102,8 @@ func TestHttpClient(t *testing.T) {
}
defer system.Close(ctx)

Instantiate(ctx, runtime)
w := MakeWasiHTTP()
w.Instantiate(ctx, runtime)

instance, err := runtime.Instantiate(ctx, bytecode)
if err != nil {
Expand Down Expand Up @@ -170,7 +170,8 @@ func TestServer(t *testing.T) {
}
defer system.Close(ctx)

Instantiate(ctx, runtime)
w := MakeWasiHTTP()
w.Instantiate(ctx, runtime)

instance, err := runtime.Instantiate(ctx, bytecode)
if err != nil {
Expand All @@ -184,9 +185,7 @@ func TestServer(t *testing.T) {
}
}
if instance != nil {
h := server.WasmServer{
Module: instance,
}
h := w.MakeHandler(instance)
s := httptest.NewServer(h)
defer s.Close()

Expand Down
23 changes: 14 additions & 9 deletions imports/wasi_http/server/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,11 @@ import (
)

type WasmServer struct {
Module api.Module
Module api.Module
Fields *types.FieldsCollection
Requests *types.Requests
Responses *types.Responses
OutParams *types.OutResponses
}

func (w WasmServer) ServeHTTP(res http.ResponseWriter, req *http.Request) {
Expand All @@ -19,37 +23,38 @@ func (w WasmServer) ServeHTTP(res http.ResponseWriter, req *http.Request) {
res.Write([]byte("Handler not found"))
return
}

id := types.MakeRequest(req)
out := types.MakeOutparameter()
id := w.Requests.MakeRequest(req)
out := w.OutParams.MakeOutparameter()

_, err := fn.Call(context.TODO(), uint64(id), uint64(out))
if err != nil {
res.WriteHeader(500)
res.Write([]byte(err.Error()))
return
}
responseId, found := types.GetResponseByOutparameter(out)
responseId, found := w.OutParams.GetResponseByOutparameter(out)
if !found {
res.WriteHeader(500)
res.Write([]byte("Couldn't find outparameter mapping"))
return
}
r, found := types.GetResponse(responseId)
r, found := w.Responses.GetResponse(responseId)
if !found || r == nil {
res.WriteHeader(500)
res.Write([]byte("Couldn't find response"))
return
}
if headers, found := types.GetFields(r.HeaderHandle); found {
if headers, found := w.Fields.GetFields(r.HeaderHandle); found {
for key, value := range headers {
for ix := range value {
res.Header().Add(key, value[ix])
}
}
types.DeleteFields(r.HeaderHandle)
w.Fields.DeleteFields(r.HeaderHandle)
}
res.WriteHeader(r.StatusCode)
data := r.Buffer.Bytes()
res.Write(data)

types.DeleteResponse(responseId)
w.Responses.DeleteResponse(responseId)
}
8 changes: 4 additions & 4 deletions imports/wasi_http/streams/read.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@ import (
"github.com/tetratelabs/wazero/api"
)

func streamReadFn(ctx context.Context, mod api.Module, stream_handle uint32, length uint64, out_ptr uint32) {
func (s *Streams) streamReadFn(ctx context.Context, mod api.Module, stream_handle uint32, length uint64, out_ptr uint32) {
rawData := make([]byte, length)
n, done, err := Streams.Read(stream_handle, rawData)
n, done, err := s.Read(stream_handle, rawData)

// data, err := types.ResponseBody()
if err != nil {
Expand Down Expand Up @@ -41,6 +41,6 @@ func streamReadFn(ctx context.Context, mod api.Module, stream_handle uint32, len
mod.Memory().Write(out_ptr, data)
}

func dropInputStreamFn(_ context.Context, mod api.Module, stream uint32) {
Streams.DeleteStream(stream)
func (s *Streams) dropInputStreamFn(_ context.Context, mod api.Module, stream uint32) {
s.DeleteStream(stream)
}
36 changes: 19 additions & 17 deletions imports/wasi_http/streams/streams.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,53 +10,55 @@ import (

const ModuleName = "streams"

type stream struct {
type Stream struct {
reader io.Reader
writer io.Writer
}

type streams struct {
streams map[uint32]stream
type Streams struct {
streams map[uint32]Stream
streamHandleBase uint32
}

var Streams = &streams{
make(map[uint32]stream),
1,
func MakeStreams() *Streams {
return &Streams{
make(map[uint32]Stream),
1,
}
}

func Instantiate(ctx context.Context, r wazero.Runtime) error {
func Instantiate(ctx context.Context, r wazero.Runtime, s *Streams) error {
_, err := r.NewHostModuleBuilder(ModuleName).
NewFunctionBuilder().WithFunc(streamReadFn).Export("read").
NewFunctionBuilder().WithFunc(dropInputStreamFn).Export("drop-input-stream").
NewFunctionBuilder().WithFunc(writeStreamFn).Export("write").
NewFunctionBuilder().WithFunc(s.streamReadFn).Export("read").
NewFunctionBuilder().WithFunc(s.dropInputStreamFn).Export("drop-input-stream").
NewFunctionBuilder().WithFunc(s.writeStreamFn).Export("write").
Instantiate(ctx)
return err
}

func (s *streams) NewInputStream(reader io.Reader) uint32 {
func (s *Streams) NewInputStream(reader io.Reader) uint32 {
s.streamHandleBase++
s.streams[s.streamHandleBase] = stream{
s.streams[s.streamHandleBase] = Stream{
reader: reader,
writer: nil,
}
return s.streamHandleBase
}

func (s *streams) DeleteStream(handle uint32) {
func (s *Streams) DeleteStream(handle uint32) {
delete(s.streams, handle)
}

func (s *streams) NewOutputStream(writer io.Writer) uint32 {
func (s *Streams) NewOutputStream(writer io.Writer) uint32 {
s.streamHandleBase++
s.streams[s.streamHandleBase] = stream{
s.streams[s.streamHandleBase] = Stream{
reader: nil,
writer: writer,
}
return s.streamHandleBase
}

func (s *streams) Read(handle uint32, data []byte) (int, bool, error) {
func (s *Streams) Read(handle uint32, data []byte) (int, bool, error) {
stream, found := s.streams[handle]
if !found {
return 0, false, fmt.Errorf("stream not found: %d", handle)
Expand All @@ -72,7 +74,7 @@ func (s *streams) Read(handle uint32, data []byte) (int, bool, error) {
return n, false, err
}

func (s *streams) Write(handle uint32, data []byte) (int, error) {
func (s *Streams) Write(handle uint32, data []byte) (int, error) {
stream, found := s.streams[handle]
if !found {
return 0, fmt.Errorf("stream not found: %d", handle)
Expand Down
4 changes: 2 additions & 2 deletions imports/wasi_http/streams/write.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,13 @@ import (
"github.com/tetratelabs/wazero/api"
)

func writeStreamFn(_ context.Context, mod api.Module, stream, ptr, l, result_ptr uint32) {
func (s *Streams) writeStreamFn(_ context.Context, mod api.Module, stream, ptr, l, result_ptr uint32) {
data, ok := mod.Memory().Read(ptr, l)
if !ok {
log.Printf("Body read failed!\n")
return
}
n, err := Streams.Write(stream, data)
n, err := s.Write(stream, data)
if err != nil {
log.Printf("Failed to write: %v\n", err.Error())
}
Expand Down
Loading

0 comments on commit 43bb9af

Please sign in to comment.