api7 / wasm-nginx-module

Run Wasm in OpenResty/Nginx
Apache License 2.0
184 stars 22 forks source link

new ABI with metric #147

Closed Sn0rt closed 1 year ago

Sn0rt commented 1 year ago

I get some error info after load coraza-filter

2023/08/09 11:12:18 [error] 660175#660175: failed to new instance: unknown import: `env::proxy_increment_metric` has not been defined
2023/08/09 11:12:18 [error] 660175#660175: *1 [lua] plugin.lua:135: load_plugin(): failed to load plugin [coraza-filter] err: failed to load wasm plugin, context: init_worker_by_lua*

inspect the code of ABI

proxy_define_metric
proxy_increment_metric
proxy_record_metric
proxy_get_metric

the proxy-wasm-go-sdk need this API


func exportHostABI(ctx context.Context, r wazero.Runtime) error {
    _, err := r.NewHostModuleBuilder("env").
        NewFunctionBuilder().
        WithFunc(func(ctx context.Context, mod api.Module, logLevel uint32, messageData uint32, messageSize uint32) uint32 {
            messageDataPtr := wasmBytePtr(ctx, mod, messageData, messageSize)
            return uint32(internal.ProxyLog(internal.LogLevel(logLevel), messageDataPtr, int(messageSize)))
        }).
        Export("proxy_log").
        NewFunctionBuilder().
        WithFunc(func(ctx context.Context, mod api.Module, pathData uint32, pathSize uint32, valueData uint32, valueSize uint32) uint32 {
            pathDataPtr := wasmBytePtr(ctx, mod, pathData, pathSize)
            valueDataPtr := wasmBytePtr(ctx, mod, valueData, valueSize)
            return uint32(internal.ProxySetProperty(pathDataPtr, int(pathSize), valueDataPtr, int(valueSize)))
        }).
        Export("proxy_set_property").
        NewFunctionBuilder().
        WithFunc(func(ctx context.Context, mod api.Module, pathData uint32, pathSize uint32,
            returnValueData uint32, returnValueSize uint32) uint32 {
            pathDataPtr := wasmBytePtr(ctx, mod, pathData, pathSize)
            var returnValueHostPtr *byte
            var returnValueSizePtr int
            ret := uint32(internal.ProxyGetProperty(pathDataPtr, int(pathSize), &returnValueHostPtr, &returnValueSizePtr))
            copyBytesToWasm(ctx, mod, returnValueHostPtr, returnValueSizePtr, returnValueData, returnValueSize)
            return ret
        }).
        Export("proxy_get_property").
        NewFunctionBuilder().
        WithFunc(func(ctx context.Context, mod api.Module,
            statusCode uint32, statusCodeDetailData uint32, statusCodeDetailsSize uint32,
            bodyData uint32, bodySize uint32, headersData uint32, headersSize uint32, grpcStatus int32) uint32 {
            statusCodeDetailDataPtr := wasmBytePtr(ctx, mod, statusCodeDetailData, statusCodeDetailsSize)
            bodyDataPtr := wasmBytePtr(ctx, mod, bodyData, bodySize)
            headersDataPtr := wasmBytePtr(ctx, mod, headersData, headersSize)
            return uint32(internal.ProxySendLocalResponse(statusCode, statusCodeDetailDataPtr, int(statusCodeDetailsSize),
                bodyDataPtr, int(bodySize), headersDataPtr, int(headersSize), grpcStatus))
        }).
        Export("proxy_send_local_response").
        NewFunctionBuilder().
        WithFunc(func(ctx context.Context, mod api.Module, keyData uint32, keySize uint32,
            returnValueData uint32, returnValueSize uint32, returnCas uint32) uint32 {
            keyDataPtr := wasmBytePtr(ctx, mod, keyData, keySize)
            var returnValueHostPtr *byte
            var returnValueSizePtr int
            var returnCasPtr uint32
            ret := uint32(internal.ProxyGetSharedData(keyDataPtr, int(keySize), &returnValueHostPtr, &returnValueSizePtr, &returnCasPtr))
            copyBytesToWasm(ctx, mod, returnValueHostPtr, returnValueSizePtr, returnValueData, returnValueSize)
            handleMemoryStatus(mod.Memory().WriteUint32Le(returnCas, returnCasPtr))
            return ret
        }).
        Export("proxy_get_shared_data").
        NewFunctionBuilder().
        WithFunc(func(ctx context.Context, mod api.Module, keyData uint32, keySize uint32, valueData uint32, valueSize uint32, cas uint32) uint32 {
            keyDataPtr := wasmBytePtr(ctx, mod, keyData, keySize)
            valueDataPtr := wasmBytePtr(ctx, mod, valueData, valueSize)
            return uint32(internal.ProxySetSharedData(keyDataPtr, int(keySize), valueDataPtr, int(valueSize), cas))
        }).
        Export("proxy_set_shared_data").
        NewFunctionBuilder().
        WithFunc(func(ctx context.Context, mod api.Module, nameData uint32, nameSize uint32, returnID uint32) uint32 {
            namePtr := wasmBytePtr(ctx, mod, nameData, nameSize)
            var returnIDPtr uint32
            ret := uint32(internal.ProxyRegisterSharedQueue(namePtr, int(nameSize), &returnIDPtr))
            handleMemoryStatus(mod.Memory().WriteUint32Le(returnID, returnIDPtr))
            return ret
        }).
        Export("proxy_register_shared_queue").
        NewFunctionBuilder().
        WithFunc(func(ctx context.Context, mod api.Module, vmIDData uint32, vmIDSize uint32, nameData uint32, nameSize uint32, returnID uint32) uint32 {
            vmID := wasmBytePtr(ctx, mod, vmIDData, vmIDSize)
            namePtr := wasmBytePtr(ctx, mod, nameData, nameSize)
            var returnIDPtr uint32
            ret := uint32(internal.ProxyResolveSharedQueue(vmID, int(vmIDSize), namePtr, int(nameSize), &returnIDPtr))
            handleMemoryStatus(mod.Memory().WriteUint32Le(returnID, returnIDPtr))
            return ret
        }).
        Export("proxy_resolve_shared_queue").
        NewFunctionBuilder().
        WithFunc(func(ctx context.Context, mod api.Module, queueID uint32, returnValueData uint32, returnValueSize uint32) uint32 {
            var returnValueHostPtr *byte
            var returnValueSizePtr int
            ret := uint32(internal.ProxyDequeueSharedQueue(queueID, &returnValueHostPtr, &returnValueSizePtr))
            copyBytesToWasm(ctx, mod, returnValueHostPtr, returnValueSizePtr, returnValueData, returnValueSize)
            return ret
        }).
        Export("proxy_dequeue_shared_queue").
        NewFunctionBuilder().
        WithFunc(func(ctx context.Context, mod api.Module, queueID uint32, valueData uint32, valueSize uint32) uint32 {
            valuePtr := wasmBytePtr(ctx, mod, valueData, valueSize)
            return uint32(internal.ProxyEnqueueSharedQueue(queueID, valuePtr, int(valueSize)))
        }).
        Export("proxy_enqueue_shared_queue").
        NewFunctionBuilder().
        WithFunc(func(ctx context.Context, mod api.Module, mapType uint32, keyData uint32, keySize uint32, returnValueData uint32, returnValueSize uint32) uint32 {
            keyPtr := wasmBytePtr(ctx, mod, keyData, keySize)
            var retValDataHostPtr *byte
            var retValSizePtr int
            ret := uint32(internal.ProxyGetHeaderMapValue(internal.MapType(mapType), keyPtr, int(keySize), &retValDataHostPtr, &retValSizePtr))
            copyBytesToWasm(ctx, mod, retValDataHostPtr, retValSizePtr, returnValueData, returnValueSize)
            return ret
        }).
        Export("proxy_get_header_map_value").
        NewFunctionBuilder().
        WithFunc(func(ctx context.Context, mod api.Module, mapType uint32, keyData uint32, keySize uint32, valueData uint32, valueSize uint32) uint32 {
            keyPtr := wasmBytePtr(ctx, mod, keyData, keySize)
            valuePtr := wasmBytePtr(ctx, mod, valueData, valueSize)
            return uint32(internal.ProxyAddHeaderMapValue(internal.MapType(mapType), keyPtr, int(keySize), valuePtr, int(valueSize)))
        }).
        Export("proxy_add_header_map_value").
        NewFunctionBuilder().
        WithFunc(func(ctx context.Context, mod api.Module, mapType uint32, keyData uint32, keySize uint32, valueData uint32, valueSize uint32) uint32 {
            keyPtr := wasmBytePtr(ctx, mod, keyData, keySize)
            valuePtr := wasmBytePtr(ctx, mod, valueData, valueSize)
            return uint32(internal.ProxyReplaceHeaderMapValue(internal.MapType(mapType), keyPtr, int(keySize), valuePtr, int(valueSize)))
        }).
        Export("proxy_replace_header_map_value").
        NewFunctionBuilder().
        WithFunc(func(streamType uint32) uint32 {
            return uint32(internal.ProxyContinueStream(internal.StreamType(streamType)))
        }).
        Export("proxy_continue_stream").
        NewFunctionBuilder().
        WithFunc(func(streamType uint32) uint32 {
            return uint32(internal.ProxyCloseStream(internal.StreamType(streamType)))
        }).
        Export("proxy_close_stream").
        NewFunctionBuilder().
        WithFunc(func(ctx context.Context, mod api.Module, mapType uint32, keyData uint32, keySize uint32) uint32 {
            keyPtr := wasmBytePtr(ctx, mod, keyData, keySize)
            return uint32(internal.ProxyRemoveHeaderMapValue(internal.MapType(mapType), keyPtr, int(keySize)))
        }).
        Export("proxy_remove_header_map_value").
        NewFunctionBuilder().
        WithFunc(func(ctx context.Context, mod api.Module, mapType uint32, returnValueData uint32, returnValueSize uint32) uint32 {
            var returnValueHostPtr *byte
            var returnValueSizePtr int
            ret := uint32(internal.ProxyGetHeaderMapPairs(internal.MapType(mapType), &returnValueHostPtr, &returnValueSizePtr))
            copyBytesToWasm(ctx, mod, returnValueHostPtr, returnValueSizePtr, returnValueData, returnValueSize)
            return ret
        }).
        Export("proxy_get_header_map_pairs").
        NewFunctionBuilder().
        WithFunc(func(ctx context.Context, mod api.Module, mapType uint32, mapData uint32, mapSize uint32) uint32 {
            mapPtr := wasmBytePtr(ctx, mod, mapData, mapSize)
            return uint32(internal.ProxySetHeaderMapPairs(internal.MapType(mapType), mapPtr, int(mapSize)))
        }).
        Export("proxy_set_header_map_pairs").
        NewFunctionBuilder().
        WithFunc(func(ctx context.Context, mod api.Module, bufferType uint32, start uint32, maxSize uint32, returnBufferData uint32, returnBufferSize uint32) uint32 {
            var returnBufferDataHostPtr *byte
            var returnBufferSizePtr int
            ret := uint32(internal.ProxyGetBufferBytes(internal.BufferType(bufferType), int(start), int(maxSize), &returnBufferDataHostPtr, &returnBufferSizePtr))
            copyBytesToWasm(ctx, mod, returnBufferDataHostPtr, returnBufferSizePtr, returnBufferData, returnBufferSize)
            return ret
        }).
        Export("proxy_get_buffer_bytes").
        NewFunctionBuilder().
        WithFunc(func(ctx context.Context, mod api.Module, bufferType uint32, start uint32, maxSize uint32, bufferData uint32, bufferSize uint32) uint32 {
            bufferPtr := wasmBytePtr(ctx, mod, bufferData, bufferSize)
            return uint32(internal.ProxySetBufferBytes(internal.BufferType(bufferType), int(start), int(maxSize), bufferPtr, int(bufferSize)))
        }).
        Export("proxy_set_buffer_bytes").
        NewFunctionBuilder().
        WithFunc(func(ctx context.Context, mod api.Module, upstreamData uint32, upstreamSize uint32, headerData uint32, headerSize uint32, bodyData uint32, bodySize uint32, trailersData uint32, trailersSize uint32, timeout uint32, calloutIDPtr uint32) uint32 {
            upstreamPtr := wasmBytePtr(ctx, mod, upstreamData, upstreamSize)
            headerPtr := wasmBytePtr(ctx, mod, headerData, headerSize)
            bodyPtr := wasmBytePtr(ctx, mod, bodyData, bodySize)
            trailersPtr := wasmBytePtr(ctx, mod, trailersData, trailersSize)
            var calloutID uint32
            ret := uint32(internal.ProxyHttpCall(upstreamPtr, int(upstreamSize), headerPtr, int(headerSize), bodyPtr, int(bodySize), trailersPtr, int(trailersSize), timeout, &calloutID))
            handleMemoryStatus(mod.Memory().WriteUint32Le(calloutIDPtr, calloutID))

            // Finishing proxy_http_call executes a callback, not a plugin lifecycle method, unlike every other host function which would then end up in wasm.
            // We can work around this by registering a callback here to go back to the wasm.
            internal.RegisterHttpCallout(calloutID, func(numHeaders, bodySize, numTrailers int) {
                proxyOnHttpCallResponse := mod.ExportedFunction("proxy_on_http_call_response")
                _, err := proxyOnHttpCallResponse.Call(ctx, uint64(getPluginContextID(ctx)), uint64(calloutID), uint64(numHeaders), uint64(bodySize), uint64(numTrailers))
                if err != nil {
                    panic(err)
                }
            })

            return ret
        }).
        Export("proxy_http_call").
        NewFunctionBuilder().
        WithFunc(func(ctx context.Context, mod api.Module, funcNamePtr uint32, funcNameSize uint32, paramPtr uint32, paramSize uint32, returnData uint32, returnSize uint32) uint32 {
            funcName := wasmBytePtr(ctx, mod, funcNamePtr, funcNameSize)
            paramHostPtr := wasmBytePtr(ctx, mod, paramPtr, paramSize)
            var returnDataHostPtr *byte
            var returnDataSizePtr int
            ret := uint32(internal.ProxyCallForeignFunction(funcName, int(funcNameSize), paramHostPtr, int(paramSize), &returnDataHostPtr, &returnDataSizePtr))
            copyBytesToWasm(ctx, mod, returnDataHostPtr, returnDataSizePtr, returnData, returnSize)
            return ret
        }).
        Export("proxy_call_foreign_function").
        NewFunctionBuilder().
        WithFunc(func(period uint32) uint32 {
            return uint32(internal.ProxySetTickPeriodMilliseconds(period))
        }).
        Export("proxy_set_tick_period_milliseconds").
        NewFunctionBuilder().
        WithFunc(func(contextID uint32) uint32 {
            return uint32(internal.ProxySetEffectiveContext(contextID))
        }).
        Export("proxy_set_effective_context").
        NewFunctionBuilder().
        WithFunc(func() uint32 {
            return uint32(internal.ProxyDone())
        }).
        Export("proxy_done").
        NewFunctionBuilder().
        WithFunc(func(ctx context.Context, mod api.Module, metricType uint32, metricNameData uint32, metricNameSize uint32, returnMetricIDPtr uint32) uint32 {
            metricName := wasmBytePtr(ctx, mod, metricNameData, metricNameSize)
            var returnMetricID uint32
            ret := uint32(internal.ProxyDefineMetric(internal.MetricType(metricType), metricName, int(metricNameSize), &returnMetricID))
            handleMemoryStatus(mod.Memory().WriteUint32Le(returnMetricIDPtr, returnMetricID))
            return ret
        }).
        Export("proxy_define_metric").
        NewFunctionBuilder().
        WithFunc(func(metricID uint32, offset int64) uint32 {
            return uint32(internal.ProxyIncrementMetric(metricID, offset))
        }).
        Export("proxy_increment_metric").
        NewFunctionBuilder().
        WithFunc(func(metricID uint32, value uint64) uint32 {
            return uint32(internal.ProxyRecordMetric(metricID, value))
        }).
        Export("proxy_record_metric").
        NewFunctionBuilder().
        WithFunc(func(ctx context.Context, mod api.Module, metricID uint32, returnMetricValue uint32) uint32 {
            var returnMetricValuePtr uint64
            ret := uint32(internal.ProxyGetMetric(metricID, &returnMetricValuePtr))
            handleMemoryStatus(mod.Memory().WriteUint64Le(returnMetricValue, returnMetricValuePtr))
            return ret
        }).
        Export("proxy_get_metric").
        Instantiate(ctx)
    return err
}