1 
2 /*
3  * Copyright (C) Yichun Zhang (agentzh)
4  */
5 
6 
7 #ifndef DDEBUG
8 #define DDEBUG 0
9 #endif
10 #include "ddebug.h"
11 
12 
13 #include "ngx_http_lua_util.h"
14 #include "ngx_http_lua_ssl.h"
15 #include "ngx_http_lua_ctx.h"
16 
17 
18 typedef struct {
19     int              ref;
20     lua_State       *vm;
21 } ngx_http_lua_ngx_ctx_cleanup_data_t;
22 
23 
24 static ngx_int_t ngx_http_lua_ngx_ctx_add_cleanup(ngx_http_request_t *r,
25     ngx_pool_t *pool, int ref);
26 static void ngx_http_lua_ngx_ctx_cleanup(void *data);
27 
28 
29 int
ngx_http_lua_ngx_set_ctx_helper(lua_State * L,ngx_http_request_t * r,ngx_http_lua_ctx_t * ctx,int index)30 ngx_http_lua_ngx_set_ctx_helper(lua_State *L, ngx_http_request_t *r,
31     ngx_http_lua_ctx_t *ctx, int index)
32 {
33     ngx_pool_t              *pool;
34 
35     if (index < 0) {
36         index = lua_gettop(L) + index + 1;
37     }
38 
39     if (ctx->ctx_ref == LUA_NOREF) {
40         ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
41                        "lua create ngx.ctx table for the current request");
42 
43         lua_pushliteral(L, ngx_http_lua_ctx_tables_key);
44         lua_rawget(L, LUA_REGISTRYINDEX);
45         lua_pushvalue(L, index);
46         ctx->ctx_ref = luaL_ref(L, -2);
47         lua_pop(L, 1);
48 
49         pool = r->pool;
50         if (ngx_http_lua_ngx_ctx_add_cleanup(r, pool, ctx->ctx_ref) != NGX_OK) {
51             return luaL_error(L, "no memory");
52         }
53 
54         return 0;
55     }
56 
57     ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
58                    "lua fetching existing ngx.ctx table for the current "
59                    "request");
60 
61     lua_pushliteral(L, ngx_http_lua_ctx_tables_key);
62     lua_rawget(L, LUA_REGISTRYINDEX);
63     luaL_unref(L, -1, ctx->ctx_ref);
64     lua_pushvalue(L, index);
65     ctx->ctx_ref = luaL_ref(L, -2);
66     lua_pop(L, 1);
67 
68     return 0;
69 }
70 
71 
72 int
ngx_http_lua_ffi_get_ctx_ref(ngx_http_request_t * r,int * in_ssl_phase,int * ssl_ctx_ref)73 ngx_http_lua_ffi_get_ctx_ref(ngx_http_request_t *r, int *in_ssl_phase,
74     int *ssl_ctx_ref)
75 {
76     ngx_http_lua_ctx_t              *ctx;
77 #if (NGX_HTTP_SSL)
78     ngx_http_lua_ssl_ctx_t          *ssl_ctx;
79 #endif
80 
81     ctx = ngx_http_get_module_ctx(r, ngx_http_lua_module);
82     if (ctx == NULL) {
83         return NGX_HTTP_LUA_FFI_NO_REQ_CTX;
84     }
85 
86     if (ctx->ctx_ref >= 0 || in_ssl_phase == NULL) {
87         return ctx->ctx_ref;
88     }
89 
90     *in_ssl_phase = ctx->context & (NGX_HTTP_LUA_CONTEXT_SSL_CERT
91                                     | NGX_HTTP_LUA_CONTEXT_SSL_SESS_FETCH
92                                     | NGX_HTTP_LUA_CONTEXT_SSL_SESS_STORE);
93     *ssl_ctx_ref = LUA_NOREF;
94 
95 #if (NGX_HTTP_SSL)
96     if (r->connection->ssl != NULL) {
97         ssl_ctx = ngx_http_lua_ssl_get_ctx(r->connection->ssl->connection);
98 
99         if (ssl_ctx != NULL) {
100             *ssl_ctx_ref = ssl_ctx->ctx_ref;
101         }
102     }
103 #endif
104 
105     return LUA_NOREF;
106 }
107 
108 
109 int
ngx_http_lua_ffi_set_ctx_ref(ngx_http_request_t * r,int ref)110 ngx_http_lua_ffi_set_ctx_ref(ngx_http_request_t *r, int ref)
111 {
112     ngx_pool_t                      *pool;
113     ngx_http_lua_ctx_t              *ctx;
114 #if (NGX_HTTP_SSL)
115     ngx_connection_t                *c;
116     ngx_http_lua_ssl_ctx_t          *ssl_ctx;
117 #endif
118 
119     ctx = ngx_http_get_module_ctx(r, ngx_http_lua_module);
120     if (ctx == NULL) {
121         return NGX_HTTP_LUA_FFI_NO_REQ_CTX;
122     }
123 
124 #if (NGX_HTTP_SSL)
125     if (ctx->context & (NGX_HTTP_LUA_CONTEXT_SSL_CERT
126                         | NGX_HTTP_LUA_CONTEXT_SSL_SESS_FETCH
127                         | NGX_HTTP_LUA_CONTEXT_SSL_SESS_STORE))
128     {
129         ssl_ctx = ngx_http_lua_ssl_get_ctx(r->connection->ssl->connection);
130         if (ssl_ctx == NULL) {
131             return NGX_ERROR;
132         }
133 
134         ssl_ctx->ctx_ref = ref;
135         c = ngx_ssl_get_connection(r->connection->ssl->connection);
136         pool = c->pool;
137 
138     } else {
139         pool = r->pool;
140     }
141 
142 #else
143     pool = r->pool;
144 #endif
145 
146     ctx->ctx_ref = ref;
147 
148     if (ngx_http_lua_ngx_ctx_add_cleanup(r, pool, ref) != NGX_OK) {
149         return NGX_ERROR;
150     }
151 
152     return NGX_OK;
153 }
154 
155 
156 static ngx_int_t
ngx_http_lua_ngx_ctx_add_cleanup(ngx_http_request_t * r,ngx_pool_t * pool,int ref)157 ngx_http_lua_ngx_ctx_add_cleanup(ngx_http_request_t *r, ngx_pool_t *pool,
158     int ref)
159 {
160     lua_State                   *L;
161     ngx_pool_cleanup_t          *cln;
162     ngx_http_lua_ctx_t          *ctx;
163 
164     ngx_http_lua_ngx_ctx_cleanup_data_t    *data;
165 
166     ctx = ngx_http_get_module_ctx(r, ngx_http_lua_module);
167     L = ngx_http_lua_get_lua_vm(r, ctx);
168 
169     cln = ngx_pool_cleanup_add(pool,
170                                sizeof(ngx_http_lua_ngx_ctx_cleanup_data_t));
171     if (cln == NULL) {
172         return NGX_ERROR;
173     }
174 
175     cln->handler = ngx_http_lua_ngx_ctx_cleanup;
176 
177     data = cln->data;
178     data->vm = L;
179     data->ref = ref;
180 
181     return NGX_OK;
182 }
183 
184 
185 static void
ngx_http_lua_ngx_ctx_cleanup(void * data)186 ngx_http_lua_ngx_ctx_cleanup(void *data)
187 {
188     lua_State       *L;
189 
190     ngx_http_lua_ngx_ctx_cleanup_data_t    *clndata = data;
191 
192     ngx_log_debug1(NGX_LOG_DEBUG_HTTP, ngx_cycle->log, 0,
193                    "lua release ngx.ctx at ref %d", clndata->ref);
194 
195     L = clndata->vm;
196 
197     lua_pushliteral(L, ngx_http_lua_ctx_tables_key);
198     lua_rawget(L, LUA_REGISTRYINDEX);
199     luaL_unref(L, -1, clndata->ref);
200     lua_pop(L, 1);
201 }
202 
203 
204 /* vi:set ft=c ts=4 sw=4 et fdm=marker: */
205