summaryrefslogtreecommitdiff
path: root/ngx_stream_lua-0.0.16/src/ngx_stream_lua_common.h
blob: f76229e1b6c828253e5c4d27a9beacbcf1a61798 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
/*
 * !!! DO NOT EDIT DIRECTLY !!!
 * This file was automatically generated from the following template:
 *
 * src/subsys/ngx_subsys_lua_common.h.tt2
 */


/*
 * Copyright (C) Xiaozhe Wang (chaoslawful)
 * Copyright (C) Yichun Zhang (agentzh)
 */


#ifndef _NGX_STREAM_LUA_COMMON_H_INCLUDED_
#define _NGX_STREAM_LUA_COMMON_H_INCLUDED_


#include "ngx_stream_lua_autoconf.h"

#include <nginx.h>
#include <ngx_core.h>
#include <ngx_stream.h>
#include <ngx_md5.h>

#include <setjmp.h>
#include <stdint.h>

#include <luajit.h>
#include <lualib.h>
#include <lauxlib.h>


#include "ngx_stream_lua_request.h"


#if (NGX_PCRE)
#   if (NGX_PCRE2)
#      define LUA_HAVE_PCRE_JIT 1
#   else

#include <pcre.h>

#       if (PCRE_MAJOR > 8) || (PCRE_MAJOR == 8 && PCRE_MINOR >= 21)
#           define LUA_HAVE_PCRE_JIT 1
#       else
#           define LUA_HAVE_PCRE_JIT 0
#       endif
#   endif
#endif


#if !defined(nginx_version) || nginx_version < 1013006
#error at least nginx 1.13.6 is required but found an older version
#endif




#if LUA_VERSION_NUM != 501
#   error unsupported Lua language version
#endif


#if !defined(LUAJIT_VERSION_NUM) || (LUAJIT_VERSION_NUM < 20000)
#   error unsupported LuaJIT version
#endif


#if (!defined OPENSSL_NO_OCSP && defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB)
#   define NGX_STREAM_LUA_USE_OCSP 1
#endif




#ifndef NGX_HAVE_SHA1
#   if defined(nginx_version) && nginx_version >= 1011002
#       define NGX_HAVE_SHA1  1
#   endif
#endif


#ifndef MD5_DIGEST_LENGTH
#define MD5_DIGEST_LENGTH 16
#endif


#ifdef NGX_LUA_USE_ASSERT
#   include <assert.h>
#   define ngx_stream_lua_assert(a)  assert(a)
#else
#   define ngx_stream_lua_assert(a)
#endif


/* Nginx HTTP Lua Inline tag prefix */

#define NGX_STREAM_LUA_INLINE_TAG "nhli_"

#define NGX_STREAM_LUA_INLINE_TAG_LEN                                        \
    (sizeof(NGX_STREAM_LUA_INLINE_TAG) - 1)

#define NGX_STREAM_LUA_INLINE_KEY_LEN                                        \
    (NGX_STREAM_LUA_INLINE_TAG_LEN + 2 * MD5_DIGEST_LENGTH)

/* Nginx HTTP Lua File tag prefix */

#define NGX_STREAM_LUA_FILE_TAG "nhlf_"

#define NGX_STREAM_LUA_FILE_TAG_LEN                                          \
    (sizeof(NGX_STREAM_LUA_FILE_TAG) - 1)

#define NGX_STREAM_LUA_FILE_KEY_LEN                                          \
    (NGX_STREAM_LUA_FILE_TAG_LEN + 2 * MD5_DIGEST_LENGTH)


#define NGX_STREAM_CLIENT_CLOSED_REQUEST     499




#ifndef NGX_STREAM_LUA_MAX_ARGS
#define NGX_STREAM_LUA_MAX_ARGS 100
#endif


/* must be within 16 bit */
#define NGX_STREAM_LUA_CONTEXT_CONTENT                              0x0001
#define NGX_STREAM_LUA_CONTEXT_LOG                                  0x0002
#define NGX_STREAM_LUA_CONTEXT_TIMER                                0x0004
#define NGX_STREAM_LUA_CONTEXT_INIT_WORKER                          0x0008
#define NGX_STREAM_LUA_CONTEXT_BALANCER                             0x0010
#define NGX_STREAM_LUA_CONTEXT_PREREAD                              0x0020
#define NGX_STREAM_LUA_CONTEXT_SSL_CERT                             0x0040
#define NGX_STREAM_LUA_CONTEXT_SSL_CLIENT_HELLO                     0x0080


#define NGX_STREAM_LUA_FFI_NO_REQ_CTX         -100
#define NGX_STREAM_LUA_FFI_BAD_CONTEXT        -101


#if (NGX_PTR_SIZE >= 8 && !defined(_WIN64))
#define ngx_stream_lua_lightudata_mask(ludata)                               \
    ((void *) ((uintptr_t) (&ngx_stream_lua_##ludata) & ((1UL << 47) - 1)))

#else
#define ngx_stream_lua_lightudata_mask(ludata)                               \
    (&ngx_stream_lua_##ludata)
#endif


typedef struct ngx_stream_lua_main_conf_s  ngx_stream_lua_main_conf_t;
typedef struct ngx_stream_lua_srv_conf_s  ngx_stream_lua_srv_conf_t;


typedef struct ngx_stream_lua_balancer_peer_data_s
    ngx_stream_lua_balancer_peer_data_t;


typedef struct ngx_stream_lua_sema_mm_s  ngx_stream_lua_sema_mm_t;


typedef ngx_int_t (*ngx_stream_lua_main_conf_handler_pt)(ngx_log_t *log,
    ngx_stream_lua_main_conf_t *lmcf, lua_State *L);
typedef ngx_int_t (*ngx_stream_lua_srv_conf_handler_pt)(
    ngx_stream_lua_request_t *r, ngx_stream_lua_srv_conf_t *lscf, lua_State *L);


typedef struct {
    u_char              *package;
    lua_CFunction        loader;
} ngx_stream_lua_preload_hook_t;


struct ngx_stream_lua_main_conf_s {
    lua_State           *lua;
    ngx_pool_cleanup_t  *vm_cleanup;

    ngx_str_t            lua_path;
    ngx_str_t            lua_cpath;

    ngx_cycle_t         *cycle;
    ngx_pool_t          *pool;

    ngx_int_t            max_pending_timers;
    ngx_int_t            pending_timers;

    ngx_int_t            max_running_timers;
    ngx_int_t            running_timers;

    ngx_connection_t    *watcher;  /* for watching the process exit event */

#if (NGX_PCRE)
    ngx_int_t            regex_cache_entries;
    ngx_int_t            regex_cache_max_entries;
    ngx_int_t            regex_match_limit;
#endif

#if (LUA_HAVE_PCRE_JIT)
#if (NGX_PCRE2)
    pcre2_jit_stack     *jit_stack;
#else
    pcre_jit_stack      *jit_stack;
#endif
#endif

    ngx_array_t         *shm_zones;  /* of ngx_shm_zone_t* */

    ngx_array_t         *shdict_zones; /* shm zones of "shdict" */

    ngx_array_t         *preload_hooks; /* of ngx_stream_lua_preload_hook_t */

    ngx_flag_t           postponed_to_preread_phase_end;

    ngx_stream_lua_main_conf_handler_pt          init_handler;
    ngx_str_t                                    init_src;

    ngx_stream_lua_main_conf_handler_pt          init_worker_handler;
    ngx_str_t                                    init_worker_src;

    ngx_stream_lua_balancer_peer_data_t          *balancer_peer_data;
                    /* neither yielding nor recursion is possible in
                     * balancer_by_lua*, so there cannot be any races among
                     * concurrent requests and it is safe to store the peer
                     * data pointer in the main conf.
                     */

    ngx_uint_t                      shm_zones_inited;

    ngx_stream_lua_sema_mm_t               *sema_mm;

    ngx_uint_t           malloc_trim_cycle;  /* a cycle is defined as the number
                                                of reqeusts */
    ngx_uint_t           malloc_trim_req_count;


    ngx_flag_t           set_sa_restart;

    unsigned             requires_preread:1;

    unsigned             requires_log:1;
    unsigned             requires_shm:1;
    unsigned             requires_capture_log:1;
};




struct ngx_stream_lua_srv_conf_s {
#if (NGX_STREAM_SSL)
    ngx_ssl_t              *ssl;  /* shared by SSL cosockets */
    ngx_array_t            *ssl_certificates;
    ngx_array_t            *ssl_certificate_keys;
    ngx_uint_t              ssl_protocols;
    ngx_str_t               ssl_ciphers;
    ngx_uint_t              ssl_verify_depth;
    ngx_str_t               ssl_trusted_certificate;
    ngx_str_t               ssl_crl;
#if (nginx_version >= 1019004)
    ngx_array_t            *ssl_conf_commands;
#endif

    struct {
        ngx_stream_lua_srv_conf_handler_pt           ssl_cert_handler;
        ngx_str_t                                    ssl_cert_src;
        u_char                                      *ssl_cert_src_key;

        ngx_stream_lua_srv_conf_handler_pt           ssl_client_hello_handler;
        ngx_str_t                                    ssl_client_hello_src;
        u_char                                      *ssl_client_hello_src_key;
    } srv;
#endif

    ngx_flag_t              enable_code_cache; /* whether to enable
                                                  code cache */

    ngx_stream_lua_handler_pt           preread_handler;

    ngx_stream_lua_handler_pt           content_handler;
    ngx_stream_lua_handler_pt           log_handler;

    u_char                      *preread_chunkname;
    ngx_stream_complex_value_t   preread_src;     /* access_by_lua
                                                inline script/script
                                                file path */

    u_char                  *preread_src_key; /* cached key for access_src */

    u_char                  *content_chunkname;

    ngx_stream_complex_value_t       content_src;
                                                  /* content_by_lua
                                                   * inline script/script
                                                   * file path */

    u_char                 *content_src_key; /* cached key for content_src */

    u_char                           *log_chunkname;
    ngx_stream_complex_value_t        log_src;
                                              /* log_by_lua inline script/script
                                               * file path */

    u_char                                 *log_src_key;
    /* cached key for log_src */


    ngx_msec_t                       keepalive_timeout;
    ngx_msec_t                       connect_timeout;
    ngx_msec_t                       send_timeout;
    ngx_msec_t                       read_timeout;

    size_t                           send_lowat;
    size_t                           buffer_size;

    ngx_uint_t                       pool_size;


    ngx_flag_t                       log_socket_errors;
    ngx_flag_t                       check_client_abort;


    struct {
        ngx_str_t           src;
        u_char             *src_key;

        ngx_stream_lua_srv_conf_handler_pt        handler;
    } balancer;

};

typedef ngx_stream_lua_srv_conf_t ngx_stream_lua_loc_conf_t;


typedef enum {
    NGX_STREAM_LUA_USER_CORO_NOP      = 0,
    NGX_STREAM_LUA_USER_CORO_RESUME   = 1,
    NGX_STREAM_LUA_USER_CORO_YIELD    = 2,
    NGX_STREAM_LUA_USER_THREAD_RESUME = 3
} ngx_stream_lua_user_coro_op_t;


typedef enum {
    NGX_STREAM_LUA_CO_RUNNING   = 0, /* coroutine running */
    NGX_STREAM_LUA_CO_SUSPENDED = 1, /* coroutine suspended */
    NGX_STREAM_LUA_CO_NORMAL    = 2, /* coroutine normal */
    NGX_STREAM_LUA_CO_DEAD      = 3, /* coroutine dead */
    NGX_STREAM_LUA_CO_ZOMBIE    = 4, /* coroutine zombie */
} ngx_stream_lua_co_status_t;


typedef struct ngx_stream_lua_co_ctx_s  ngx_stream_lua_co_ctx_t;

typedef struct ngx_stream_lua_posted_thread_s  ngx_stream_lua_posted_thread_t;

struct ngx_stream_lua_posted_thread_s {
    ngx_stream_lua_co_ctx_t                     *co_ctx;
    ngx_stream_lua_posted_thread_t              *next;
};




struct ngx_stream_lua_co_ctx_s {
    void                    *data;      /* user state for cosockets */

    lua_State                       *co;
    ngx_stream_lua_co_ctx_t         *parent_co_ctx;

    ngx_stream_lua_posted_thread_t          *zombie_child_threads;

    ngx_stream_lua_cleanup_pt      cleanup;


    ngx_event_t              sleep;  /* used for ngx.sleep */

    ngx_queue_t              sem_wait_queue;

#ifdef NGX_LUA_USE_ASSERT
    int                      co_top; /* stack top after yielding/creation,
                                        only for sanity checks */
#endif

    int                      co_ref; /*  reference to anchor the thread
                                         coroutines (entry coroutine and user
                                         threads) in the Lua registry,
                                         preventing the thread coroutine
                                         from beging collected by the
                                         Lua GC */

    unsigned                 waited_by_parent:1;  /* whether being waited by
                                                     a parent coroutine */

    unsigned                 co_status:3;  /* the current coroutine's status */

    unsigned                 flushing:1; /* indicates whether the current
                                            coroutine is waiting for
                                            ngx.flush(true) */

    unsigned                 is_uthread:1; /* whether the current coroutine is
                                              a user thread */

    unsigned                 thread_spawn_yielded:1; /* yielded from
                                                        the ngx.thread.spawn()
                                                        call */
    unsigned                 sem_resume_status:1;

    unsigned                 is_wrap:1; /* set when creating coroutines via
                                           coroutine.wrap */

    unsigned                 propagate_error:1; /* set when propagating an error
                                                   from a coroutine to its
                                                   parent */
};


typedef struct {
    lua_State       *vm;
    ngx_int_t        count;
} ngx_stream_lua_vm_state_t;


typedef struct ngx_stream_lua_ctx_s {
    /* for lua_coce_cache off: */
    ngx_stream_lua_vm_state_t           *vm_state;

    ngx_stream_lua_request_t            *request;
    ngx_stream_lua_handler_pt            resume_handler;

    ngx_stream_lua_co_ctx_t             *cur_co_ctx;
                                    /* co ctx for the current coroutine */

    /* FIXME: we should use rbtree here to prevent O(n) lookup overhead */
    ngx_list_t              *user_co_ctx; /* coroutine contexts for user
                                             coroutines */

    ngx_stream_lua_co_ctx_t    entry_co_ctx; /* coroutine context for the
                                              entry coroutine */

    ngx_stream_lua_co_ctx_t   *on_abort_co_ctx; /* coroutine context for the
                                                 on_abort thread */

    int                      ctx_ref;  /*  reference to anchor
                                           request ctx data in lua
                                           registry */

    unsigned                 flushing_coros; /* number of coroutines waiting on
                                                ngx.flush(true) */

    ngx_chain_t             *out;  /* buffered output chain for HTTP 1.0 */
    ngx_chain_t             *free_bufs;
    ngx_chain_t             *busy_bufs;
    ngx_chain_t             *free_recv_bufs;

    ngx_stream_lua_cleanup_pt  *cleanup;
    ngx_stream_lua_cleanup_t   *free_cleanup; /* free list of cleanup records */



    ngx_int_t                exit_code;

    void                    *downstream;
                                    /* can be either
                                     * ngx_stream_lua_socket_tcp_upstream_t
                                     * or ngx_stream_lua_co_ctx_t */


    ngx_stream_lua_posted_thread_t         *posted_threads;

    int                      uthreads; /* number of active user threads */

    uint16_t                 context;   /* the current running directive context
                                           (or running phase) for the current
                                           Lua chunk */


    unsigned                 waiting_more_body:1;   /* 1: waiting for more
                                                       request body data;
                                                       0: no need to wait */

    unsigned         co_op:2; /*  coroutine API operation */

    unsigned         exited:1;

    unsigned         eof:1;             /*  1: last_buf has been sent;
                                            0: last_buf not sent yet */

    unsigned         capture:1;  /*  1: response body of current request
                                        is to be captured by the lua
                                        capture filter,
                                     0: not to be captured */


    unsigned         read_body_done:1;      /* 1: request body has been all
                                               read; 0: body has not been
                                               all read */

    unsigned         headers_set:1; /* whether the user has set custom
                                       response headers */

    unsigned         entered_preread_phase:1;

    unsigned         entered_content_phase:1;

    unsigned         buffering:1; /* HTTP 1.0 response body buffering flag */

    unsigned         no_abort:1; /* prohibit "world abortion" via ngx.exit()
                                    and etc */

    unsigned         header_sent:1; /* r->header_sent is not sufficient for
                                     * this because special header filters
                                     * like ngx_image_filter may intercept
                                     * the header. so we should always test
                                     * both flags. see the test case in
                                     * t/020-subrequest.t */

    unsigned         seen_last_in_filter:1;  /* used by body_filter_by_lua* */
    unsigned         seen_last_for_subreq:1; /* used by body capture filter */
    unsigned         writing_raw_req_socket:1; /* used by raw downstream
                                                  socket */
    unsigned         acquired_raw_req_socket:1;  /* whether a raw req socket
                                                    is acquired */
    unsigned         seen_body_data:1;
    unsigned         peek_needs_more_data:1; /* whether req socket is waiting
                                               for more data in preread buf */
} ngx_stream_lua_ctx_t;




extern ngx_module_t ngx_stream_lua_module;



#endif /* _NGX_STREAM_LUA_COMMON_H_INCLUDED_ */

/* vi:set ft=c ts=4 sw=4 et fdm=marker: */