1
package abi
2

            
3
/*
4
#cgo darwin LDFLAGS: -Wl,-undefined,dynamic_lookup
5
#cgo linux LDFLAGS: -Wl,--unresolved-symbols=ignore-all
6
#include <stdbool.h>
7
#include <stdint.h>
8
#include <stdlib.h>
9
#include <string.h>
10
#include "../../../abi/abi.h"
11

            
12
typedef const envoy_dynamic_module_type_envoy_buffer* ConstEnvoyBufferPtr;
13
*/
14
import "C"
15
import (
16
	_ "embed"
17
	"fmt"
18
	"runtime"
19
	"strconv"
20
	"sync"
21
	"unsafe"
22

            
23
	sdk "github.com/envoyproxy/envoy/source/extensions/dynamic_modules/sdk/go"
24
	"github.com/envoyproxy/envoy/source/extensions/dynamic_modules/sdk/go/shared"
25
)
26

            
27
type httpFilterConfigWrapper struct {
28
	pluginFactory shared.HttpFilterFactory
29
	configHandle  *dymConfigHandle
30
}
31

            
32
type httpFilterConfigWrapperPerRoute struct {
33
	config any
34
}
35

            
36
type httpFilterWrapper = dymHttpFilterHandle
37

            
38
type httpFilterSharedDataWrapper struct {
39
	data any
40
}
41

            
42
const numManagerShards = 32
43

            
44
// The managers to keep track of configs and plugins.
45
type manager[T any] struct {
46
	data  [numManagerShards]map[uintptr]*T
47
	mutex [numManagerShards]sync.Mutex
48
}
49

            
50
func (m *manager[T]) record(item *T) unsafe.Pointer {
51
	pointer := unsafe.Pointer(item)
52
	index := uintptr(pointer) % numManagerShards
53
	m.mutex[index].Lock()
54
	defer m.mutex[index].Unlock()
55
	// Assume the map is initialized.
56
	m.data[index][uintptr(pointer)] = item
57
	return pointer
58
}
59

            
60
func (m *manager[T]) unwrap(itemPtr unsafe.Pointer) *T {
61
	return (*T)(itemPtr)
62
}
63

            
64
func (m *manager[T]) search(key uintptr) *T {
65
	index := key % numManagerShards
66
	m.mutex[index].Lock()
67
	defer m.mutex[index].Unlock()
68
	return m.data[index][key]
69
}
70

            
71
func (m *manager[T]) remove(itemPtr unsafe.Pointer) {
72
	index := uintptr(itemPtr) % numManagerShards
73
	m.mutex[index].Lock()
74
	defer m.mutex[index].Unlock()
75
	delete(m.data[index], uintptr(itemPtr))
76
}
77

            
78
func newManager[T any]() *manager[T] {
79
	m := &manager[T]{}
80
	for i := 0; i < numManagerShards; i++ {
81
		m.data[i] = make(map[uintptr]*T)
82
	}
83
	return m
84
}
85

            
86
var configManager = newManager[httpFilterConfigWrapper]()
87
var configPerRouteManager = newManager[httpFilterConfigWrapperPerRoute]()
88
var pluginManager = newManager[httpFilterWrapper]()
89
var sharedDataManager = newManager[httpFilterSharedDataWrapper]()
90

            
91
////////////////////////////////////////////////////////////////////////////////////////////////////
92
////////////////////////////////////////////////////////////////////////////////////////////////////
93
////////////////////////////////////////////////////////////////////////////////////////////////////
94

            
95
func nullModuleBuffer() C.envoy_dynamic_module_type_module_buffer {
96
	return C.envoy_dynamic_module_type_module_buffer{
97
		ptr:    nil,
98
		length: 0,
99
	}
100
}
101

            
102
func stringToModuleBuffer(str string) C.envoy_dynamic_module_type_module_buffer {
103
	return C.envoy_dynamic_module_type_module_buffer{
104
		ptr:    (*C.char)(unsafe.Pointer(unsafe.StringData(str))),
105
		length: C.size_t(len(str)),
106
	}
107
}
108

            
109
func bytesToModuleBuffer(b []byte) C.envoy_dynamic_module_type_module_buffer {
110
	return C.envoy_dynamic_module_type_module_buffer{
111
		ptr:    (*C.char)(unsafe.Pointer(unsafe.SliceData(b))),
112
		length: C.size_t(len(b)),
113
	}
114
}
115

            
116
func stringArrayToModuleBufferSlice(
117
	strs []string,
118
) []C.envoy_dynamic_module_type_module_buffer {
119
	views := make([]C.envoy_dynamic_module_type_module_buffer, len(strs))
120
	for i, str := range strs {
121
		views[i] = stringToModuleBuffer(str)
122
	}
123
	return views
124
}
125

            
126
func headersToModuleHttpHeaderSlice(
127
	headers [][2]string,
128
) []C.envoy_dynamic_module_type_module_http_header {
129
	views := make([]C.envoy_dynamic_module_type_module_http_header, len(headers))
130
	for i, header := range headers {
131
		views[i] = C.envoy_dynamic_module_type_module_http_header{
132
			key_ptr:      (*C.char)(unsafe.Pointer(unsafe.StringData(header[0]))),
133
			key_length:   C.size_t(len(header[0])),
134
			value_ptr:    (*C.char)(unsafe.Pointer(unsafe.StringData(header[1]))),
135
			value_length: C.size_t(len(header[1])),
136
		}
137
	}
138
	return views
139
}
140

            
141
func envoyBufferToStringUnsafe(buf C.envoy_dynamic_module_type_envoy_buffer) string {
142
	return unsafe.String((*byte)(unsafe.Pointer(buf.ptr)), buf.length)
143
}
144

            
145
func envoyBufferToBytesUnsafe(buf C.envoy_dynamic_module_type_envoy_buffer) []byte {
146
	return unsafe.Slice((*byte)(unsafe.Pointer(buf.ptr)), buf.length)
147
}
148

            
149
func envoyBufferToUnsafeEnvoyBuffer(buf C.envoy_dynamic_module_type_envoy_buffer) shared.UnsafeEnvoyBuffer {
150
	return shared.UnsafeEnvoyBuffer{
151
		Ptr: (*byte)(unsafe.Pointer(buf.ptr)),
152
		Len: uint64(buf.length),
153
	}
154
}
155

            
156
func envoyHttpHeaderSliceToUnsafeHeaderSlice(
157
	buf []C.envoy_dynamic_module_type_envoy_http_header,
158
) [][2]shared.UnsafeEnvoyBuffer {
159
	headers := make([][2]shared.UnsafeEnvoyBuffer, len(buf))
160
	for i, header := range buf {
161
		headers[i] = [2]shared.UnsafeEnvoyBuffer{
162
			{Ptr: (*byte)(unsafe.Pointer(header.key_ptr)), Len: uint64(header.key_length)},
163
			{Ptr: (*byte)(unsafe.Pointer(header.value_ptr)), Len: uint64(header.value_length)},
164
		}
165
	}
166
	return headers
167
}
168

            
169
func envoyBufferSliceToUnsafeEnvoyBufferSlice(
170
	buf []C.envoy_dynamic_module_type_envoy_buffer,
171
) []shared.UnsafeEnvoyBuffer {
172
	chunks := make([]shared.UnsafeEnvoyBuffer, 0, len(buf))
173
	for _, chunk := range buf {
174
		chunks = append(chunks, shared.UnsafeEnvoyBuffer{
175
			Ptr: (*byte)(unsafe.Pointer(chunk.ptr)),
176
			Len: uint64(chunk.length),
177
		})
178
	}
179
	return chunks
180
}
181

            
182
func hostLog(level shared.LogLevel, format string, args []any) {
183
	logLevel := uint32(level)
184
	// Quick check if logging is enabled at this level.
185
	if !bool(C.envoy_dynamic_module_callback_log_enabled(
186
		(C.envoy_dynamic_module_type_log_level)(logLevel),
187
	)) {
188
		return
189
	}
190
	message := fmt.Sprintf(format, args...)
191
	C.envoy_dynamic_module_callback_log(
192
		(C.envoy_dynamic_module_type_log_level)(logLevel),
193
		stringToModuleBuffer(message),
194
	)
195
	runtime.KeepAlive(message)
196
}
197

            
198
type dymHeaderMap struct {
199
	hostPluginPtr C.envoy_dynamic_module_type_http_filter_envoy_ptr
200
	headerType    C.envoy_dynamic_module_type_http_header_type
201
}
202

            
203
func (h *dymHeaderMap) getSingleHeader(key string, index uint64, valueCount *uint64) shared.UnsafeEnvoyBuffer {
204
	var valueView C.envoy_dynamic_module_type_envoy_buffer
205
	ret := C.envoy_dynamic_module_callback_http_get_header(
206
		h.hostPluginPtr,
207
		h.headerType,
208
		stringToModuleBuffer(key),
209
		&valueView,
210
		(C.size_t)(index),
211
		(*C.size_t)(valueCount),
212
	)
213

            
214
	if !bool(ret) || valueView.ptr == nil || valueView.length == 0 {
215
		return shared.UnsafeEnvoyBuffer{}
216
	}
217

            
218
	runtime.KeepAlive(key)
219
	return envoyBufferToUnsafeEnvoyBuffer(valueView)
220
}
221

            
222
func (h *dymHeaderMap) Get(key string) []shared.UnsafeEnvoyBuffer {
223
	valueCount := uint64(0)
224

            
225
	firstValue := h.getSingleHeader(key, 0, &valueCount)
226
	if valueCount == 0 {
227
		return []shared.UnsafeEnvoyBuffer{}
228
	}
229

            
230
	values := make([]shared.UnsafeEnvoyBuffer, 0, valueCount)
231
	values = append(values, firstValue)
232

            
233
	for i := uint64(1); i < valueCount; i++ {
234
		value := h.getSingleHeader(key, i, nil)
235
		values = append(values, value)
236
	}
237

            
238
	return values
239
}
240

            
241
func (h *dymHeaderMap) GetOne(key string) shared.UnsafeEnvoyBuffer {
242
	return h.getSingleHeader(key, 0, nil)
243
}
244

            
245
func (h *dymHeaderMap) GetAll() [][2]shared.UnsafeEnvoyBuffer {
246
	headerCount := C.envoy_dynamic_module_callback_http_get_headers_size(
247
		(C.envoy_dynamic_module_type_http_filter_envoy_ptr)(h.hostPluginPtr),
248
		(C.envoy_dynamic_module_type_http_header_type)(h.headerType),
249
	)
250
	if headerCount == 0 {
251
		return nil
252
	}
253

            
254
	resultHeaders := make([]C.envoy_dynamic_module_type_envoy_http_header, headerCount)
255
	C.envoy_dynamic_module_callback_http_get_headers(
256
		(C.envoy_dynamic_module_type_http_filter_envoy_ptr)(h.hostPluginPtr),
257
		(C.envoy_dynamic_module_type_http_header_type)(h.headerType),
258
		unsafe.SliceData(resultHeaders),
259
	)
260
	finalResult := envoyHttpHeaderSliceToUnsafeHeaderSlice(resultHeaders)
261
	runtime.KeepAlive(resultHeaders)
262
	return finalResult
263
}
264

            
265
func (h *dymHeaderMap) Set(key, value string) {
266
	C.envoy_dynamic_module_callback_http_set_header(
267
		(C.envoy_dynamic_module_type_http_filter_envoy_ptr)(h.hostPluginPtr),
268
		(C.envoy_dynamic_module_type_http_header_type)(h.headerType),
269
		stringToModuleBuffer(key),
270
		stringToModuleBuffer(value),
271
	)
272
	runtime.KeepAlive(key)
273
	runtime.KeepAlive(value)
274
}
275

            
276
func (h *dymHeaderMap) Add(key, value string) {
277
	C.envoy_dynamic_module_callback_http_add_header(
278
		(C.envoy_dynamic_module_type_http_filter_envoy_ptr)(h.hostPluginPtr),
279
		(C.envoy_dynamic_module_type_http_header_type)(h.headerType),
280
		stringToModuleBuffer(key),
281
		stringToModuleBuffer(value),
282
	)
283
	runtime.KeepAlive(key)
284
	runtime.KeepAlive(value)
285
}
286

            
287
func (h *dymHeaderMap) Remove(key string) {
288
	// The ABI use the set to nil to remove the header.
289
	C.envoy_dynamic_module_callback_http_set_header(
290
		(C.envoy_dynamic_module_type_http_filter_envoy_ptr)(h.hostPluginPtr),
291
		(C.envoy_dynamic_module_type_http_header_type)(h.headerType),
292
		stringToModuleBuffer(key),
293
		nullModuleBuffer(),
294
	)
295
	runtime.KeepAlive(key)
296
}
297

            
298
type dymBodyBuffer struct {
299
	hostPluginPtr C.envoy_dynamic_module_type_http_filter_envoy_ptr
300
	bufferType    C.envoy_dynamic_module_type_http_body_type
301
}
302

            
303
func (b *dymBodyBuffer) GetChunks() []shared.UnsafeEnvoyBuffer {
304
	var chunksSize C.size_t = 0
305
	size := C.envoy_dynamic_module_callback_http_get_body_chunks_size(
306
		(C.envoy_dynamic_module_type_http_filter_envoy_ptr)(b.hostPluginPtr),
307
		(C.envoy_dynamic_module_type_http_body_type)(b.bufferType),
308
	)
309
	chunksSize = size
310
	if chunksSize == 0 {
311
		return nil
312
	}
313

            
314
	resultChunks := make([]C.envoy_dynamic_module_type_envoy_buffer, chunksSize)
315
	C.envoy_dynamic_module_callback_http_get_body_chunks(
316
		(C.envoy_dynamic_module_type_http_filter_envoy_ptr)(b.hostPluginPtr),
317
		(C.envoy_dynamic_module_type_http_body_type)(b.bufferType),
318
		unsafe.SliceData(resultChunks),
319
	)
320
	runtime.KeepAlive(resultChunks)
321
	return envoyBufferSliceToUnsafeEnvoyBufferSlice(resultChunks)
322
}
323

            
324
func (b *dymBodyBuffer) GetSize() uint64 {
325
	size := C.envoy_dynamic_module_callback_http_get_body_size(
326
		b.hostPluginPtr,
327
		b.bufferType,
328
	)
329
	return uint64(size)
330
}
331

            
332
func (b *dymBodyBuffer) Append(data []byte) {
333
	if len(data) == 0 {
334
		return
335
	}
336
	C.envoy_dynamic_module_callback_http_append_body(
337
		b.hostPluginPtr,
338
		b.bufferType,
339
		bytesToModuleBuffer(data),
340
	)
341
	runtime.KeepAlive(data)
342
}
343

            
344
func (b *dymBodyBuffer) Drain(size uint64) {
345
	C.envoy_dynamic_module_callback_http_drain_body(
346
		b.hostPluginPtr,
347
		b.bufferType,
348
		(C.size_t)(size),
349
	)
350
}
351

            
352
type dymScheduler struct {
353
	schedulerPtr  unsafe.Pointer
354
	schedulerLock sync.Mutex
355
	nextTaskID    uint64
356
	tasks         map[uint64]func()
357
	commitFunc    func(unsafe.Pointer, C.uint64_t)
358
}
359

            
360
func newDymScheduler(
361
	schedulerPtr unsafe.Pointer,
362
	commitFunc func(unsafe.Pointer, C.uint64_t),
363
) *dymScheduler {
364
	return &dymScheduler{
365
		schedulerPtr: schedulerPtr,
366
		tasks:        make(map[uint64]func()),
367
		commitFunc:   commitFunc,
368
	}
369
}
370

            
371
func (s *dymScheduler) Schedule(task func()) {
372
	// Lock the scheduler to prevent concurrent access
373
	s.schedulerLock.Lock()
374
	taskID := s.nextTaskID
375
	s.nextTaskID++
376
	s.tasks[taskID] = task
377
	s.schedulerLock.Unlock()
378

            
379
	// Call the host to schedule the task, passing the task ID as context
380
	s.commitFunc(s.schedulerPtr, C.uint64_t(taskID))
381
}
382

            
383
func (s *dymScheduler) onScheduled(taskID uint64) {
384
	s.schedulerLock.Lock()
385
	task := s.tasks[taskID]
386
	delete(s.tasks, taskID)
387
	s.schedulerLock.Unlock()
388
	if task != nil {
389
		task()
390
	}
391
}
392

            
393
type dymHttpFilterHandle struct {
394
	hostPluginPtr C.envoy_dynamic_module_type_http_filter_envoy_ptr
395

            
396
	requestHeaderMap     dymHeaderMap
397
	responseHeaderMap    dymHeaderMap
398
	requestTrailerMap    dymHeaderMap
399
	responseTrailerMap   dymHeaderMap
400
	receivedRequestBody  dymBodyBuffer
401
	receivedResponseBody dymBodyBuffer
402
	bufferedRequestBody  dymBodyBuffer
403
	bufferedResponseBody dymBodyBuffer
404

            
405
	plugin            shared.HttpFilter
406
	scheduler         *dymScheduler
407
	streamCompleted   bool
408
	streamDestoried   bool
409
	localResponseSent bool
410
	// nextCalloutID was removed because callout ID is now returned by the host.
411

            
412
	calloutCallbacks map[uint64]shared.HttpCalloutCallback
413
	streamCallbacks  map[uint64]shared.HttpStreamCallback
414

            
415
	recordedSharedData []unsafe.Pointer
416

            
417
	downstreamWatermarkCallbacks shared.DownstreamWatermarkCallbacks
418
}
419

            
420
func (h *dymHttpFilterHandle) GetMetadataString(source shared.MetadataSourceType, metadataNamespace, key string) (shared.UnsafeEnvoyBuffer, bool) {
421
	var valueView C.envoy_dynamic_module_type_envoy_buffer
422

            
423
	ret := C.envoy_dynamic_module_callback_http_get_metadata_string(
424
		h.hostPluginPtr,
425
		(C.envoy_dynamic_module_type_metadata_source)(source),
426
		stringToModuleBuffer(metadataNamespace),
427
		stringToModuleBuffer(key),
428
		&valueView,
429
	)
430
	if !bool(ret) || valueView.ptr == nil || valueView.length == 0 {
431
		return shared.UnsafeEnvoyBuffer{}, false
432
	}
433

            
434
	runtime.KeepAlive(metadataNamespace)
435
	runtime.KeepAlive(key)
436
	return envoyBufferToUnsafeEnvoyBuffer(valueView), true
437
}
438

            
439
func (h *dymHttpFilterHandle) GetMetadataNumber(source shared.MetadataSourceType, metadataNamespace, key string) (float64, bool) {
440
	var value C.double = 0
441

            
442
	ret := C.envoy_dynamic_module_callback_http_get_metadata_number(
443
		h.hostPluginPtr,
444
		(C.envoy_dynamic_module_type_metadata_source)(source),
445
		stringToModuleBuffer(metadataNamespace),
446
		stringToModuleBuffer(key),
447
		&value,
448
	)
449
	if !bool(ret) {
450
		return 0, false
451
	}
452

            
453
	runtime.KeepAlive(metadataNamespace)
454
	runtime.KeepAlive(key)
455
	return float64(value), true
456
}
457

            
458
func (h *dymHttpFilterHandle) GetMetadataBool(source shared.MetadataSourceType, metadataNamespace, key string) (bool, bool) {
459
	var value C.bool
460

            
461
	ret := C.envoy_dynamic_module_callback_http_get_metadata_bool(
462
		h.hostPluginPtr,
463
		(C.envoy_dynamic_module_type_metadata_source)(source),
464
		stringToModuleBuffer(metadataNamespace),
465
		stringToModuleBuffer(key),
466
		&value,
467
	)
468
	if !bool(ret) {
469
		return false, false
470
	}
471

            
472
	runtime.KeepAlive(metadataNamespace)
473
	runtime.KeepAlive(key)
474
	return bool(value), true
475
}
476

            
477
func (h *dymHttpFilterHandle) GetMetadataKeys(source shared.MetadataSourceType, metadataNamespace string) []shared.UnsafeEnvoyBuffer {
478
	count := C.envoy_dynamic_module_callback_http_get_metadata_keys_count(
479
		h.hostPluginPtr,
480
		(C.envoy_dynamic_module_type_metadata_source)(source),
481
		stringToModuleBuffer(metadataNamespace),
482
	)
483
	if count == 0 {
484
		runtime.KeepAlive(metadataNamespace)
485
		return nil
486
	}
487

            
488
	buffers := make([]C.envoy_dynamic_module_type_envoy_buffer, int(count))
489
	ret := C.envoy_dynamic_module_callback_http_get_metadata_keys(
490
		h.hostPluginPtr,
491
		(C.envoy_dynamic_module_type_metadata_source)(source),
492
		stringToModuleBuffer(metadataNamespace),
493
		&buffers[0],
494
	)
495
	runtime.KeepAlive(metadataNamespace)
496
	if !bool(ret) {
497
		return nil
498
	}
499

            
500
	runtime.KeepAlive(buffers)
501
	return envoyBufferSliceToUnsafeEnvoyBufferSlice(buffers)
502
}
503

            
504
func (h *dymHttpFilterHandle) GetMetadataNamespaces(source shared.MetadataSourceType) []shared.UnsafeEnvoyBuffer {
505
	count := C.envoy_dynamic_module_callback_http_get_metadata_namespaces_count(
506
		h.hostPluginPtr,
507
		(C.envoy_dynamic_module_type_metadata_source)(source),
508
	)
509
	if count == 0 {
510
		return nil
511
	}
512

            
513
	buffers := make([]C.envoy_dynamic_module_type_envoy_buffer, int(count))
514
	ret := C.envoy_dynamic_module_callback_http_get_metadata_namespaces(
515
		h.hostPluginPtr,
516
		(C.envoy_dynamic_module_type_metadata_source)(source),
517
		&buffers[0],
518
	)
519
	if !bool(ret) {
520
		return nil
521
	}
522

            
523
	runtime.KeepAlive(buffers)
524
	return envoyBufferSliceToUnsafeEnvoyBufferSlice(buffers)
525
}
526

            
527
func (h *dymHttpFilterHandle) AddMetadataListNumber(metadataNamespace, key string, value float64) bool {
528
	ret := C.envoy_dynamic_module_callback_http_add_dynamic_metadata_list_number(
529
		h.hostPluginPtr,
530
		stringToModuleBuffer(metadataNamespace),
531
		stringToModuleBuffer(key),
532
		(C.double)(value),
533
	)
534
	runtime.KeepAlive(metadataNamespace)
535
	runtime.KeepAlive(key)
536
	return bool(ret)
537
}
538

            
539
func (h *dymHttpFilterHandle) AddMetadataListString(metadataNamespace, key string, value string) bool {
540
	ret := C.envoy_dynamic_module_callback_http_add_dynamic_metadata_list_string(
541
		h.hostPluginPtr,
542
		stringToModuleBuffer(metadataNamespace),
543
		stringToModuleBuffer(key),
544
		stringToModuleBuffer(value),
545
	)
546
	runtime.KeepAlive(metadataNamespace)
547
	runtime.KeepAlive(key)
548
	runtime.KeepAlive(value)
549
	return bool(ret)
550
}
551

            
552
func (h *dymHttpFilterHandle) AddMetadataListBool(metadataNamespace, key string, value bool) bool {
553
	ret := C.envoy_dynamic_module_callback_http_add_dynamic_metadata_list_bool(
554
		h.hostPluginPtr,
555
		stringToModuleBuffer(metadataNamespace),
556
		stringToModuleBuffer(key),
557
		(C.bool)(value),
558
	)
559
	runtime.KeepAlive(metadataNamespace)
560
	runtime.KeepAlive(key)
561
	return bool(ret)
562
}
563

            
564
func (h *dymHttpFilterHandle) GetMetadataListSize(source shared.MetadataSourceType, metadataNamespace, key string) (int, bool) {
565
	var result C.size_t = 0
566
	ret := C.envoy_dynamic_module_callback_http_get_metadata_list_size(
567
		h.hostPluginPtr,
568
		(C.envoy_dynamic_module_type_metadata_source)(source),
569
		stringToModuleBuffer(metadataNamespace),
570
		stringToModuleBuffer(key),
571
		&result,
572
	)
573
	runtime.KeepAlive(metadataNamespace)
574
	runtime.KeepAlive(key)
575
	if !bool(ret) {
576
		return 0, false
577
	}
578
	return int(result), true
579
}
580

            
581
func (h *dymHttpFilterHandle) GetMetadataListNumber(source shared.MetadataSourceType, metadataNamespace, key string, index int) (float64, bool) {
582
	var value C.double = 0
583
	ret := C.envoy_dynamic_module_callback_http_get_metadata_list_number(
584
		h.hostPluginPtr,
585
		(C.envoy_dynamic_module_type_metadata_source)(source),
586
		stringToModuleBuffer(metadataNamespace),
587
		stringToModuleBuffer(key),
588
		(C.size_t)(index),
589
		&value,
590
	)
591
	runtime.KeepAlive(metadataNamespace)
592
	runtime.KeepAlive(key)
593
	if !bool(ret) {
594
		return 0, false
595
	}
596
	return float64(value), true
597
}
598

            
599
func (h *dymHttpFilterHandle) GetMetadataListString(source shared.MetadataSourceType, metadataNamespace, key string, index int) (shared.UnsafeEnvoyBuffer, bool) {
600
	var valueView C.envoy_dynamic_module_type_envoy_buffer
601
	ret := C.envoy_dynamic_module_callback_http_get_metadata_list_string(
602
		h.hostPluginPtr,
603
		(C.envoy_dynamic_module_type_metadata_source)(source),
604
		stringToModuleBuffer(metadataNamespace),
605
		stringToModuleBuffer(key),
606
		(C.size_t)(index),
607
		&valueView,
608
	)
609
	runtime.KeepAlive(metadataNamespace)
610
	runtime.KeepAlive(key)
611
	if !bool(ret) {
612
		return shared.UnsafeEnvoyBuffer{}, false
613
	}
614
	// Handle the case where the value is empty string.
615
	if valueView.ptr == nil || valueView.length == 0 {
616
		return shared.UnsafeEnvoyBuffer{}, true
617
	}
618
	return envoyBufferToUnsafeEnvoyBuffer(valueView), true
619
}
620

            
621
func (h *dymHttpFilterHandle) GetMetadataListBool(source shared.MetadataSourceType, metadataNamespace, key string, index int) (bool, bool) {
622
	var value C.bool
623
	ret := C.envoy_dynamic_module_callback_http_get_metadata_list_bool(
624
		h.hostPluginPtr,
625
		(C.envoy_dynamic_module_type_metadata_source)(source),
626
		stringToModuleBuffer(metadataNamespace),
627
		stringToModuleBuffer(key),
628
		(C.size_t)(index),
629
		&value,
630
	)
631
	runtime.KeepAlive(metadataNamespace)
632
	runtime.KeepAlive(key)
633
	if !bool(ret) {
634
		return false, false
635
	}
636
	return bool(value), true
637
}
638

            
639
func (h *dymHttpFilterHandle) SetMetadata(metadataNamespace, key string, value any) {
640
	var numValue float64 = 0
641
	var isNum bool = false
642
	var strValue string = ""
643
	var isStr bool = false
644

            
645
	switch v := value.(type) {
646
	case uint:
647
		numValue = float64(v)
648
		isNum = true
649
	case uint8:
650
		numValue = float64(v)
651
		isNum = true
652
	case uint16:
653
		numValue = float64(v)
654
		isNum = true
655
	case uint32:
656
		numValue = float64(v)
657
		isNum = true
658
	case uint64:
659
		numValue = float64(v)
660
		isNum = true
661
	case int:
662
		numValue = float64(v)
663
		isNum = true
664
	case int8:
665
		numValue = float64(v)
666
		isNum = true
667
	case int16:
668
		numValue = float64(v)
669
		isNum = true
670
	case int32:
671
		numValue = float64(v)
672
		isNum = true
673
	case int64:
674
		numValue = float64(v)
675
		isNum = true
676
	case float32:
677
		numValue = float64(v)
678
		isNum = true
679
	case float64:
680
		numValue = float64(v)
681
		isNum = true
682
	case bool:
683
		C.envoy_dynamic_module_callback_http_set_dynamic_metadata_bool(
684
			h.hostPluginPtr,
685
			stringToModuleBuffer(metadataNamespace),
686
			stringToModuleBuffer(key),
687
			(C.bool)(v),
688
		)
689
		runtime.KeepAlive(metadataNamespace)
690
		runtime.KeepAlive(key)
691
		return
692
	case string:
693
		strValue = v
694
		isStr = true
695
	}
696

            
697
	if isNum {
698
		C.envoy_dynamic_module_callback_http_set_dynamic_metadata_number(
699
			h.hostPluginPtr,
700
			stringToModuleBuffer(metadataNamespace),
701
			stringToModuleBuffer(key),
702
			(C.double)(numValue),
703
		)
704
	} else if isStr {
705
		C.envoy_dynamic_module_callback_http_set_dynamic_metadata_string(
706
			h.hostPluginPtr,
707
			stringToModuleBuffer(metadataNamespace),
708
			stringToModuleBuffer(key),
709
			stringToModuleBuffer(strValue),
710
		)
711
	}
712
	runtime.KeepAlive(metadataNamespace)
713
	runtime.KeepAlive(key)
714
	runtime.KeepAlive(strValue)
715
}
716

            
717
func (h *dymHttpFilterHandle) GetAttributeNumber(
718
	attributeID shared.AttributeID,
719
) (float64, bool) {
720
	var value C.uint64_t = 0
721

            
722
	ret := C.envoy_dynamic_module_callback_http_filter_get_attribute_int(
723
		h.hostPluginPtr,
724
		(C.envoy_dynamic_module_type_attribute_id)(attributeID),
725
		&value,
726
	)
727
	if !bool(ret) {
728
		return 0, false
729
	}
730

            
731
	return float64(value), true
732
}
733

            
734
func (h *dymHttpFilterHandle) GetAttributeString(
735
	attributeID shared.AttributeID,
736
) (shared.UnsafeEnvoyBuffer, bool) {
737
	var valueView C.envoy_dynamic_module_type_envoy_buffer
738

            
739
	ret := C.envoy_dynamic_module_callback_http_filter_get_attribute_string(
740
		h.hostPluginPtr,
741
		(C.envoy_dynamic_module_type_attribute_id)(attributeID),
742
		&valueView,
743
	)
744
	if !bool(ret) || valueView.ptr == nil || valueView.length == 0 {
745
		return shared.UnsafeEnvoyBuffer{}, false
746
	}
747

            
748
	return envoyBufferToUnsafeEnvoyBuffer(valueView), true
749
}
750

            
751
func (h *dymHttpFilterHandle) GetAttributeBool(
752
	attributeID shared.AttributeID,
753
) (bool, bool) {
754
	var value C.bool
755

            
756
	ret := C.envoy_dynamic_module_callback_http_filter_get_attribute_bool(
757
		h.hostPluginPtr,
758
		(C.envoy_dynamic_module_type_attribute_id)(attributeID),
759
		&value,
760
	)
761
	if !bool(ret) {
762
		return false, false
763
	}
764

            
765
	return bool(value), true
766
}
767

            
768
func (h *dymHttpFilterHandle) GetFilterState(key string) (shared.UnsafeEnvoyBuffer, bool) {
769
	var valueView C.envoy_dynamic_module_type_envoy_buffer
770

            
771
	ret := C.envoy_dynamic_module_callback_http_get_filter_state_bytes(
772
		h.hostPluginPtr,
773
		stringToModuleBuffer(key),
774
		&valueView,
775
	)
776
	if !bool(ret) || valueView.ptr == nil || valueView.length == 0 {
777
		return shared.UnsafeEnvoyBuffer{}, false
778
	}
779

            
780
	runtime.KeepAlive(key)
781
	return envoyBufferToUnsafeEnvoyBuffer(valueView), true
782
}
783

            
784
func (h *dymHttpFilterHandle) SetFilterState(key string, value []byte) {
785
	C.envoy_dynamic_module_callback_http_set_filter_state_bytes(
786
		h.hostPluginPtr,
787
		stringToModuleBuffer(key),
788
		bytesToModuleBuffer(value),
789
	)
790
	runtime.KeepAlive(key)
791
	runtime.KeepAlive(value)
792
}
793

            
794
func (h *dymHttpFilterHandle) GetData(key string) any {
795
	buf, found := h.GetMetadataString(shared.MetadataSourceTypeDynamic,
796
		"composer.shared_data", key)
797
	if !found {
798
		return nil
799
	}
800
	// Convert string back to uintptr safely.
801
	uintValue, err := strconv.ParseUint(buf.ToUnsafeString(), 10, 64)
802
	if err != nil {
803
		return nil
804
	}
805
	pointer := uintptr(uintValue)
806
	// Use search rather than unwrap because the go runtime will complain
807
	// the pointer parsed from string `pointer arithmetic result points to invalid allocation`.
808
	wrapper := sharedDataManager.search(pointer)
809
	if wrapper == nil {
810
		return nil
811
	}
812
	return wrapper.data
813
}
814

            
815
func (h *dymHttpFilterHandle) SetData(key string, value any) {
816
	wrapper := &httpFilterSharedDataWrapper{data: value}
817
	pointer := sharedDataManager.record(wrapper)
818
	h.recordedSharedData = append(h.recordedSharedData, pointer)
819

            
820
	// Covert pointer to uintptr to string safely.
821
	stringValue := strconv.FormatUint(uint64(uintptr(pointer)), 10)
822
	h.SetMetadata("composer.shared_data", key, stringValue)
823
}
824

            
825
func (h *dymHttpFilterHandle) clearData() {
826
	for _, pointer := range h.recordedSharedData {
827
		sharedDataManager.remove(pointer)
828
	}
829
}
830

            
831
func (h *dymHttpFilterHandle) SendLocalResponse(
832
	statusCode uint32,
833
	headers [][2]string,
834
	body []byte,
835
	detail string,
836
) {
837
	h.localResponseSent = true
838

            
839
	// Prepare headers.
840
	headerViews := headersToModuleHttpHeaderSlice(headers)
841
	C.envoy_dynamic_module_callback_http_send_response(
842
		h.hostPluginPtr,
843
		(C.uint32_t)(statusCode),
844
		unsafe.SliceData(headerViews),
845
		(C.size_t)(len(headerViews)),
846
		bytesToModuleBuffer(body),
847
		stringToModuleBuffer(detail),
848
	)
849

            
850
	runtime.KeepAlive(body)
851
	runtime.KeepAlive(detail)
852
	runtime.KeepAlive(headers)
853
}
854

            
855
func (h *dymHttpFilterHandle) SendResponseHeaders(
856
	headers [][2]string, endOfStream bool,
857
) {
858
	// Prepare headers.
859
	headerViews := headersToModuleHttpHeaderSlice(headers)
860
	C.envoy_dynamic_module_callback_http_send_response_headers(
861
		h.hostPluginPtr,
862
		unsafe.SliceData(headerViews),
863
		(C.size_t)(len(headerViews)),
864
		(C.bool)(endOfStream),
865
	)
866
	runtime.KeepAlive(headers)
867
	runtime.KeepAlive(headerViews)
868
}
869

            
870
func (h *dymHttpFilterHandle) SendResponseData(
871
	data []byte, endOfStream bool,
872
) {
873
	C.envoy_dynamic_module_callback_http_send_response_data(
874
		h.hostPluginPtr,
875
		bytesToModuleBuffer(data),
876
		(C.bool)(endOfStream),
877
	)
878
	runtime.KeepAlive(data)
879
}
880

            
881
func (h *dymHttpFilterHandle) SendResponseTrailers(
882
	trailers [][2]string,
883
) {
884
	// Prepare trailers.
885
	trailerViews := headersToModuleHttpHeaderSlice(trailers)
886
	C.envoy_dynamic_module_callback_http_send_response_trailers(
887
		h.hostPluginPtr,
888
		unsafe.SliceData(trailerViews),
889
		(C.size_t)(len(trailerViews)),
890
	)
891
	runtime.KeepAlive(trailers)
892
	runtime.KeepAlive(trailerViews)
893
}
894

            
895
func (h *dymHttpFilterHandle) AddCustomFlag(flag string) {
896
	C.envoy_dynamic_module_callback_http_add_custom_flag(
897
		h.hostPluginPtr,
898
		stringToModuleBuffer(flag),
899
	)
900
}
901

            
902
func (h *dymHttpFilterHandle) ContinueRequest() {
903
	C.envoy_dynamic_module_callback_http_filter_continue_decoding(
904
		(C.envoy_dynamic_module_type_http_filter_envoy_ptr)(h.hostPluginPtr),
905
	)
906
}
907

            
908
func (h *dymHttpFilterHandle) ContinueResponse() {
909
	C.envoy_dynamic_module_callback_http_filter_continue_encoding(
910
		(C.envoy_dynamic_module_type_http_filter_envoy_ptr)(h.hostPluginPtr),
911
	)
912
}
913

            
914
func (h *dymHttpFilterHandle) ClearRouteCache() {
915
	C.envoy_dynamic_module_callback_http_clear_route_cache(h.hostPluginPtr)
916
}
917

            
918
func (h *dymHttpFilterHandle) RequestHeaders() shared.HeaderMap {
919
	return &h.requestHeaderMap
920
}
921

            
922
func (h *dymHttpFilterHandle) BufferedRequestBody() shared.BodyBuffer {
923
	return &h.bufferedRequestBody
924
}
925

            
926
func (h *dymHttpFilterHandle) ReceivedRequestBody() shared.BodyBuffer {
927
	return &h.receivedRequestBody
928
}
929

            
930
func (h *dymHttpFilterHandle) RequestTrailers() shared.HeaderMap {
931
	return &h.requestTrailerMap
932
}
933

            
934
func (h *dymHttpFilterHandle) ResponseHeaders() shared.HeaderMap {
935
	return &h.responseHeaderMap
936
}
937

            
938
func (h *dymHttpFilterHandle) BufferedResponseBody() shared.BodyBuffer {
939
	return &h.bufferedResponseBody
940
}
941

            
942
func (h *dymHttpFilterHandle) ReceivedResponseBody() shared.BodyBuffer {
943
	return &h.receivedResponseBody
944
}
945

            
946
func (h *dymHttpFilterHandle) ReceivedBufferedRequestBody() bool {
947
	return bool(C.envoy_dynamic_module_callback_http_received_buffered_request_body(
948
		h.hostPluginPtr,
949
	))
950
}
951

            
952
func (h *dymHttpFilterHandle) ReceivedBufferedResponseBody() bool {
953
	return bool(C.envoy_dynamic_module_callback_http_received_buffered_response_body(
954
		h.hostPluginPtr,
955
	))
956
}
957

            
958
func (h *dymHttpFilterHandle) ResponseTrailers() shared.HeaderMap {
959
	return &h.responseTrailerMap
960
}
961

            
962
func (h *dymHttpFilterHandle) GetMostSpecificConfig() any {
963
	perRoutePtr := C.envoy_dynamic_module_callback_get_most_specific_route_config(
964
		h.hostPluginPtr,
965
	)
966
	if perRoutePtr != nil {
967
		w := configPerRouteManager.unwrap(unsafe.Pointer(perRoutePtr))
968
		return w.config
969
	}
970
	return nil
971
}
972

            
973
func (h *dymHttpFilterHandle) GetScheduler() shared.Scheduler {
974
	if h.scheduler == nil {
975
		// The scheduler is created lazily and should never be nil
976
		// in practice. But it will be nil in mock tests.
977
		schedulerPtr := C.envoy_dynamic_module_callback_http_filter_scheduler_new(
978
			h.hostPluginPtr)
979
		h.scheduler = newDymScheduler(
980
			unsafe.Pointer(schedulerPtr),
981
			func(schedulerPtr unsafe.Pointer, taskID C.uint64_t) {
982
				C.envoy_dynamic_module_callback_http_filter_scheduler_commit(
983
					(C.envoy_dynamic_module_type_http_filter_scheduler_module_ptr)(schedulerPtr),
984
					taskID,
985
				)
986
			},
987
		)
988

            
989
		runtime.SetFinalizer(h.scheduler, func(s *dymScheduler) {
990
			C.envoy_dynamic_module_callback_http_filter_scheduler_delete(
991
				(C.envoy_dynamic_module_type_http_filter_scheduler_module_ptr)(s.schedulerPtr),
992
			)
993
		})
994
	}
995
	return h.scheduler
996
}
997

            
998
func (h *dymHttpFilterHandle) Log(level shared.LogLevel, format string, args ...any) {
999
	hostLog(level, format, args)
}
func (h *dymHttpFilterHandle) HttpCallout(
	cluster string, headers [][2]string, body []byte, timeoutMs uint64,
	cb shared.HttpCalloutCallback) (shared.HttpCalloutInitResult, uint64) {
	// Prepare headers.
	headerViews := headersToModuleHttpHeaderSlice(headers)
	var calloutID C.uint64_t = 0
	result := C.envoy_dynamic_module_callback_http_filter_http_callout(
		h.hostPluginPtr,
		&calloutID,
		stringToModuleBuffer(cluster),
		unsafe.SliceData(headerViews),
		(C.size_t)(len(headerViews)),
		bytesToModuleBuffer(body),
		(C.uint64_t)(timeoutMs),
	)
	runtime.KeepAlive(cluster)
	runtime.KeepAlive(headers)
	runtime.KeepAlive(body)
	runtime.KeepAlive(headerViews)
	goResult := shared.HttpCalloutInitResult(result)
	if goResult != shared.HttpCalloutInitSuccess {
		return goResult, 0
	}
	if h.calloutCallbacks == nil {
		h.calloutCallbacks = make(map[uint64]shared.HttpCalloutCallback)
	}
	h.calloutCallbacks[uint64(calloutID)] = cb
	return goResult, uint64(calloutID)
}
func (h *dymHttpFilterHandle) StartHttpStream(
	cluster string, headers [][2]string, body []byte, endOfStream bool, timeoutMs uint64,
	cb shared.HttpStreamCallback) (shared.HttpCalloutInitResult, uint64) {
	// Prepare headers.
	headerViews := headersToModuleHttpHeaderSlice(headers)
	var streamID C.uint64_t = 0
	result := C.envoy_dynamic_module_callback_http_filter_start_http_stream(
		h.hostPluginPtr,
		&streamID,
		stringToModuleBuffer(cluster),
		unsafe.SliceData(headerViews),
		(C.size_t)(len(headerViews)),
		bytesToModuleBuffer(body),
		(C.bool)(endOfStream),
		(C.uint64_t)(timeoutMs),
	)
	runtime.KeepAlive(cluster)
	runtime.KeepAlive(headers)
	runtime.KeepAlive(body)
	runtime.KeepAlive(headerViews)
	goResult := shared.HttpCalloutInitResult(result)
	if goResult != shared.HttpCalloutInitSuccess {
		return goResult, 0
	}
	if h.streamCallbacks == nil {
		h.streamCallbacks = make(map[uint64]shared.HttpStreamCallback)
	}
	h.streamCallbacks[uint64(streamID)] = cb
	return goResult, uint64(streamID)
}
func (h *dymHttpFilterHandle) SendHttpStreamData(
	streamID uint64, data []byte, endOfStream bool,
) bool {
	ret := C.envoy_dynamic_module_callback_http_stream_send_data(
		h.hostPluginPtr,
		(C.uint64_t)(streamID),
		bytesToModuleBuffer(data),
		(C.bool)(endOfStream),
	)
	runtime.KeepAlive(data)
	return bool(ret)
}
func (h *dymHttpFilterHandle) SendHttpStreamTrailers(
	streamID uint64, trailers [][2]string,
) bool {
	// Prepare trailers.
	trailerViews := headersToModuleHttpHeaderSlice(trailers)
	ret := C.envoy_dynamic_module_callback_http_stream_send_trailers(
		h.hostPluginPtr,
		(C.uint64_t)(streamID),
		unsafe.SliceData(trailerViews),
		(C.size_t)(len(trailerViews)),
	)
	runtime.KeepAlive(trailers)
	runtime.KeepAlive(trailerViews)
	return bool(ret)
}
func (h *dymHttpFilterHandle) ResetHttpStream(
	streamID uint64,
) {
	C.envoy_dynamic_module_callback_http_filter_reset_http_stream(
		h.hostPluginPtr,
		(C.uint64_t)(streamID),
	)
}
func (h *dymHttpFilterHandle) SetDownstreamWatermarkCallbacks(
	cbs shared.DownstreamWatermarkCallbacks,
) {
	h.downstreamWatermarkCallbacks = cbs
}
func (h *dymHttpFilterHandle) ClearDownstreamWatermarkCallbacks() {
	h.downstreamWatermarkCallbacks = nil
}
func (h *dymHttpFilterHandle) RecordHistogramValue(id shared.MetricID,
	value uint64, tagsValues ...string) shared.MetricsResult {
	idUint64 := uint64(id)
	// Prepare tag values.
	tagValueViews := stringArrayToModuleBufferSlice(tagsValues)
	ret := C.envoy_dynamic_module_callback_http_filter_record_histogram_value(
		h.hostPluginPtr,
		(C.size_t)(idUint64),
		unsafe.SliceData(tagValueViews),
		(C.size_t)(len(tagValueViews)),
		(C.uint64_t)(value),
	)
	runtime.KeepAlive(tagsValues)
	runtime.KeepAlive(tagValueViews)
	return shared.MetricsResult(ret)
}
func (h *dymHttpFilterHandle) SetGaugeValue(id shared.MetricID,
	value uint64, tagsValues ...string) shared.MetricsResult {
	idUint64 := uint64(id)
	// Prepare tag values.
	tagValueViews := stringArrayToModuleBufferSlice(tagsValues)
	ret := C.envoy_dynamic_module_callback_http_filter_set_gauge(
		h.hostPluginPtr,
		(C.size_t)(idUint64),
		unsafe.SliceData(tagValueViews),
		(C.size_t)(len(tagValueViews)),
		(C.uint64_t)(value),
	)
	runtime.KeepAlive(tagsValues)
	runtime.KeepAlive(tagValueViews)
	return shared.MetricsResult(ret)
}
func (h *dymHttpFilterHandle) IncrementGaugeValue(id shared.MetricID,
	value uint64, tagsValues ...string) shared.MetricsResult {
	// Prepare tag values.
	tagValueViews := stringArrayToModuleBufferSlice(tagsValues)
	ret := C.envoy_dynamic_module_callback_http_filter_increment_gauge(
		h.hostPluginPtr,
		(C.size_t)(uint64(id)),
		unsafe.SliceData(tagValueViews),
		(C.size_t)(len(tagValueViews)),
		(C.uint64_t)(value),
	)
	runtime.KeepAlive(tagsValues)
	runtime.KeepAlive(tagValueViews)
	return shared.MetricsResult(ret)
}
func (h *dymHttpFilterHandle) DecrementGaugeValue(id shared.MetricID,
	value uint64, tagsValues ...string) shared.MetricsResult {
	// Prepare tag values.
	tagValueViews := stringArrayToModuleBufferSlice(tagsValues)
	ret := C.envoy_dynamic_module_callback_http_filter_decrement_gauge(
		h.hostPluginPtr,
		(C.size_t)(uint64(id)),
		unsafe.SliceData(tagValueViews),
		(C.size_t)(len(tagValueViews)),
		(C.uint64_t)(value),
	)
	runtime.KeepAlive(tagsValues)
	runtime.KeepAlive(tagValueViews)
	return shared.MetricsResult(ret)
}
func (h *dymHttpFilterHandle) IncrementCounterValue(id shared.MetricID,
	value uint64, tagsValues ...string) shared.MetricsResult {
	// Prepare tag values.
	tagValueViews := stringArrayToModuleBufferSlice(tagsValues)
	ret := C.envoy_dynamic_module_callback_http_filter_increment_counter(
		h.hostPluginPtr,
		(C.size_t)(uint64(id)),
		unsafe.SliceData(tagValueViews),
		(C.size_t)(len(tagValueViews)),
		(C.uint64_t)(value),
	)
	runtime.KeepAlive(tagsValues)
	runtime.KeepAlive(tagValueViews)
	return shared.MetricsResult(ret)
}
func newDymStreamPluginHandle(
	hostPluginPtr C.envoy_dynamic_module_type_http_filter_envoy_ptr,
) *dymHttpFilterHandle {
	pluginHandle := &dymHttpFilterHandle{
		hostPluginPtr: hostPluginPtr,
		requestHeaderMap: dymHeaderMap{
			hostPluginPtr: hostPluginPtr,
			headerType:    C.envoy_dynamic_module_type_http_header_type(0),
		},
		requestTrailerMap: dymHeaderMap{
			hostPluginPtr: hostPluginPtr,
			headerType:    C.envoy_dynamic_module_type_http_header_type(1),
		},
		responseHeaderMap: dymHeaderMap{
			hostPluginPtr: hostPluginPtr,
			headerType:    C.envoy_dynamic_module_type_http_header_type(2),
		},
		responseTrailerMap: dymHeaderMap{
			hostPluginPtr: hostPluginPtr,
			headerType:    C.envoy_dynamic_module_type_http_header_type(3),
		},
		receivedRequestBody: dymBodyBuffer{
			hostPluginPtr: hostPluginPtr,
			bufferType:    C.envoy_dynamic_module_type_http_body_type(0),
		},
		bufferedRequestBody: dymBodyBuffer{
			hostPluginPtr: hostPluginPtr,
			bufferType:    C.envoy_dynamic_module_type_http_body_type(1),
		},
		receivedResponseBody: dymBodyBuffer{
			hostPluginPtr: hostPluginPtr,
			bufferType:    C.envoy_dynamic_module_type_http_body_type(2),
		},
		bufferedResponseBody: dymBodyBuffer{
			hostPluginPtr: hostPluginPtr,
			bufferType:    C.envoy_dynamic_module_type_http_body_type(3),
		},
	}
	return pluginHandle
}
type dymConfigHandle struct {
	hostConfigPtr    C.envoy_dynamic_module_type_http_filter_config_envoy_ptr
	calloutCallbacks map[uint64]shared.HttpCalloutCallback
	streamCallbacks  map[uint64]shared.HttpStreamCallback
	scheduler        *dymScheduler
}
func (h *dymConfigHandle) Log(level shared.LogLevel, format string, args ...any) {
	hostLog(level, format, args)
}
func (h *dymConfigHandle) DefineHistogram(name string,
	tagKeys ...string) (shared.MetricID, shared.MetricsResult) {
	// Prepare tag keys.
	tagKeyViews := stringArrayToModuleBufferSlice(tagKeys)
	var metricID C.size_t = 0
	var tagKeyPtr *C.envoy_dynamic_module_type_module_buffer = nil
	if len(tagKeyViews) > 0 {
		tagKeyPtr = unsafe.SliceData(tagKeyViews)
	}
	result := C.envoy_dynamic_module_callback_http_filter_config_define_histogram(
		h.hostConfigPtr,
		stringToModuleBuffer(name),
		tagKeyPtr,
		(C.size_t)(len(tagKeyViews)),
		&metricID,
	)
	runtime.KeepAlive(name)
	runtime.KeepAlive(tagKeys)
	runtime.KeepAlive(tagKeyViews)
	return shared.MetricID(metricID), shared.MetricsResult(result)
}
func (h *dymConfigHandle) DefineGauge(name string,
	tagKeys ...string) (shared.MetricID, shared.MetricsResult) {
	// Prepare tag keys.
	tagKeyViews := stringArrayToModuleBufferSlice(tagKeys)
	var metricID C.size_t = 0
	var tagKeyPtr *C.envoy_dynamic_module_type_module_buffer = nil
	if len(tagKeyViews) > 0 {
		tagKeyPtr = unsafe.SliceData(tagKeyViews)
	}
	result := C.envoy_dynamic_module_callback_http_filter_config_define_gauge(
		h.hostConfigPtr,
		stringToModuleBuffer(name),
		tagKeyPtr,
		(C.size_t)(len(tagKeyViews)),
		&metricID,
	)
	runtime.KeepAlive(name)
	runtime.KeepAlive(tagKeys)
	runtime.KeepAlive(tagKeyViews)
	return shared.MetricID(metricID), shared.MetricsResult(result)
}
func (h *dymConfigHandle) DefineCounter(name string,
	tagKeys ...string) (shared.MetricID, shared.MetricsResult) {
	// Prepare tag keys.
	tagKeyViews := stringArrayToModuleBufferSlice(tagKeys)
	var metricID C.size_t = 0
	var tagKeyPtr *C.envoy_dynamic_module_type_module_buffer = nil
	if len(tagKeyViews) > 0 {
		tagKeyPtr = unsafe.SliceData(tagKeyViews)
	}
	result := C.envoy_dynamic_module_callback_http_filter_config_define_counter(
		h.hostConfigPtr,
		stringToModuleBuffer(name),
		tagKeyPtr,
		(C.size_t)(len(tagKeyViews)),
		&metricID,
	)
	runtime.KeepAlive(name)
	runtime.KeepAlive(tagKeys)
	runtime.KeepAlive(tagKeyViews)
	return shared.MetricID(metricID), shared.MetricsResult(result)
}
func (h *dymConfigHandle) HttpCallout(
	cluster string, headers [][2]string, body []byte, timeoutMs uint64,
	cb shared.HttpCalloutCallback) (shared.HttpCalloutInitResult, uint64) {
	headerViews := headersToModuleHttpHeaderSlice(headers)
	var calloutID C.uint64_t = 0
	result := C.envoy_dynamic_module_callback_http_filter_config_http_callout(
		h.hostConfigPtr,
		&calloutID,
		stringToModuleBuffer(cluster),
		unsafe.SliceData(headerViews),
		(C.size_t)(len(headerViews)),
		bytesToModuleBuffer(body),
		(C.uint64_t)(timeoutMs),
	)
	runtime.KeepAlive(cluster)
	runtime.KeepAlive(headers)
	runtime.KeepAlive(body)
	runtime.KeepAlive(headerViews)
	goResult := shared.HttpCalloutInitResult(result)
	if goResult != shared.HttpCalloutInitSuccess {
		return goResult, 0
	}
	if h.calloutCallbacks == nil {
		h.calloutCallbacks = make(map[uint64]shared.HttpCalloutCallback)
	}
	h.calloutCallbacks[uint64(calloutID)] = cb
	return goResult, uint64(calloutID)
}
func (h *dymConfigHandle) StartHttpStream(
	cluster string, headers [][2]string, body []byte, endOfStream bool, timeoutMs uint64,
	cb shared.HttpStreamCallback) (shared.HttpCalloutInitResult, uint64) {
	headerViews := headersToModuleHttpHeaderSlice(headers)
	var streamID C.uint64_t = 0
	result := C.envoy_dynamic_module_callback_http_filter_config_start_http_stream(
		h.hostConfigPtr,
		&streamID,
		stringToModuleBuffer(cluster),
		unsafe.SliceData(headerViews),
		(C.size_t)(len(headerViews)),
		bytesToModuleBuffer(body),
		(C.bool)(endOfStream),
		(C.uint64_t)(timeoutMs),
	)
	runtime.KeepAlive(cluster)
	runtime.KeepAlive(headers)
	runtime.KeepAlive(body)
	runtime.KeepAlive(headerViews)
	goResult := shared.HttpCalloutInitResult(result)
	if goResult != shared.HttpCalloutInitSuccess {
		return goResult, 0
	}
	if h.streamCallbacks == nil {
		h.streamCallbacks = make(map[uint64]shared.HttpStreamCallback)
	}
	h.streamCallbacks[uint64(streamID)] = cb
	return goResult, uint64(streamID)
}
func (h *dymConfigHandle) SendHttpStreamData(streamID uint64, data []byte, endOfStream bool) bool {
	ret := C.envoy_dynamic_module_callback_http_filter_config_stream_send_data(
		h.hostConfigPtr,
		(C.uint64_t)(streamID),
		bytesToModuleBuffer(data),
		(C.bool)(endOfStream),
	)
	runtime.KeepAlive(data)
	return bool(ret)
}
func (h *dymConfigHandle) SendHttpStreamTrailers(streamID uint64, trailers [][2]string) bool {
	trailerViews := headersToModuleHttpHeaderSlice(trailers)
	ret := C.envoy_dynamic_module_callback_http_filter_config_stream_send_trailers(
		h.hostConfigPtr,
		(C.uint64_t)(streamID),
		unsafe.SliceData(trailerViews),
		(C.size_t)(len(trailerViews)),
	)
	runtime.KeepAlive(trailers)
	runtime.KeepAlive(trailerViews)
	return bool(ret)
}
func (h *dymConfigHandle) ResetHttpStream(streamID uint64) {
	C.envoy_dynamic_module_callback_http_filter_config_reset_http_stream(
		h.hostConfigPtr,
		(C.uint64_t)(streamID),
	)
}
func (h *dymConfigHandle) GetScheduler() shared.Scheduler {
	if h.scheduler == nil {
		// The scheduler is created lazily and should never be nil
		// in practice. But it will be nil in mock tests.
		schedulerPtr := C.envoy_dynamic_module_callback_http_filter_config_scheduler_new(
			h.hostConfigPtr)
		h.scheduler = newDymScheduler(
			unsafe.Pointer(schedulerPtr),
			func(schedulerPtr unsafe.Pointer, taskID C.uint64_t) {
				C.envoy_dynamic_module_callback_http_filter_config_scheduler_commit(
					(C.envoy_dynamic_module_type_http_filter_config_scheduler_module_ptr)(schedulerPtr),
					taskID,
				)
			},
		)
		runtime.SetFinalizer(h.scheduler, func(s *dymScheduler) {
			C.envoy_dynamic_module_callback_http_filter_config_scheduler_delete(
				(C.envoy_dynamic_module_type_http_filter_config_scheduler_module_ptr)(s.schedulerPtr),
			)
		})
	}
	return h.scheduler
}
type dymRouteConfigHandle struct{}
func (h *dymRouteConfigHandle) Log(level shared.LogLevel, format string, args ...any) {
	hostLog(level, format, args)
}
func (h *dymRouteConfigHandle) DefineHistogram(name string,
	tagKeys ...string) (shared.MetricID, shared.MetricsResult) {
	return 0, shared.MetricsFrozen
}
func (h *dymRouteConfigHandle) DefineGauge(name string,
	tagKeys ...string) (shared.MetricID, shared.MetricsResult) {
	return 0, shared.MetricsFrozen
}
func (h *dymRouteConfigHandle) DefineCounter(name string,
	tagKeys ...string) (shared.MetricID, shared.MetricsResult) {
	return 0, shared.MetricsFrozen
}
//export envoy_dynamic_module_on_program_init
func envoy_dynamic_module_on_program_init() C.envoy_dynamic_module_type_abi_version_module_ptr {
	return C.envoy_dynamic_module_type_abi_version_module_ptr(C.envoy_dynamic_modules_abi_version)
}
//export envoy_dynamic_module_on_http_filter_config_new
func envoy_dynamic_module_on_http_filter_config_new(
	hostConfigPtr C.envoy_dynamic_module_type_http_filter_config_envoy_ptr,
	name C.envoy_dynamic_module_type_envoy_buffer,
	config C.envoy_dynamic_module_type_envoy_buffer,
) C.envoy_dynamic_module_type_http_filter_config_module_ptr {
	nameString := envoyBufferToStringUnsafe(name)
	configBytes := envoyBufferToBytesUnsafe(config)
	configHandle := &dymConfigHandle{hostConfigPtr: hostConfigPtr}
	factory, err := sdk.NewHttpFilterFactory(configHandle, nameString, configBytes)
	if err != nil || factory == nil {
		configHandle.Log(shared.LogLevelWarn, "Failed to load configuration: %v", err)
		return nil
	}
	configPtr := configManager.record(&httpFilterConfigWrapper{pluginFactory: factory, configHandle: configHandle})
	return C.envoy_dynamic_module_type_http_filter_config_module_ptr(configPtr)
}
//export envoy_dynamic_module_on_http_filter_config_destroy
func envoy_dynamic_module_on_http_filter_config_destroy(
	configPtr C.envoy_dynamic_module_type_http_filter_config_module_ptr,
) {
	factoryWrapper := configManager.unwrap(unsafe.Pointer(configPtr))
	if factoryWrapper == nil {
		return
	}
	factoryWrapper.configHandle.scheduler = nil
	factoryWrapper.pluginFactory.OnDestroy()
	configManager.remove(unsafe.Pointer(configPtr))
}
//export envoy_dynamic_module_on_http_filter_per_route_config_new
func envoy_dynamic_module_on_http_filter_per_route_config_new(
	name C.envoy_dynamic_module_type_envoy_buffer,
	config C.envoy_dynamic_module_type_envoy_buffer,
) C.envoy_dynamic_module_type_http_filter_per_route_config_module_ptr {
	nameStr := envoyBufferToStringUnsafe(name)
	configBytes := envoyBufferToBytesUnsafe(config)
	// The route config handle only make logging available.
	configHandle := &dymRouteConfigHandle{}
	configFactory := sdk.GetHttpFilterConfigFactory(nameStr)
	if configFactory == nil {
		configHandle.Log(shared.LogLevelWarn,
			"Failed to load configuration: no factory for %s", nameStr)
		return nil
	}
	parsedConfig, err := configFactory.CreatePerRoute(configBytes)
	if err != nil || parsedConfig == nil {
		configHandle.Log(shared.LogLevelWarn,
			"Failed to load per-route configuration: %v", err)
		return nil
	}
	configPtr := configPerRouteManager.record(&httpFilterConfigWrapperPerRoute{config: parsedConfig})
	return C.envoy_dynamic_module_type_http_filter_per_route_config_module_ptr(configPtr)
}
//export envoy_dynamic_module_on_http_filter_per_route_config_destroy
func envoy_dynamic_module_on_http_filter_per_route_config_destroy(
	configPtr C.envoy_dynamic_module_type_http_filter_per_route_config_module_ptr,
) {
	configPerRouteManager.remove(unsafe.Pointer(configPtr))
}
//export envoy_dynamic_module_on_http_filter_new
func envoy_dynamic_module_on_http_filter_new(
	pluginConfigPtr C.envoy_dynamic_module_type_http_filter_config_module_ptr,
	hostPluginPtr C.envoy_dynamic_module_type_http_filter_envoy_ptr,
) C.envoy_dynamic_module_type_http_filter_module_ptr {
	factoryWrapper := configManager.unwrap(unsafe.Pointer(pluginConfigPtr))
	if factoryWrapper == nil {
		return nil
	}
	// Create the plugin wrapper.
	pluginWrapper := newDymStreamPluginHandle(hostPluginPtr)
	pluginWrapper.plugin = factoryWrapper.pluginFactory.Create(pluginWrapper)
	pluginPtr := pluginManager.record(pluginWrapper)
	return C.envoy_dynamic_module_type_http_filter_module_ptr(pluginPtr)
}
//export envoy_dynamic_module_on_http_filter_destroy
func envoy_dynamic_module_on_http_filter_destroy(
	pluginPtr C.envoy_dynamic_module_type_http_filter_module_ptr,
) {
	pluginWrapper := pluginManager.unwrap(unsafe.Pointer(pluginPtr))
	if pluginWrapper == nil || pluginWrapper.streamDestoried {
		return
	}
	pluginWrapper.streamDestoried = true
	if pluginWrapper.plugin != nil {
		pluginWrapper.plugin.OnDestroy()
	}
	pluginManager.remove(unsafe.Pointer(pluginPtr))
}
//export envoy_dynamic_module_on_http_filter_request_headers
func envoy_dynamic_module_on_http_filter_request_headers(
	_ C.envoy_dynamic_module_type_http_filter_envoy_ptr,
	pluginPtr C.envoy_dynamic_module_type_http_filter_module_ptr,
	endOfStream C.bool,
) C.envoy_dynamic_module_type_on_http_filter_request_headers_status {
	// Get the plugin wrapper.
	pluginWrapper := pluginManager.unwrap(unsafe.Pointer(pluginPtr))
	if pluginWrapper == nil || pluginWrapper.plugin == nil {
		return 0
	}
	return C.envoy_dynamic_module_type_on_http_filter_request_headers_status(
		pluginWrapper.plugin.OnRequestHeaders(&pluginWrapper.requestHeaderMap, bool(endOfStream)))
}
//export envoy_dynamic_module_on_http_filter_request_body
func envoy_dynamic_module_on_http_filter_request_body(
	_ C.envoy_dynamic_module_type_http_filter_envoy_ptr,
	pluginPtr C.envoy_dynamic_module_type_http_filter_module_ptr,
	endOfStream C.bool,
) C.envoy_dynamic_module_type_on_http_filter_request_body_status {
	pluginWrapper := pluginManager.unwrap(unsafe.Pointer(pluginPtr))
	if pluginWrapper == nil || pluginWrapper.plugin == nil {
		return 0
	}
	return C.envoy_dynamic_module_type_on_http_filter_request_body_status(
		pluginWrapper.plugin.OnRequestBody(&pluginWrapper.receivedRequestBody, bool(endOfStream)))
}
//export envoy_dynamic_module_on_http_filter_request_trailers
func envoy_dynamic_module_on_http_filter_request_trailers(
	_ C.envoy_dynamic_module_type_http_filter_envoy_ptr,
	pluginPtr C.envoy_dynamic_module_type_http_filter_module_ptr,
) C.envoy_dynamic_module_type_on_http_filter_request_trailers_status {
	pluginWrapper := pluginManager.unwrap(unsafe.Pointer(pluginPtr))
	if pluginWrapper == nil || pluginWrapper.plugin == nil {
		return 0
	}
	return C.envoy_dynamic_module_type_on_http_filter_request_trailers_status(
		pluginWrapper.plugin.OnRequestTrailers(&pluginWrapper.requestTrailerMap))
}
//export envoy_dynamic_module_on_http_filter_response_headers
func envoy_dynamic_module_on_http_filter_response_headers(
	_ C.envoy_dynamic_module_type_http_filter_envoy_ptr,
	pluginPtr C.envoy_dynamic_module_type_http_filter_module_ptr,
	endOfStream C.bool,
) C.envoy_dynamic_module_type_on_http_filter_response_headers_status {
	pluginWrapper := pluginManager.unwrap(unsafe.Pointer(pluginPtr))
	if pluginWrapper == nil || pluginWrapper.plugin == nil || pluginWrapper.localResponseSent {
		return 0
	}
	return C.envoy_dynamic_module_type_on_http_filter_response_headers_status(
		pluginWrapper.plugin.OnResponseHeaders(&pluginWrapper.responseHeaderMap, bool(endOfStream)))
}
//export envoy_dynamic_module_on_http_filter_response_body
func envoy_dynamic_module_on_http_filter_response_body(
	_ C.envoy_dynamic_module_type_http_filter_envoy_ptr,
	pluginPtr C.envoy_dynamic_module_type_http_filter_module_ptr,
	endOfStream C.bool,
) C.envoy_dynamic_module_type_on_http_filter_response_body_status {
	pluginWrapper := pluginManager.unwrap(unsafe.Pointer(pluginPtr))
	if pluginWrapper == nil || pluginWrapper.plugin == nil || pluginWrapper.localResponseSent {
		return 0
	}
	return C.envoy_dynamic_module_type_on_http_filter_response_body_status(
		pluginWrapper.plugin.OnResponseBody(&pluginWrapper.receivedResponseBody, bool(endOfStream)))
}
//export envoy_dynamic_module_on_http_filter_response_trailers
func envoy_dynamic_module_on_http_filter_response_trailers(
	_ C.envoy_dynamic_module_type_http_filter_envoy_ptr,
	pluginPtr C.envoy_dynamic_module_type_http_filter_module_ptr,
) C.envoy_dynamic_module_type_on_http_filter_response_trailers_status {
	pluginWrapper := pluginManager.unwrap(unsafe.Pointer(pluginPtr))
	if pluginWrapper == nil || pluginWrapper.plugin == nil || pluginWrapper.localResponseSent {
		return 0
	}
	return C.envoy_dynamic_module_type_on_http_filter_response_trailers_status(
		pluginWrapper.plugin.OnResponseTrailers(&pluginWrapper.responseTrailerMap))
}
//export envoy_dynamic_module_on_http_filter_stream_complete
func envoy_dynamic_module_on_http_filter_stream_complete(
	_ C.envoy_dynamic_module_type_http_filter_envoy_ptr,
	pluginPtr C.envoy_dynamic_module_type_http_filter_module_ptr,
) {
	pluginWrapper := pluginManager.unwrap(unsafe.Pointer(pluginPtr))
	if pluginWrapper == nil || pluginWrapper.plugin == nil {
		return
	}
	pluginWrapper.streamCompleted = true
	pluginWrapper.clearData()
	pluginWrapper.scheduler = nil
	pluginWrapper.plugin.OnStreamComplete()
}
//export envoy_dynamic_module_on_http_filter_scheduled
func envoy_dynamic_module_on_http_filter_scheduled(
	_ C.envoy_dynamic_module_type_http_filter_envoy_ptr,
	pluginPtr C.envoy_dynamic_module_type_http_filter_module_ptr,
	taskID C.uint64_t,
) {
	pluginWrapper := pluginManager.unwrap(unsafe.Pointer(pluginPtr))
	if pluginWrapper == nil || pluginWrapper.scheduler == nil || pluginWrapper.streamCompleted {
		return
	}
	pluginWrapper.scheduler.onScheduled(uint64(taskID))
}
//export envoy_dynamic_module_on_http_filter_http_callout_done
func envoy_dynamic_module_on_http_filter_http_callout_done(
	_ C.envoy_dynamic_module_type_http_filter_envoy_ptr,
	pluginPtr C.envoy_dynamic_module_type_http_filter_module_ptr,
	calloutID C.uint64_t,
	result C.envoy_dynamic_module_type_http_callout_result,
	headers *C.envoy_dynamic_module_type_envoy_http_header,
	headersSize C.size_t,
	chunks *C.envoy_dynamic_module_type_envoy_buffer,
	chunksSize C.size_t,
) {
	pluginWrapper := pluginManager.unwrap(unsafe.Pointer(pluginPtr))
	if pluginWrapper == nil || pluginWrapper.streamCompleted {
		return
	}
	// Prepare headers and body chunks.
	resultHeaders := envoyHttpHeaderSliceToUnsafeHeaderSlice(unsafe.Slice(headers, int(headersSize)))
	resultChunks := envoyBufferSliceToUnsafeEnvoyBufferSlice(unsafe.Slice(chunks, int(chunksSize)))
	cb := pluginWrapper.calloutCallbacks[uint64(calloutID)]
	if cb != nil {
		delete(pluginWrapper.calloutCallbacks, uint64(calloutID))
		cb.OnHttpCalloutDone(uint64(calloutID),
			shared.HttpCalloutResult(result),
			resultHeaders,
			resultChunks,
		)
	}
}
//export envoy_dynamic_module_on_http_filter_http_stream_headers
func envoy_dynamic_module_on_http_filter_http_stream_headers(
	_ C.envoy_dynamic_module_type_http_filter_envoy_ptr,
	pluginPtr C.envoy_dynamic_module_type_http_filter_module_ptr,
	streamID C.uint64_t,
	headers *C.envoy_dynamic_module_type_envoy_http_header,
	headersSize C.size_t,
	endOfStream C.bool,
) {
	pluginWrapper := pluginManager.unwrap(unsafe.Pointer(pluginPtr))
	if pluginWrapper == nil || pluginWrapper.streamCompleted {
		return
	}
	// Prepare headers.
	resultHeaders := envoyHttpHeaderSliceToUnsafeHeaderSlice(unsafe.Slice(headers, int(headersSize)))
	cb := pluginWrapper.streamCallbacks[uint64(streamID)]
	if cb != nil {
		cb.OnHttpStreamHeaders(uint64(streamID), resultHeaders, bool(endOfStream))
	}
}
//export envoy_dynamic_module_on_http_filter_http_stream_data
func envoy_dynamic_module_on_http_filter_http_stream_data(
	_ C.envoy_dynamic_module_type_http_filter_envoy_ptr,
	pluginPtr C.envoy_dynamic_module_type_http_filter_module_ptr,
	streamID C.uint64_t,
	chunks C.ConstEnvoyBufferPtr,
	chunksSize C.size_t,
	endOfStream C.bool,
) {
	pluginWrapper := pluginManager.unwrap(unsafe.Pointer(pluginPtr))
	if pluginWrapper == nil || pluginWrapper.streamCompleted {
		return
	}
	// Prepare data.
	resultData := envoyBufferSliceToUnsafeEnvoyBufferSlice(unsafe.Slice(chunks, int(chunksSize)))
	cb := pluginWrapper.streamCallbacks[uint64(streamID)]
	if cb != nil {
		cb.OnHttpStreamData(uint64(streamID), resultData, bool(endOfStream))
	}
}
//export envoy_dynamic_module_on_http_filter_http_stream_trailers
func envoy_dynamic_module_on_http_filter_http_stream_trailers(
	_ C.envoy_dynamic_module_type_http_filter_envoy_ptr,
	pluginPtr C.envoy_dynamic_module_type_http_filter_module_ptr,
	streamID C.uint64_t,
	trailers *C.envoy_dynamic_module_type_envoy_http_header,
	trailersSize C.size_t,
) {
	pluginWrapper := pluginManager.unwrap(unsafe.Pointer(pluginPtr))
	if pluginWrapper == nil || pluginWrapper.streamCompleted {
		return
	}
	// Prepare trailers.
	resultTrailers := envoyHttpHeaderSliceToUnsafeHeaderSlice(unsafe.Slice(trailers, int(trailersSize)))
	cb := pluginWrapper.streamCallbacks[uint64(streamID)]
	if cb != nil {
		cb.OnHttpStreamTrailers(uint64(streamID), resultTrailers)
	}
}
//export envoy_dynamic_module_on_http_filter_http_stream_complete
func envoy_dynamic_module_on_http_filter_http_stream_complete(
	_ C.envoy_dynamic_module_type_http_filter_envoy_ptr,
	pluginPtr C.envoy_dynamic_module_type_http_filter_module_ptr,
	streamID C.uint64_t,
) {
	pluginWrapper := pluginManager.unwrap(unsafe.Pointer(pluginPtr))
	if pluginWrapper == nil || pluginWrapper.streamCompleted {
		return
	}
	cb := pluginWrapper.streamCallbacks[uint64(streamID)]
	if cb != nil {
		delete(pluginWrapper.streamCallbacks, uint64(streamID))
		cb.OnHttpStreamComplete(uint64(streamID))
	}
}
//export envoy_dynamic_module_on_http_filter_http_stream_reset
func envoy_dynamic_module_on_http_filter_http_stream_reset(
	_ C.envoy_dynamic_module_type_http_filter_envoy_ptr,
	pluginPtr C.envoy_dynamic_module_type_http_filter_module_ptr,
	streamID C.uint64_t,
	reason C.envoy_dynamic_module_type_http_stream_reset_reason,
) {
	pluginWrapper := pluginManager.unwrap(unsafe.Pointer(pluginPtr))
	if pluginWrapper == nil || pluginWrapper.streamCompleted {
		return
	}
	cb := pluginWrapper.streamCallbacks[uint64(streamID)]
	if cb != nil {
		delete(pluginWrapper.streamCallbacks, uint64(streamID))
		cb.OnHttpStreamReset(uint64(streamID), shared.HttpStreamResetReason(reason))
	}
}
//export envoy_dynamic_module_on_http_filter_downstream_above_write_buffer_high_watermark
func envoy_dynamic_module_on_http_filter_downstream_above_write_buffer_high_watermark(
	_ C.envoy_dynamic_module_type_http_filter_envoy_ptr,
	pluginPtr C.envoy_dynamic_module_type_http_filter_module_ptr,
) {
	pluginWrapper := pluginManager.unwrap(unsafe.Pointer(pluginPtr))
	if pluginWrapper == nil || pluginWrapper.streamCompleted {
		return
	}
	if pluginWrapper.downstreamWatermarkCallbacks != nil {
		pluginWrapper.downstreamWatermarkCallbacks.OnAboveWriteBufferHighWatermark()
	}
}
//export envoy_dynamic_module_on_http_filter_downstream_below_write_buffer_low_watermark
func envoy_dynamic_module_on_http_filter_downstream_below_write_buffer_low_watermark(
	_ C.envoy_dynamic_module_type_http_filter_envoy_ptr,
	pluginPtr C.envoy_dynamic_module_type_http_filter_module_ptr,
) {
	pluginWrapper := pluginManager.unwrap(unsafe.Pointer(pluginPtr))
	if pluginWrapper == nil || pluginWrapper.streamCompleted {
		return
	}
	if pluginWrapper.downstreamWatermarkCallbacks != nil {
		pluginWrapper.downstreamWatermarkCallbacks.OnBelowWriteBufferLowWatermark()
	}
}
//export envoy_dynamic_module_on_http_filter_local_reply
func envoy_dynamic_module_on_http_filter_local_reply(
	filter_envoy_ptr C.envoy_dynamic_module_type_http_filter_envoy_ptr,
	filter_module_ptr C.envoy_dynamic_module_type_http_filter_module_ptr,
	response_code C.uint32_t,
	details C.envoy_dynamic_module_type_envoy_buffer,
	reset_imminent C.bool,
) C.envoy_dynamic_module_type_on_http_filter_local_reply_status {
	return C.envoy_dynamic_module_type_on_http_filter_local_reply_status(0)
}
//export envoy_dynamic_module_on_http_filter_config_http_callout_done
func envoy_dynamic_module_on_http_filter_config_http_callout_done(
	_ C.envoy_dynamic_module_type_http_filter_config_envoy_ptr,
	configPtr C.envoy_dynamic_module_type_http_filter_config_module_ptr,
	calloutID C.uint64_t,
	result C.envoy_dynamic_module_type_http_callout_result,
	headers *C.envoy_dynamic_module_type_envoy_http_header,
	headersSize C.size_t,
	chunks *C.envoy_dynamic_module_type_envoy_buffer,
	chunksSize C.size_t,
) {
	configWrapper := configManager.unwrap(unsafe.Pointer(configPtr))
	if configWrapper == nil || configWrapper.configHandle == nil {
		return
	}
	ch := configWrapper.configHandle
	resultHeaders := envoyHttpHeaderSliceToUnsafeHeaderSlice(unsafe.Slice(headers, int(headersSize)))
	resultChunks := envoyBufferSliceToUnsafeEnvoyBufferSlice(unsafe.Slice(chunks, int(chunksSize)))
	cb := ch.calloutCallbacks[uint64(calloutID)]
	if cb != nil {
		delete(ch.calloutCallbacks, uint64(calloutID))
		cb.OnHttpCalloutDone(uint64(calloutID), shared.HttpCalloutResult(result), resultHeaders, resultChunks)
	}
}
//export envoy_dynamic_module_on_http_filter_config_http_stream_headers
func envoy_dynamic_module_on_http_filter_config_http_stream_headers(
	_ C.envoy_dynamic_module_type_http_filter_config_envoy_ptr,
	configPtr C.envoy_dynamic_module_type_http_filter_config_module_ptr,
	streamID C.uint64_t,
	headers *C.envoy_dynamic_module_type_envoy_http_header,
	headersSize C.size_t,
	endOfStream C.bool,
) {
	configWrapper := configManager.unwrap(unsafe.Pointer(configPtr))
	if configWrapper == nil || configWrapper.configHandle == nil {
		return
	}
	ch := configWrapper.configHandle
	resultHeaders := envoyHttpHeaderSliceToUnsafeHeaderSlice(unsafe.Slice(headers, int(headersSize)))
	cb := ch.streamCallbacks[uint64(streamID)]
	if cb != nil {
		cb.OnHttpStreamHeaders(uint64(streamID), resultHeaders, bool(endOfStream))
	}
}
//export envoy_dynamic_module_on_http_filter_config_http_stream_data
func envoy_dynamic_module_on_http_filter_config_http_stream_data(
	_ C.envoy_dynamic_module_type_http_filter_config_envoy_ptr,
	configPtr C.envoy_dynamic_module_type_http_filter_config_module_ptr,
	streamID C.uint64_t,
	chunks C.ConstEnvoyBufferPtr,
	chunksSize C.size_t,
	endOfStream C.bool,
) {
	configWrapper := configManager.unwrap(unsafe.Pointer(configPtr))
	if configWrapper == nil || configWrapper.configHandle == nil {
		return
	}
	ch := configWrapper.configHandle
	resultData := envoyBufferSliceToUnsafeEnvoyBufferSlice(unsafe.Slice(chunks, int(chunksSize)))
	cb := ch.streamCallbacks[uint64(streamID)]
	if cb != nil {
		cb.OnHttpStreamData(uint64(streamID), resultData, bool(endOfStream))
	}
}
//export envoy_dynamic_module_on_http_filter_config_http_stream_trailers
func envoy_dynamic_module_on_http_filter_config_http_stream_trailers(
	_ C.envoy_dynamic_module_type_http_filter_config_envoy_ptr,
	configPtr C.envoy_dynamic_module_type_http_filter_config_module_ptr,
	streamID C.uint64_t,
	trailers *C.envoy_dynamic_module_type_envoy_http_header,
	trailersSize C.size_t,
) {
	configWrapper := configManager.unwrap(unsafe.Pointer(configPtr))
	if configWrapper == nil || configWrapper.configHandle == nil {
		return
	}
	ch := configWrapper.configHandle
	resultTrailers := envoyHttpHeaderSliceToUnsafeHeaderSlice(unsafe.Slice(trailers, int(trailersSize)))
	cb := ch.streamCallbacks[uint64(streamID)]
	if cb != nil {
		cb.OnHttpStreamTrailers(uint64(streamID), resultTrailers)
	}
}
//export envoy_dynamic_module_on_http_filter_config_http_stream_complete
func envoy_dynamic_module_on_http_filter_config_http_stream_complete(
	_ C.envoy_dynamic_module_type_http_filter_config_envoy_ptr,
	configPtr C.envoy_dynamic_module_type_http_filter_config_module_ptr,
	streamID C.uint64_t,
) {
	configWrapper := configManager.unwrap(unsafe.Pointer(configPtr))
	if configWrapper == nil || configWrapper.configHandle == nil {
		return
	}
	ch := configWrapper.configHandle
	cb := ch.streamCallbacks[uint64(streamID)]
	if cb != nil {
		delete(ch.streamCallbacks, uint64(streamID))
		cb.OnHttpStreamComplete(uint64(streamID))
	}
}
//export envoy_dynamic_module_on_http_filter_config_http_stream_reset
func envoy_dynamic_module_on_http_filter_config_http_stream_reset(
	_ C.envoy_dynamic_module_type_http_filter_config_envoy_ptr,
	configPtr C.envoy_dynamic_module_type_http_filter_config_module_ptr,
	streamID C.uint64_t,
	reason C.envoy_dynamic_module_type_http_stream_reset_reason,
) {
	configWrapper := configManager.unwrap(unsafe.Pointer(configPtr))
	if configWrapper == nil || configWrapper.configHandle == nil {
		return
	}
	ch := configWrapper.configHandle
	cb := ch.streamCallbacks[uint64(streamID)]
	if cb != nil {
		delete(ch.streamCallbacks, uint64(streamID))
		cb.OnHttpStreamReset(uint64(streamID), shared.HttpStreamResetReason(reason))
	}
}
//export envoy_dynamic_module_on_http_filter_config_scheduled
func envoy_dynamic_module_on_http_filter_config_scheduled(
	_ C.envoy_dynamic_module_type_http_filter_config_envoy_ptr,
	configPtr C.envoy_dynamic_module_type_http_filter_config_module_ptr,
	taskID C.uint64_t,
) {
	configWrapper := configManager.unwrap(unsafe.Pointer(configPtr))
	if configWrapper == nil || configWrapper.configHandle == nil {
		return
	}
	ch := configWrapper.configHandle
	if ch.scheduler != nil {
		ch.scheduler.onScheduled(uint64(taskID))
	}
}