22#include <ngx_core.h>
33#include <ngx_http.h>
44#include "ngx_http_wasm_state.h"
5+ #include "ngx_http_wasm_ctx.h"
56#include "vm/vm.h"
67
78
@@ -26,22 +27,9 @@ typedef struct {
2627} ngx_http_wasm_main_conf_t ;
2728
2829
29- typedef struct {
30- void * plugin ;
31- uint32_t cur_ctx_id ;
32- ngx_queue_t occupied ;
33- ngx_queue_t free ;
34- unsigned done :1 ;
35- } ngx_http_wasm_plugin_t ;
36-
37-
38- typedef struct {
39- uint32_t id ;
40- ngx_http_wasm_state_t * state ;
41- ngx_http_wasm_plugin_t * hw_plugin ;
42- ngx_pool_t * pool ;
43- ngx_queue_t queue ;
44- } ngx_http_wasm_plugin_ctx_t ;
30+ typedef enum {
31+ HTTP_REQUEST_HEADERS = 1 ,
32+ } ngx_http_wasm_phase_t ;
4533
4634
4735static ngx_command_t ngx_http_wasm_cmds [] = {
@@ -249,7 +237,7 @@ ngx_http_wasm_unload_plugin(ngx_http_wasm_plugin_t *hw_plugin)
249237
250238
251239void
252- ngx_http_wasm_delete_plugin_ctx (ngx_http_wasm_plugin_ctx_t * hwp_ctx )
240+ ngx_http_wasm_free_plugin_ctx (ngx_http_wasm_plugin_ctx_t * hwp_ctx )
253241{
254242 ngx_int_t rc ;
255243 uint32_t ctx_id = hwp_ctx -> id ;
@@ -259,6 +247,11 @@ ngx_http_wasm_delete_plugin_ctx(ngx_http_wasm_plugin_ctx_t *hwp_ctx)
259247
260248 log = ngx_cycle -> log ;
261249
250+ if (!ngx_queue_empty (& hwp_ctx -> occupied )) {
251+ /* some http ctxs are using it. Do not free */
252+ return ;
253+ }
254+
262255 ngx_queue_remove (& hwp_ctx -> queue );
263256 ngx_queue_insert_head (& hw_plugin -> free , & hwp_ctx -> queue );
264257
@@ -279,12 +272,22 @@ ngx_http_wasm_delete_plugin_ctx(ngx_http_wasm_plugin_ctx_t *hwp_ctx)
279272 hwp_ctx -> pool = NULL ;
280273 }
281274
275+ ngx_log_error (NGX_LOG_INFO , log , 0 , "free plugin context %d" , ctx_id );
276+
282277 if (hw_plugin -> done ) {
283278 ngx_http_wasm_free_plugin (hw_plugin );
284279 }
285280}
286281
287282
283+ void
284+ ngx_http_wasm_delete_plugin_ctx (ngx_http_wasm_plugin_ctx_t * hwp_ctx )
285+ {
286+ hwp_ctx -> done = 1 ;
287+ ngx_http_wasm_free_plugin_ctx (hwp_ctx );
288+ }
289+
290+
288291void *
289292ngx_http_wasm_on_configure (ngx_http_wasm_plugin_t * hw_plugin , const char * conf , size_t size )
290293{
@@ -320,6 +323,8 @@ ngx_http_wasm_on_configure(ngx_http_wasm_plugin_t *hw_plugin, const char *conf,
320323 ctx_id = hw_plugin -> cur_ctx_id ;
321324 hwp_ctx -> id = ctx_id ;
322325 hwp_ctx -> hw_plugin = hw_plugin ;
326+ ngx_queue_init (& hwp_ctx -> occupied );
327+ ngx_queue_init (& hwp_ctx -> free );
323328 }
324329
325330 rc = ngx_wasm_vm .call (plugin , & proxy_on_context_create , false,
@@ -369,3 +374,174 @@ ngx_http_wasm_on_configure(ngx_http_wasm_plugin_t *hw_plugin, const char *conf,
369374 ngx_http_wasm_delete_plugin_ctx (hwp_ctx );
370375 return NULL ;
371376}
377+
378+
379+ ngx_http_wasm_http_ctx_t *
380+ ngx_http_wasm_create_http_ctx (ngx_http_wasm_plugin_ctx_t * hwp_ctx , ngx_http_request_t * r )
381+ {
382+ ngx_int_t rc ;
383+ uint32_t ctx_id ;
384+ ngx_http_wasm_http_ctx_t * http_ctx ;
385+ ngx_http_wasm_plugin_t * hw_plugin = hwp_ctx -> hw_plugin ;
386+ void * plugin = hw_plugin -> plugin ;
387+ ngx_log_t * log ;
388+
389+ log = r -> connection -> log ;
390+
391+ if (!ngx_queue_empty (& hwp_ctx -> free )) {
392+ ngx_queue_t * q ;
393+
394+ q = ngx_queue_last (& hwp_ctx -> free );
395+ ngx_queue_remove (q );
396+ http_ctx = ngx_queue_data (q , ngx_http_wasm_http_ctx_t , queue );
397+ ctx_id = http_ctx -> id ;
398+
399+ } else {
400+ http_ctx = ngx_pcalloc (hwp_ctx -> pool , sizeof (ngx_http_wasm_http_ctx_t ));
401+ if (http_ctx == NULL ) {
402+ ngx_log_error (NGX_LOG_ERR , log , 0 , "no memory" );
403+ return NULL ;
404+ }
405+
406+ hw_plugin -> cur_ctx_id ++ ;
407+ ctx_id = hw_plugin -> cur_ctx_id ;
408+ http_ctx -> id = ctx_id ;
409+ http_ctx -> hwp_ctx = hwp_ctx ;
410+ }
411+
412+ rc = ngx_wasm_vm .call (plugin , & proxy_on_context_create , false,
413+ NGX_WASM_PARAM_I32_I32 , ctx_id , hwp_ctx -> id );
414+ if (rc != NGX_OK ) {
415+ ngx_log_error (NGX_LOG_ERR , log , 0 , "failed to create context %d, rc: %d" ,
416+ ctx_id , rc );
417+ /* reuse the ctx_id */
418+ ngx_queue_insert_head (& hwp_ctx -> free , & http_ctx -> queue );
419+ return NULL ;
420+ }
421+
422+ ngx_queue_insert_head (& hwp_ctx -> occupied , & http_ctx -> queue );
423+
424+ ngx_log_error (NGX_LOG_INFO , ngx_cycle -> log , 0 , "create http context %d" , ctx_id );
425+
426+ return http_ctx ;
427+ }
428+
429+
430+ static void
431+ ngx_http_wasm_cleanup (void * data )
432+ {
433+ ngx_int_t rc ;
434+ ngx_http_wasm_ctx_t * ctx = data ;
435+ ngx_http_wasm_http_ctx_t * http_ctx = ctx -> http_ctx ;
436+ uint32_t ctx_id ;
437+ ngx_http_wasm_plugin_ctx_t * hwp_ctx ;
438+ void * plugin ;
439+ ngx_log_t * log ;
440+
441+ log = ngx_cycle -> log ;
442+
443+ if (http_ctx == NULL ) {
444+ return ;
445+ }
446+
447+ ctx_id = http_ctx -> id ;
448+ hwp_ctx = http_ctx -> hwp_ctx ;
449+ plugin = hwp_ctx -> hw_plugin -> plugin ;
450+
451+ ngx_queue_remove (& http_ctx -> queue );
452+ ngx_queue_insert_head (& hwp_ctx -> free , & http_ctx -> queue );
453+
454+ rc = ngx_wasm_vm .call (plugin , & proxy_on_done , true, NGX_WASM_PARAM_I32 , ctx_id );
455+ if (rc <= 0 ) {
456+ ngx_log_error (NGX_LOG_ERR , log , 0 , "failed to mark context %d as done, rc: %d" ,
457+ ctx_id , rc );
458+ }
459+
460+ rc = ngx_wasm_vm .call (plugin , & proxy_on_delete , false, NGX_WASM_PARAM_I32 , ctx_id );
461+ if (rc != NGX_OK ) {
462+ ngx_log_error (NGX_LOG_ERR , log , 0 , "failed to delete context %d, rc: %d" ,
463+ ctx_id , rc );
464+ }
465+
466+ ngx_log_error (NGX_LOG_INFO , log , 0 , "free http context %d" , ctx_id );
467+
468+ if (hwp_ctx -> done ) {
469+ ngx_http_wasm_free_plugin_ctx (hwp_ctx );
470+ }
471+ }
472+
473+
474+ static ngx_http_wasm_ctx_t *
475+ ngx_http_wasm_get_module_ctx (ngx_http_request_t * r )
476+ {
477+ ngx_http_wasm_ctx_t * ctx ;
478+ ngx_pool_cleanup_t * cln ;
479+
480+ ctx = ngx_http_get_module_ctx (r , ngx_http_wasm_module );
481+
482+ if (ctx == NULL ) {
483+ ctx = ngx_pcalloc (r -> pool , sizeof (ngx_http_wasm_ctx_t ));
484+ if (ctx == NULL ) {
485+ ngx_log_error (NGX_LOG_ERR , r -> connection -> log , 0 , "no memory" );
486+ return NULL ;
487+ }
488+
489+ cln = ngx_pool_cleanup_add (r -> pool , 0 );
490+ if (cln == NULL ) {
491+ ngx_log_error (NGX_LOG_ERR , r -> connection -> log , 0 , "no memory" );
492+ return NULL ;
493+ }
494+
495+ cln -> data = ctx ;
496+ cln -> handler = ngx_http_wasm_cleanup ;
497+
498+ ngx_http_set_ctx (r , ctx , ngx_http_wasm_module );
499+ }
500+
501+ return ctx ;
502+ }
503+
504+
505+ ngx_http_wasm_http_ctx_t *
506+ ngx_http_wasm_fetch_http_ctx (ngx_http_wasm_plugin_ctx_t * hwp_ctx , ngx_http_request_t * r )
507+ {
508+ ngx_http_wasm_ctx_t * ctx ;
509+
510+
511+ ctx = ngx_http_wasm_get_module_ctx (r );
512+ if (ctx == NULL ) {
513+ return NULL ;
514+ }
515+
516+ if (ctx -> http_ctx == NULL ) {
517+ ctx -> http_ctx = ngx_http_wasm_create_http_ctx (hwp_ctx , r );
518+ }
519+
520+ return ctx -> http_ctx ;
521+ }
522+
523+
524+ ngx_int_t
525+ ngx_http_wasm_on_http (ngx_http_wasm_plugin_ctx_t * hwp_ctx , ngx_http_request_t * r ,
526+ ngx_http_wasm_phase_t type )
527+ {
528+ ngx_int_t rc ;
529+ ngx_log_t * log ;
530+ ngx_http_wasm_http_ctx_t * http_ctx ;
531+
532+ log = r -> connection -> log ;
533+
534+ if (!ngx_http_wasm_vm_inited ) {
535+ ngx_log_error (NGX_LOG_ERR , log , 0 , "miss wasm_vm configuration" );
536+ return NGX_DECLINED ;
537+ }
538+
539+ rc = NGX_OK ;
540+
541+ http_ctx = ngx_http_wasm_fetch_http_ctx (hwp_ctx , r );
542+ if (http_ctx == NULL ) {
543+ return NGX_DECLINED ;
544+ }
545+
546+ return rc ;
547+ }
0 commit comments