import * as imports from "./imports" ; import { free } from "./malloc" ; import { proc_exit } from "bindings/wasi_unstable" ; @ global export function abort_proc_exit ( message , fileName , lineNumber , columnNumber ) { let logMessage = "" ; if ( message !== null ) { logMessage += message . toString ( ) ; } if ( fileName !== null ) { logMessage += " at: " + fileName . toString ( ) + "(" + lineNumber . toString ( ) + ":" + columnNumber . toString ( ) + ")" ; } log ( LogLevelValues . critical , logMessage ) ; proc_exit ( 255 ) ; } function CHECK_RESULT ( c ) { if ( c != WasmResultValues . Ok ) { log ( LogLevelValues . critical , c . toString ( ) ) ; throw new Error ( ":(" ) ; } } export class Reference < T > { data : T ; ptr ( ) { return changetype < usize > ( this ) + offsetof < Reference < T > > ( "data" ) ; } } class ArrayBufferReference { private buffer : usize ; private size : usize ; constructor ( ) { } sizePtr ( ) { return changetype < usize > ( this ) + offsetof < ArrayBufferReference > ( "size" ) ; } bufferPtr ( ) { return changetype < usize > ( this ) + offsetof < ArrayBufferReference > ( "buffer" ) ; } toArrayBuffer ( ) { if ( this . size == 0 ) { return new ArrayBuffer ( 0 ) ; } let array = changetype < ArrayBuffer > ( this . buffer ) ; free ( this . buffer ) ; return array ; } } var globalArrayBufferReference = new ArrayBufferReference ( ) ; let globalU32Ref = new Reference < u32 > ( ) ; let globalLogLevelRef = new Reference < imports . LogLevel > ( ) ; let globalU64Ref = new Reference < u64 > ( ) ; let globalUsizeRef = new Reference < usize > ( ) ; export class HeaderPair { key : ArrayBuffer ; value : ArrayBuffer ; toString ( ) { return this . key . toString ( ) + ":" + this . value . toString ( ) ; } constructor ( header_key_data , header_value_data ) { this . key = header_key_data ; this . value = header_value_data ; } } export function makeHeaderPair ( key , value ) { let key_arr = String . UTF8 . encode ( key ) ; let value_arr = String . UTF8 . encode ( value ) ; return new HeaderPair ( key_arr , value_arr ) ; } export type Headers = Array < HeaderPair > ; export enum LogLevelValues { trace , debug , info , warn , error , critical } export enum FilterStatusValues { Continue = 0 , StopIteration = 1 } export enum FilterHeadersStatusValues { Continue = 0 , StopIteration = 1 , ContinueAndEndStream = 2 , StopAllIterationAndBuffer = 3 , StopAllIterationAndWatermark = 4 } export enum FilterMetadataStatusValues { Continue = 0 } export enum FilterTrailersStatusValues { Continue = 0 , StopIteration = 1 } export enum FilterDataStatusValues { Continue = 0 , StopIterationAndBuffer = 1 , StopIterationAndWatermark = 2 , StopIterationNoBuffer = 3 } export enum GrpcStatusValues { Ok = 0 , Canceled = 1 , Unknown = 2 , InvalidArgument = 3 , DeadlineExceeded = 4 , NotFound = 5 , AlreadyExists = 6 , PermissionDenied = 7 , ResourceExhausted = 8 , FailedPrecondition = 9 , Aborted = 10 , OutOfRange = 11 , Unimplemented = 12 , Internal = 13 , Unavailable = 14 , DataLoss = 15 , Unauthenticated = 16 , MaximumValid = Unauthenticated , InvalidCode = - 1 } export enum MetricTypeValues { Counter = 0 , Gauge = 1 , Histogram = 2 } export enum PeerTypeValues { Unknown = 0 , Local = 1 , Remote = 2 } export enum WasmResultValues { Ok = 0 , NotFound = 1 , BadArgument = 2 , SerializationFailure = 3 , ParseFailure = 4 , BadExpression = 5 , InvalidMemoryAccess = 6 , Empty = 7 , CasMismatch = 8 , ResultMismatch = 9 , InternalFailure = 10 , BrokenConnection = 11 , Unimplemented = 12 } export enum HeaderMapTypeValues { RequestHeaders = 0 , RequestTrailers = 1 , ResponseHeaders = 2 , ResponseTrailers = 3 , GrpcReceiveInitialMetadata = 4 , GrpcReceiveTrailingMetadata = 5 , HttpCallResponseHeaders = 6 , HttpCallResponseTrailers = 7 , MAX = 7 } export enum BufferTypeValues { HttpRequestBody = 0 , HttpResponseBody = 1 , NetworkDownstreamData = 2 , NetworkUpstreamData = 3 , HttpCallResponseBody = 4 , GrpcReceiveBuffer = 5 , VmConfiguration = 6 , PluginConfiguration = 7 , CallData = 8 , MAX = 8 } export enum BufferFlagsValues { EndOfStream = 1 } export enum StreamTypeValues { Request = 0 , Response = 1 , Downstream = 2 , Upstream = 3 , MAX = 3 } export function log ( level , logMessage ) { let buffer = String . UTF8 . encode ( logMessage ) ; imports . proxy_log ( level as imports . LogLevel , changetype < usize > ( buffer ) , buffer . byteLength ) ; } export function logLevel ( ) { let level = globalLogLevelRef ; CHECK_RESULT ( imports . proxy_get_log_level ( level . ptr ( ) ) ) ; return level . data ; } class StatusWithData { status : u32 ; data : ArrayBuffer ; } export function get_status ( ) { let status = globalU32Ref ; CHECK_RESULT ( imports . proxy_get_status ( status . ptr ( ) , globalArrayBufferReference . bufferPtr ( ) , globalArrayBufferReference . sizePtr ( ) ) ) ; return { status : status . data , data : globalArrayBufferReference . toArrayBuffer ( ) } ; } export function set_tick_period_milliseconds ( millisecond ) { CHECK_RESULT ( imports . proxy_set_tick_period_milliseconds ( millisecond ) ) ; } export function get_current_time_nanoseconds ( ) { let nanos = globalU64Ref ; CHECK_RESULT ( imports . proxy_get_current_time_nanoseconds ( nanos . ptr ( ) ) ) ; return nanos . data ; } export function get_property ( path ) { let buffer = String . UTF8 . encode ( path ) ; CHECK_RESULT ( imports . proxy_get_property ( changetype < usize > ( buffer ) , buffer . byteLength , globalArrayBufferReference . bufferPtr ( ) , globalArrayBufferReference . sizePtr ( ) ) ) ; return globalArrayBufferReference . toArrayBuffer ( ) ; } export function set_property ( path , data ) { let buffer = String . UTF8 . encode ( path ) ; return imports . proxy_set_property ( changetype < usize > ( buffer ) , buffer . byteLength , changetype < usize > ( data ) , data . byteLength ) ; } function pairsSize ( headers ) { let size = 4 ; for ( let i = 0 ; i < headers . length ; i ++ ) { let header = headers [ i ] ; size += 8 ; size += header . key . byteLength + 1 ; size += header . value . byteLength + 1 ; } return size ; } function serializeHeaders ( headers ) { let result = new ArrayBuffer ( pairsSize ( headers ) ) ; let sizes = Uint32Array . wrap ( result , 0 , 1 + 2 * headers . length ) ; sizes [ 0 ] = headers . length ; let index = 1 ; for ( let i = 0 ; i < headers . length ; i ++ ) { let header = headers [ i ] ; sizes [ index ] = header . key . byteLength ; index ++ ; sizes [ index ] = header . value . byteLength ; index ++ ; } let data = Uint8Array . wrap ( result , sizes . byteLength ) ; let currentOffset = 0 ; for ( let i = 0 ; i < headers . length ; i ++ ) { let header = headers [ i ] ; let wrappedKey = Uint8Array . wrap ( header . key ) ; let keyData = data . subarray ( currentOffset , currentOffset + wrappedKey . byteLength ) ; for ( let i = 0 ; i < wrappedKey . byteLength ; i ++ ) { keyData [ i ] = wrappedKey [ i ] ; } currentOffset += wrappedKey . byteLength + 1 ; let wrappedValue = Uint8Array . wrap ( header . value ) ; let valueData = data . subarray ( currentOffset , currentOffset + wrappedValue . byteLength ) ; for ( let i = 0 ; i < wrappedValue . byteLength ; i ++ ) { valueData [ i ] = wrappedValue [ i ] ; } currentOffset += wrappedValue . byteLength + 1 ; } return result ; } function deserializeHeaders ( headers ) { if ( headers . byteLength == 0 ) { return [ ] ; } let numheaders = Uint32Array . wrap ( headers , 0 , 1 ) [ 0 ] ; let sizes = Uint32Array . wrap ( headers , sizeof < u32 > ( ) , 2 * numheaders ) ; let data = headers . slice ( sizeof < u32 > ( ) * ( 1 + 2 * numheaders ) ) ; let result = [ ] ; let sizeIndex = 0 ; let dataIndex = 0 ; for ( let i = 0 ; i < numheaders ; i ++ ) { let keySize = sizes [ sizeIndex ] ; sizeIndex ++ ; let header_key_data = data . slice ( dataIndex , dataIndex + keySize ) ; dataIndex += keySize + 1 ; let valueSize = sizes [ sizeIndex ] ; sizeIndex ++ ; let header_value_data = data . slice ( dataIndex , dataIndex + valueSize ) ; dataIndex += valueSize + 1 ; let pair = new HeaderPair ( header_key_data , header_value_data ) ; result . push ( pair ) ; } return result ; } export function continue_request ( ) { return imports . proxy_continue_stream ( StreamTypeValues . Request ) ; } export function continue_response ( ) { return imports . proxy_continue_stream ( StreamTypeValues . Response ) ; } export function send_local_response ( response_code , response_code_details , body , additional_headers , grpc_status ) { let response_code_details_buffer = String . UTF8 . encode ( response_code_details ) ; let headers = serializeHeaders ( additional_headers ) ; return imports . proxy_send_local_response ( response_code , changetype < usize > ( response_code_details_buffer ) , response_code_details_buffer . byteLength , changetype < usize > ( body ) , body . byteLength , changetype < usize > ( headers ) , headers . byteLength , grpc_status ) ; } export function clear_route_cache ( ) { return imports . proxy_clear_route_cache ( ) ; } class GetSharedData { value : ArrayBuffer | null ; result : WasmResultValues ; cas : u32 ; } export function get_shared_data ( key ) { const key_buffer = String . UTF8 . encode ( key ) ; let cas = globalUsizeRef ; let data = globalArrayBufferReference ; let result = new GetSharedData ( ) ; result . result = imports . proxy_get_shared_data ( changetype < usize > ( key_buffer ) , key_buffer . byteLength , data . bufferPtr ( ) , data . sizePtr ( ) , cas . ptr ( ) ) ; if ( result . result == WasmResultValues . Ok ) { result . value = data . toArrayBuffer ( ) ; result . cas = cas . data ; } return result ; } export function set_shared_data ( key , value , cas = 0 ) { const key_buffer = String . UTF8 . encode ( key ) ; return imports . proxy_set_shared_data ( changetype < usize > ( key_buffer ) , key_buffer . byteLength , changetype < usize > ( value ) , value . byteLength , cas ) ; } class TokenSharedQueueResult { result : WasmResultValues ; token : u32 ; } export function register_shared_queue ( queue_name ) { let qid = globalU32Ref ; let queue_name_buffer = String . UTF8 . encode ( queue_name ) ; let result = new TokenSharedQueueResult ( ) ; result . result = imports . proxy_register_shared_queue ( changetype < usize > ( queue_name_buffer ) , queue_name_buffer . byteLength , qid . ptr ( ) ) ; if ( result . result == WasmResultValues . Ok ) { result . token = qid . data ; } return result ; } export function resolve_shared_queue ( vm_id , queue_name ) { let qid = globalU32Ref ; let vm_id_buffer = String . UTF8 . encode ( vm_id ) ; let queue_name_buffer = String . UTF8 . encode ( queue_name ) ; let result = new TokenSharedQueueResult ( ) ; result . result = imports . proxy_resolve_shared_queue ( changetype < usize > ( vm_id_buffer ) , vm_id_buffer . byteLength , changetype < usize > ( queue_name_buffer ) , queue_name_buffer . byteLength , qid . ptr ( ) ) ; if ( result . result == WasmResultValues . Ok ) { result . token = qid . data ; } return result ; } class DequeueSharedQueueResult { result : WasmResultValues ; data : ArrayBuffer | null ; } export function dequeue_shared_queue ( token ) { let result = new DequeueSharedQueueResult ( ) ; let data = globalArrayBufferReference ; let res = imports . proxy_dequeue_shared_queue ( token , data . bufferPtr ( ) , data . sizePtr ( ) ) ; result . result = res ; if ( res == WasmResultValues . Ok ) { result . data = data . toArrayBuffer ( ) ; } return result ; } export function enqueue_shared_queue ( token , data ) { return imports . proxy_enqueue_shared_queue ( token , changetype < usize > ( data ) , data . byteLength ) ; } export function add_header_map_value ( typ , key , value ) { return imports . proxy_add_header_map_value ( typ , changetype < usize > ( key ) , key . byteLength , changetype < usize > ( value ) , value . byteLength ) ; } export function add_header_map_value_string ( typ , key , value ) { let key_arr = String . UTF8 . encode ( key ) ; let value_arr = String . UTF8 . encode ( value ) ; return imports . proxy_add_header_map_value ( typ , changetype < usize > ( key_arr ) , key_arr . byteLength , changetype < usize > ( value_arr ) , value_arr . byteLength ) ; } class HeaderStreamManipulator { typ : HeaderMapTypeValues ; constructor ( typ ) { this . typ = typ ; } param key param value add ( key , value ) { add_header_map_value_string ( this . typ , key , value ) ; } param key param value replace ( key , value ) { replace_header_map_value_string ( this . typ , key , value ) ; } param key return get ( key ) { return get_header_map_value_string ( this . typ , key ) ; } param key remove ( key ) { remove_header_map_value_string ( this . typ , key ) ; } /**
     * get all headers.
     */ get_headers ( ) { return get_header_map_pairs ( this . typ ) ; } /**
     * set all headers.
     */ set_headers ( headers ) { return set_header_map_pairs ( this . typ , headers ) ; } } /**
 * Manipulate request and response headers.
 * Note that request header manipulation will only have effect before the request goes upstream.
 * Response header manipulation can happen only after the response was started and before it
 * was sent downstream.
 */ class HeaderMapManipulator { request : HeaderStreamManipulator ; response : HeaderStreamManipulator ; http_callback : HeaderStreamManipulator ; constructor ( request , response , http_callback ) { this . request = request ; this . response = response ; this . http_callback = http_callback ; } } /**
 * Methods to manipulate the current stream. No need to instantiate this class. use the global
 * stream_context variable.
 */ class StreamContext { headers : HeaderMapManipulator ; trailers : HeaderMapManipulator ; constructor ( headers , trailers ) { this . headers = headers ; this . trailers = trailers ; } } /**
 * Use this variable to manipulate the current stream.
 */ export var stream_context = new StreamContext ( new HeaderMapManipulator ( new HeaderStreamManipulator ( HeaderMapTypeValues . RequestHeaders ) , new HeaderStreamManipulator ( HeaderMapTypeValues . ResponseHeaders ) , new HeaderStreamManipulator ( HeaderMapTypeValues . HttpCallResponseHeaders ) ) , new HeaderMapManipulator ( new HeaderStreamManipulator ( HeaderMapTypeValues . RequestTrailers ) , new HeaderStreamManipulator ( HeaderMapTypeValues . ResponseTrailers ) , new HeaderStreamManipulator ( HeaderMapTypeValues . HttpCallResponseTrailers ) ) ) ; function get_header_map_value_string ( typ , key ) { const key_buffer = String . UTF8 . encode ( key ) ; let result = get_header_map_value ( typ , key_buffer ) ; return String . UTF8 . decode ( result ) ; } export function get_header_map_value ( typ , key ) { let result = imports . proxy_get_header_map_value ( typ , changetype < usize > ( key ) , key . byteLength , globalArrayBufferReference . bufferPtr ( ) , globalArrayBufferReference . sizePtr ( ) ) ; if ( result == WasmResultValues . Ok ) { return globalArrayBufferReference . toArrayBuffer ( ) ; } return new ArrayBuffer ( 0 ) ; } function get_header_map_flat_pairs ( typ ) { let result = imports . proxy_get_header_map_pairs ( typ , globalArrayBufferReference . bufferPtr ( ) , globalArrayBufferReference . sizePtr ( ) ) ; if ( result == WasmResultValues . Ok ) { return globalArrayBufferReference . toArrayBuffer ( ) ; } return new ArrayBuffer ( 0 ) ; } function get_header_map_pairs ( typ ) { let pairs = get_header_map_flat_pairs ( typ ) ; return deserializeHeaders ( pairs ) ; } function set_header_map_flat_pairs ( typ , flat_headers ) { CHECK_RESULT ( imports . proxy_set_header_map_pairs ( typ , changetype < usize > ( flat_headers ) , flat_headers . byteLength ) ) ; } function set_header_map_pairs ( typ , headers ) { let flat_headers = serializeHeaders ( headers ) ; set_header_map_flat_pairs ( typ , flat_headers ) ; } export function replace_header_map_value_string ( typ , key , value ) { let key_arr = String . UTF8 . encode ( key ) ; let value_arr = String . UTF8 . encode ( value ) ; replace_header_map_value ( typ , key_arr , value_arr ) ; } export function replace_header_map_value ( typ , key , value ) { CHECK_RESULT ( imports . proxy_replace_header_map_value ( typ , changetype < usize > ( key ) , key . byteLength , changetype < usize > ( value ) , value . byteLength ) ) ; } export function remove_header_map_value_string ( typ , key ) { let key_arr = String . UTF8 . encode ( key ) ; remove_header_map_value ( typ , key_arr ) ; } export function remove_header_map_value ( typ , key ) { CHECK_RESULT ( imports . proxy_remove_header_map_value ( typ , changetype < usize > ( key ) , key . byteLength ) ) ; } export function get_header_map_size ( typ ) { let size = globalUsizeRef ; CHECK_RESULT ( imports . proxy_get_header_map_size ( typ , size . ptr ( ) ) ) ; return size . data ; } export function get_buffer_bytes ( typ , start , length ) { let result = imports . proxy_get_buffer_bytes ( typ , start , length , globalArrayBufferReference . bufferPtr ( ) , globalArrayBufferReference . sizePtr ( ) ) ; if ( result == WasmResultValues . Ok ) { return globalArrayBufferReference . toArrayBuffer ( ) ; } return new ArrayBuffer ( 0 ) ; } class BufferStatusResult { result : WasmResultValues ; length : usize ; flags : u32 ; } export function get_buffer_status ( typ ) { let length_ptr = globalUsizeRef ; let flags_ptr = globalU32Ref ; let result = imports . proxy_get_buffer_status ( typ , length_ptr . ptr ( ) , flags_ptr . ptr ( ) ) ; let resultTuple = new BufferStatusResult ( ) ; resultTuple . result = result ; if ( result == WasmResultValues . Ok ) { resultTuple . length = length_ptr . data ; resultTuple . flags = flags_ptr . data ; return resultTuple ; } return resultTuple ; } class Metric { metric_id : u32 ; constructor ( typ , name ) { let metric_res = define_metric ( typ , name ) ; if ( metric_res . result != WasmResultValues . Ok ) { throw new Error ( "can't define metric" ) ; } this . metric_id = metric_res . metric_id ; } } export class Gauge extends Metric { constructor ( name ) { super ( MetricTypeValues . Gauge , name ) ; } increment ( offset ) { return imports . proxy_increment_metric ( this . metric_id , offset ) ; } record ( metric_id , value ) { return imports . proxy_record_metric ( metric_id , value ) ; } } export class Histogram extends Metric { constructor ( name ) { super ( MetricTypeValues . Histogram , name ) ; } increment ( offset ) { return imports . proxy_increment_metric ( this . metric_id , offset ) ; } record ( metric_id , value ) { return imports . proxy_record_metric ( metric_id , value ) ; } } export class Counter extends Metric { constructor ( name ) { super ( MetricTypeValues . Counter , name ) ; } increment ( offset ) { return imports . proxy_increment_metric ( this . metric_id , offset ) ; } } class MetricResult { result : WasmResultValues ; metric_id : u32 ; } export function define_metric ( typ , name ) { let metric_id = globalU32Ref ; let nameutf8 = String . UTF8 . encode ( name ) ; let res = imports . proxy_define_metric ( typ , changetype < usize > ( nameutf8 ) , nameutf8 . byteLength , metric_id . ptr ( ) ) ; let result = new MetricResult ( ) ; result . result = res ; if ( res == WasmResultValues . Ok ) { result . metric_id = metric_id . data ; } return result ; } export function increment_metric ( metric_id , offset ) { return imports . proxy_increment_metric ( metric_id , offset ) ; } export function record_metric ( metric_id , value ) { return imports . proxy_record_metric ( metric_id , value ) ; } class MetricData { result : WasmResultValues ; data : u64 ; } export function get_metric ( metric_id ) { let metric_data = globalU64Ref ; let res = imports . proxy_record_metric ( metric_id , metric_data . ptr ( ) ) ; let result = new MetricData ( ) ; result . result = res ; if ( res == WasmResultValues . Ok ) { result . data = metric_data . data ; } return result ; } export function done ( ) { return imports . proxy_done ( ) ; } export function proxy_set_effective_context ( _id ) { const result = imports . proxy_set_effective_context ( _id ) ; if ( result != WasmResultValues . Ok ) { log ( LogLevelValues . critical , "Unable to set effective context: " + _id . toString ( ) + " with result: " + result . toString ( ) ) ; } return result ; } param function_name param argument export function call_foreign_function ( function_name , argument ) { let function_name_buffer = String . UTF8 . encode ( function_name ) ; let argument_name_buffer = String . UTF8 . encode ( argument ) ; CHECK_RESULT ( imports . proxy_call_foreign_function ( changetype < usize > ( function_name_buffer ) , function_name_buffer . byteLength , changetype < usize > ( argument_name_buffer ) , argument_name_buffer . byteLength , globalArrayBufferReference . bufferPtr ( ) , globalArrayBufferReference . sizePtr ( ) ) ) ; return globalArrayBufferReference . toArrayBuffer ( ) ; } param _id function setEffectiveContext ( _id ) { return proxy_set_effective_context ( _id ) ; } /**
 * BaseContexts contains things that are common to RootContext and Context.
 */ export abstract class BaseContext { context_id : u32 ; constructor ( context_id_ ) { this . context_id = context_id_ ; } continueRequest ( ) { const result = imports . proxy_continue_stream ( StreamTypeValues . Request ) ; if ( result != WasmResultValues . Ok ) { log ( LogLevelValues . critical , "Unable to continue request: " + result . toString ( ) ) ; } } onDone ( ) { log ( LogLevelValues . debug , "context id: " + this . context_id . toString ( ) + ": onDone()" ) ; return true ; } onDelete ( ) { log ( LogLevelValues . debug , "context id: " + this . context_id . toString ( ) + ": onDelete()" ) ; } } /**
 * Wrapper around http callbacks. When AS script supports closures, we can refactor \ remove this.
 */ export class HttpCallback { origin_context : BaseContext ; cb : ( origin_context : BaseContext , headers : u32 , body_size : usize , trailers : u32 ) => void ; constructor ( origin_context , cb ) { this . origin_context = origin_context ; this . cb = cb ; } } class GrpcCallback { ctx : Object ; cb : ( c : Object ) => void ; constructor ( ctx , cb ) { this . ctx = ctx ; this . cb = cb ; } } /**
 * A root context represents a class of instance specific contexts. This is usually used to hold
 * configuration that is used in the individual contexts.
 */ export class RootContext extends BaseContext { private configuration_ : string = "" ; private http_calls_ : Map < u32 , HttpCallback > = new Map ( ) ; private grpc_calls_ : Map < u32 , GrpcCallback > = new Map ( ) ; constructor ( context_id ) { super ( context_id ) ; } getConfiguration ( ) { return this . configuration_ ; } createContext ( context_id ) { log ( LogLevelValues . error , "Base createContext called - this should never happen!" ) ; return new Context ( context_id , this ) ; } cancelPendingRequests ( ) { log ( LogLevelValues . debug , "context id: " + this . context_id . toString ( ) + ": cancelPendingRequests()" ) ; const callbacks = this . http_calls_ . values ( ) ; for ( let i = 0 ; i < callbacks . length ; ++ i ) { callbacks [ i ] . cb ( callbacks [ i ] . origin_context , 0 , 0 , 0 ) ; } let keys = this . http_calls_ . keys ( ) ; for ( let i = 0 ; i < keys . length ; ++ i ) { let key = keys [ i ] ; } this . http_calls_ . clear ( ) ; } validateConfiguration ( configuration_size ) { log ( LogLevelValues . debug , "context id: " + this . context_id . toString ( ) + ": validateConfiguration(configuration_size:" + configuration_size . toString ( ) + ")" ) ; return true ; } onConfigure ( configuration_size ) { log ( LogLevelValues . debug , "context id: " + this . context_id . toString ( ) + ": onConfigure(configuration_size: " + configuration_size . toString ( ) + ")" ) ; CHECK_RESULT ( imports . proxy_get_buffer_bytes ( BufferTypeValues . PluginConfiguration , 0 , configuration_size , globalArrayBufferReference . bufferPtr ( ) , configuration_size ) ) ; this . configuration_ = String . UTF8 . decode ( globalArrayBufferReference . toArrayBuffer ( ) ) ; log ( LogLevelValues . debug , "context id: " + this . context_id . toString ( ) + ": Updating this.configuration=" + this . configuration_ ) ; return true ; } onStart ( vm_configuration_size ) { log ( LogLevelValues . debug , "context id: " + this . context_id . toString ( ) + ": onStart(vm_configuration_size:" + vm_configuration_size . toString ( ) + ")" ) ; return true ; } onTick ( ) { log ( LogLevelValues . debug , "context id: " + this . context_id . toString ( ) + ": onTick()" ) ; } onQueueReady ( token ) { log ( LogLevelValues . debug , "context id: " + this . context_id . toString ( ) + ": onQueueReady(token:" + token . toString ( ) + ")" ) ; } onDone ( ) { log ( LogLevelValues . debug , "context id: " + this . context_id . toString ( ) + ": onDone()" ) ; this . cancelPendingRequests ( ) ; return true ; } done ( ) { log ( LogLevelValues . debug , "context id: " + this . context_id . toString ( ) + ": done()" ) ; } param cluster param headers param body param trailers param timeout_milliseconds param cb httpCall ( cluster , headers , body , trailers , timeout_milliseconds , origin_context , cb ) { log ( LogLevelValues . debug , "context id: " + this . context_id . toString ( ) + ": httpCall(cluster: " + cluster + ", headers:" + headers . toString ( ) + ", body:" + body . toString ( ) + ", trailers:" + trailers . toString ( ) + ")" ) ; let buffer = String . UTF8 . encode ( cluster ) ; let header_pairs = serializeHeaders ( headers ) ; let trailer_pairs = serializeHeaders ( trailers ) ; let token = new Reference < u32 > ( ) ; let result = imports . proxy_http_call ( changetype < usize > ( buffer ) , buffer . byteLength , changetype < usize > ( header_pairs ) , header_pairs . byteLength , changetype < usize > ( body ) , body . byteLength , changetype < usize > ( trailer_pairs ) , trailer_pairs . byteLength , timeout_milliseconds , token . ptr ( ) ) ; log ( LogLevelValues . debug , "Http call executed with result: " + result . toString ( ) ) ; if ( result == WasmResultValues . Ok ) { log ( LogLevelValues . debug , "set token: " + token . data . toString ( ) + " on " + this . context_id . toString ( ) ) ; this . http_calls_ . set ( token . data , new HttpCallback ( origin_context , cb ) ) ; } return result ; } onHttpCallResponse ( token , headers , body_size , trailers ) { log ( LogLevelValues . debug , "context id: " + this . context_id . toString ( ) + ": onHttpCallResponse(token: " + token . toString ( ) + ", headers:" + headers . toString ( ) + ", body_size:" + body_size . toString ( ) + ", trailers:" + trailers . toString ( ) + ")" ) ; log ( LogLevelValues . debug , "http_calls_: " + this . http_calls_ . size . toString ( ) ) ; log ( LogLevelValues . debug , "get token: " + token . toString ( ) + " from " + this . context_id . toString ( ) ) ; log ( LogLevelValues . debug , "context_map: " + context_map . keys ( ) . join ( ", " ) ) ; if ( this . http_calls_ . has ( token ) ) { let callback = this . http_calls_ . get ( token ) ; log ( LogLevelValues . debug , "onHttpCallResponse: calling callback for context id: " + callback . origin_context . context_id . toString ( ) ) ; this . http_calls_ . delete ( token ) ; setEffectiveContext ( callback . origin_context . context_id ) ; callback . cb ( callback . origin_context , headers , body_size , trailers ) ; } else { log ( LogLevelValues . error , "onHttpCallResponse: Token " + token . toString ( ) + " not found." ) ; } } on_grpc_receive_initial_metadata ( token , headers ) { } on_grpc_trailing_metadata ( token , trailers ) { } on_grpc_receive ( token , response_size ) { } on_grpc_close ( token , status_code ) { } } /**
 * Context class the base for class for entities that are per-request or per-connection.
 */ export class Context extends BaseContext { root_context : RootContext ; constructor ( context_id_ , root_context ) { super ( context_id_ ) ; this . root_context = root_context ; } createContext ( ) { log ( LogLevelValues . critical , "ctx: can't create context" ) ; throw new Error ( "not implemented" ) ; } onNewConnection ( ) { log ( LogLevelValues . debug , "context id: " + this . context_id . toString ( ) + ": onNewConnection()" ) ; return FilterStatusValues . Continue ; } onDownstreamData ( size , end ) { log ( LogLevelValues . debug , "context id: " + this . context_id . toString ( ) + ": onDownstreamData(size: " + size . toString ( ) + ", end: " + end . toString ( ) + ")" ) ; return FilterStatusValues . Continue ; } onUpstreamData ( size , end ) { log ( LogLevelValues . debug , "context id: " + this . context_id . toString ( ) + ": onUpstreamData(size: " + size . toString ( ) + ", end: " + end . toString ( ) + ")" ) ; return FilterStatusValues . Continue ; } onDownstreamConnectionClose ( t ) { log ( LogLevelValues . debug , "context id: " + this . context_id . toString ( ) + ": onDownstreamConnectionClose(t: " + t . toString ( ) + ")" ) ; } onUpstreamConnectionClose ( t ) { log ( LogLevelValues . debug , "context id: " + this . context_id . toString ( ) + ": onUpstreamConnectionClose(t: " + t . toString ( ) + ")" ) ; } onRequestHeaders ( a , end_of_stream ) { return FilterHeadersStatusValues . Continue ; } onRequestMetadata ( a ) { return FilterMetadataStatusValues . Continue ; } onRequestBody ( body_buffer_length , end_of_stream ) { return FilterDataStatusValues . Continue ; } onRequestTrailers ( a ) { return FilterTrailersStatusValues . Continue ; } onResponseHeaders ( a , end_of_stream ) { return FilterHeadersStatusValues . Continue ; } onResponseMetadata ( a ) { return FilterMetadataStatusValues . Continue ; } onResponseBody ( body_buffer_length , end_of_stream ) { return FilterDataStatusValues . Continue ; } onResponseTrailers ( s ) { return FilterTrailersStatusValues . Continue ; } onLog ( ) { log ( LogLevelValues . debug , "context id: " + this . context_id . toString ( ) + ": onLog()" ) ; } setEffectiveContext ( ) { return imports . proxy_set_effective_context ( this . context_id ) ; } } function get_plugin_root_id ( ) { let root_id = get_property ( "plugin_root_id" ) ; if ( root_id . byteLength == 0 ) { return "" ; } return String . UTF8 . decode ( root_id ) ; } let root_context_factory_map = new Map < string , ( context_id : u32 ) => RootContext > ( ) ; let context_map = new Map < u32 , BaseContext > ( ) ; export function ensureRootContext ( root_context_id ) { log ( LogLevelValues . debug , "ensureRootContext(root_context_id: " + root_context_id . toString ( ) + ")" ) ; log ( LogLevelValues . debug , "Current context_map: " + context_map . keys ( ) . join ( ", " ) ) ; if ( context_map . has ( root_context_id ) ) { log ( LogLevelValues . debug , "Returning root context for id: " + root_context_id . toString ( ) ) ; return getRootContext ( root_context_id ) ; } const root_id = get_plugin_root_id ( ) ; log ( LogLevelValues . debug , "Registering new root context for " + root_id + " with id: " + root_context_id . toString ( ) ) ; if ( ! root_context_factory_map . has ( root_id ) ) { throw new Error ( "Missing root context factory for root id: " + root_id ) ; } const root_context_func = root_context_factory_map . get ( root_id ) ; const root_context = root_context_func ( root_context_id ) ; root_context . context_id = root_context_id ; context_map . set ( root_context_id , root_context ) ; return root_context ; } export function ensureContext ( context_id , root_context_id ) { log ( LogLevelValues . debug , "ensureContext(context_id: " + context_id . toString ( ) + ", root_context_id: " + root_context_id . toString ( ) + ")" ) ; log ( LogLevelValues . debug , "Current context_map: " + context_map . keys ( ) . join ( ", " ) ) ; const root_context = ensureRootContext ( root_context_id ) ; if ( context_map . has ( context_id ) ) { log ( LogLevelValues . debug , "Existing context id: " + context_id . toString ( ) ) ; return ; } log ( LogLevelValues . debug , "Registering new context with context_id: " + context_id . toString ( ) + " under root_context: " + root_context_id . toString ( ) ) ; let context = root_context . createContext ( context_id ) ; context_map . set ( context_id , context ) ; log ( LogLevelValues . debug , "Updated context_map: " + context_map . keys ( ) . join ( ", " ) ) ; } export function getBaseContext ( context_id ) { return context_map . get ( context_id ) as BaseContext ; } export function getContext ( context_id ) { return context_map . get ( context_id ) as Context ; } export function getRootContext ( context_id ) { return context_map . get ( context_id ) as RootContext ; } export function deleteContext ( context_id ) { context_map . delete ( context_id ) ; } param root_context_factory param name export function registerRootContext ( root_context_factory , name ) { root_context_factory_map . set ( name , root_context_factory ) ; }