wa-lang.org/wazero@v1.0.2/imports/proxywasm/types/context.go (about) 1 // Copyright 2020-2021 Tetrate 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package types 16 17 // There are four types of these interfaces which you are supposed to implement in order to extend your network proxies. 18 // They are VMContext, PluginContext, TcpContext and HttpContext, and their relationship can be described as the following diagram: 19 // 20 // Wasm Virtual Machine(VM) 21 // (corresponds to VM configuration) 22 // ┌────────────────────────────────────────────────────────────────────────────┐ 23 // │ TcpContext │ 24 // │ ╱ (Each Tcp stream) │ 25 // │ ╱ │ 26 // │ 1: N ╱ 1: N │ 27 // │ VMContext ────────── PluginContext │ 28 // │ (VM configuration) (Plugin configuration) ╲ 1: N │ 29 // │ ╲ │ 30 // │ ╲ HttpContext │ 31 // │ (Each Http stream) │ 32 // └────────────────────────────────────────────────────────────────────────────┘ 33 // 34 // To summarize, 35 // 36 // 1) VMContext corresponds to each Wasm Virtual Machine, and only one VMContext exists in each VM. 37 // Note that in Envoy, Wasm VMs are created per "vm_config" field in envoy.yaml. For example having different "vm_config.configuration" fields 38 // results in multiple VMs being created and each of them corresponds to each "vm_config.configuration". 39 // 40 // 2) VMContext is parent of PluginContext, and is responsible for creating arbitrary number of PluginContexts. 41 // 42 // 3) PluginContext corresponds to each plugin configuration in the host. In Envoy, each plugin configuration is given at HttpFilter or NetworkFilter 43 // on listeners. That said, a plugin context corresponds to an Http or Network filter on a listener and is in charge of creating the "filter instances" for 44 // each Http or Tcp stream. These "filter instances" are represented by HttpContexts or TcpContexts. 45 // 46 // 4) PluginContext is a parent of TcpContext and HttpContext, and is responsible for creating arbitrary number of these contexts. 47 // 48 // 5) TcpContext is responsible for handling individual Tcp stream events. 49 // 50 // 6) HttpContext is responsible for handling individual Http stream events. 51 52 // VMContext corresponds to a Wasm VM machine and its configuration. 53 // It's the entrypoint for extending the network proxy. 54 // Its lifetime matches the Wasm Virtual Machines on the host. 55 type VMContext interface { 56 // OnVMStart is called after the VM is created and main function is called. 57 // During this call, GetVMConfiguration hostcall is available and can be used to 58 // retrieve the configuration set at vm_config.configuration in the host configuration. 59 // This is mainly used for doing Wasm VM-wide initialization. 60 OnVMStart(vmConfigurationSize int) OnVMStartStatus 61 62 // NewPluginContext is used for creating PluginContext for each plugin configuration. 63 NewPluginContext(contextID uint32) PluginContext 64 } 65 66 // PluginContext corresponds to different plugin configurations (config.configuration). 67 // Each configuration is typically given at the HTTP/TCP filter in a listener in the hosts. 68 // PluginContext is responsible for creating the "filter instances" for each TCP/HTTP stream on the listener. 69 type PluginContext interface { 70 // OnPluginStart is called for all plugin contexts (after OnVmStart if this is the VM context). 71 // During this call, GetPluginConfiguration is available and can be used to 72 // retrieve the configuration set at config.configuration in the host configuration. 73 OnPluginStart(pluginConfigurationSize int) OnPluginStartStatus 74 75 // OnPluginDone is called right before the plugin contexts are deleted by hosts. 76 // Return false to indicate plugin is in a pending state and there's more work left. 77 // In that case you must call PluginDone() function once the work is completed to indicate that 78 // hosts can kill this context. 79 OnPluginDone() bool 80 81 // OnQueueReady is called when the queue is ready after calling the RegisterQueue hostcall. 82 // Note that the queue might be dequeued by another VM running in another thread, so it's 83 // possible queue will be empty during the OnQueueReady even if it is not dequeued by this VM. 84 OnQueueReady(queueID uint32) 85 86 // OnTick is called when SetTickPeriodMilliSeconds hostcall is called by this plugin context. 87 // This can be used to do asynchronous tasks in parallel to the stream processing. 88 OnTick() 89 90 // The following functions are used for creating contexts on streams, 91 // and developers *must* implement either of them corresponding to 92 // extension points. For example, if you configure this plugin context is running 93 // at Http filters, then NewHttpContext must be implemented. Same goes for 94 // Tcp filters. 95 96 // NewTcpContext is used for creating TcpContext for each Tcp stream. 97 // Return nil to indicate this PluginContext is not for TcpContext. 98 NewTcpContext(contextID uint32) TcpContext 99 100 // NewHttpContext is used for creating HttpContext for each Http stream. 101 // Return nil to indicate this PluginContext is not for HttpContext. 102 NewHttpContext(contextID uint32) HttpContext 103 } 104 105 // TcpContext corresponds to each Tcp stream and is created by PluginContext via NewTcpContext. 106 type TcpContext interface { 107 // OnNewConnection is called when the Tcp connection is established between downstream and upstream. 108 OnNewConnection() Action 109 110 // OnDownstreamData is called when a data frame arrives from the downstream connection. 111 OnDownstreamData(dataSize int, endOfStream bool) Action 112 113 // OnDownstreamClose is called when the downstream connection is closed. 114 OnDownstreamClose(peerType PeerType) 115 116 // OnUpstreamData is called when a data frame arrives from the upstream connection. 117 OnUpstreamData(dataSize int, endOfStream bool) Action 118 119 // OnUpstreamClose is called when the upstream connection is closed. 120 OnUpstreamClose(peerType PeerType) 121 122 // OnStreamDone is called before the host deletes this context. 123 // You can retrieve the stream information (such as remote addresses, etc.) during this call. 124 // This can be used to implement logging features. 125 OnStreamDone() 126 } 127 128 // HttpContext corresponds to each Http stream and is created by PluginContext via NewHttpContext. 129 type HttpContext interface { 130 // OnHttpRequestHeaders is called when request headers arrive. 131 // Return types.ActionPause if you want to stop sending headers to the upstream. 132 OnHttpRequestHeaders(numHeaders int, endOfStream bool) Action 133 134 // OnHttpRequestBody is called when a request body *frame* arrives. 135 // Note that this is potentially called multiple times until we see end_of_stream = true. 136 // Return types.ActionPause if you want to buffer the body and stop sending body to the upstream. 137 // Even after returning types.ActionPause, this will be called when an unseen frame arrives. 138 OnHttpRequestBody(bodySize int, endOfStream bool) Action 139 140 // OnHttpRequestTrailers is called when request trailers arrive. 141 // Return types.ActionPause if you want to stop sending trailers to the upstream. 142 OnHttpRequestTrailers(numTrailers int) Action 143 144 // OnHttpResponseHeaders is called when response headers arrive. 145 // Return types.ActionPause if you want to stop sending headers to downstream. 146 OnHttpResponseHeaders(numHeaders int, endOfStream bool) Action 147 148 // OnHttpResponseBody is called when a response body *frame* arrives. 149 // Note that this is potentially called multiple times until we see end_of_stream = true. 150 // Return types.ActionPause if you want to buffer the body and stop sending body to the downtream. 151 // Even after returning types.ActionPause, this will be called when an unseen frame arrives. 152 OnHttpResponseBody(bodySize int, endOfStream bool) Action 153 154 // OnHttpResponseTrailers is called when response trailers arrive. 155 // Return types.ActionPause if you want to stop sending trailers to the downstream. 156 OnHttpResponseTrailers(numTrailers int) Action 157 158 // OnHttpStreamDone is called before the host deletes this context. 159 // You can retrieve the HTTP request/response information (such as headers, etc.) during this call. 160 // This can be used to implement logging features. 161 OnHttpStreamDone() 162 } 163 164 // DefaultContexts are a no-op implementation of contexts. 165 // Users can embed them into their custom contexts, so that 166 // they only have to implement methods they want. 167 type ( 168 // DefaultVMContext provides the no-op implementation of the VMContext interface. 169 DefaultVMContext struct{} 170 171 // DefaultPluginContext provides the no-op implementation of the PluginContext interface. 172 DefaultPluginContext struct{} 173 174 // DefaultTcpContext provides the no-op implementation of the TcpContext interface. 175 DefaultTcpContext struct{} 176 177 // DefaultHttpContext provides the no-op implementation of the HttpContext interface. 178 DefaultHttpContext struct{} 179 ) 180 181 // impl VMContext 182 183 func (*DefaultVMContext) OnVMStart(vmConfigurationSize int) OnVMStartStatus { return OnVMStartStatusOK } 184 func (*DefaultVMContext) NewPluginContext(contextID uint32) PluginContext { 185 return &DefaultPluginContext{} 186 } 187 188 // impl PluginContext 189 190 func (*DefaultPluginContext) OnQueueReady(uint32) {} 191 func (*DefaultPluginContext) OnTick() {} 192 func (*DefaultPluginContext) OnPluginStart(int) OnPluginStartStatus { 193 return OnPluginStartStatusOK 194 } 195 func (*DefaultPluginContext) OnPluginDone() bool { return true } 196 func (*DefaultPluginContext) NewTcpContext(uint32) TcpContext { return nil } 197 func (*DefaultPluginContext) NewHttpContext(uint32) HttpContext { return nil } 198 199 // impl TcpContext 200 201 func (*DefaultTcpContext) OnDownstreamData(int, bool) Action { return ActionContinue } 202 func (*DefaultTcpContext) OnDownstreamClose(PeerType) {} 203 func (*DefaultTcpContext) OnNewConnection() Action { return ActionContinue } 204 func (*DefaultTcpContext) OnUpstreamData(int, bool) Action { return ActionContinue } 205 func (*DefaultTcpContext) OnUpstreamClose(PeerType) {} 206 func (*DefaultTcpContext) OnStreamDone() {} 207 208 // impl HttpContext 209 210 func (*DefaultHttpContext) OnHttpRequestHeaders(int, bool) Action { return ActionContinue } 211 func (*DefaultHttpContext) OnHttpRequestBody(int, bool) Action { return ActionContinue } 212 func (*DefaultHttpContext) OnHttpRequestTrailers(int) Action { return ActionContinue } 213 func (*DefaultHttpContext) OnHttpResponseHeaders(int, bool) Action { return ActionContinue } 214 func (*DefaultHttpContext) OnHttpResponseBody(int, bool) Action { return ActionContinue } 215 func (*DefaultHttpContext) OnHttpResponseTrailers(int) Action { return ActionContinue } 216 func (*DefaultHttpContext) OnHttpStreamDone() {} 217 218 var ( 219 _ VMContext = &DefaultVMContext{} 220 _ PluginContext = &DefaultPluginContext{} 221 _ TcpContext = &DefaultTcpContext{} 222 _ HttpContext = &DefaultHttpContext{} 223 )