Mercurial > hg > nginx-quic
annotate src/http/modules/ngx_http_flv_module.c @ 7524:deebe988cbd7
Perl: reworked perl module to pass ctx instead of request.
This ensures that correct ctx is always available, including after
filter finalization. In particular, this fixes a segmentation fault
with the following configuration:
location / {
image_filter test;
perl 'sub {
my $r = shift;
$r->send_http_header();
$r->print("foo\n");
$r->print("bar\n");
}';
}
This also seems to be the only way to correctly handle filter finalization
in various complex cases, for example, when embedded perl is used both
in the original handler and in an error page called after filter
finalization.
author | Maxim Dounin <mdounin@mdounin.ru> |
---|---|
date | Fri, 12 Jul 2019 11:29:22 +0300 |
parents | 99934aade555 |
children | 7a55311b0dc3 |
rev | line source |
---|---|
753 | 1 |
2 /* | |
3 * Copyright (C) Igor Sysoev | |
4412 | 4 * Copyright (C) Nginx, Inc. |
753 | 5 */ |
6 | |
7 #include <ngx_config.h> | |
8 #include <ngx_core.h> | |
9 #include <ngx_http.h> | |
10 | |
11 | |
12 static char *ngx_http_flv(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); | |
13 | |
14 static ngx_command_t ngx_http_flv_commands[] = { | |
15 | |
16 { ngx_string("flv"), | |
17 NGX_HTTP_LOC_CONF|NGX_CONF_NOARGS, | |
18 ngx_http_flv, | |
19 0, | |
20 0, | |
21 NULL }, | |
22 | |
23 ngx_null_command | |
24 }; | |
25 | |
26 | |
4297
2f8e9469b436
Fixed flv header to match specification.
Maxim Dounin <mdounin@mdounin.ru>
parents:
3527
diff
changeset
|
27 static u_char ngx_flv_header[] = "FLV\x1\x5\0\0\0\x9\0\0\0\0"; |
753 | 28 |
29 | |
30 static ngx_http_module_t ngx_http_flv_module_ctx = { | |
31 NULL, /* preconfiguration */ | |
32 NULL, /* postconfiguration */ | |
33 | |
34 NULL, /* create main configuration */ | |
35 NULL, /* init main configuration */ | |
36 | |
37 NULL, /* create server configuration */ | |
38 NULL, /* merge server configuration */ | |
39 | |
40 NULL, /* create location configuration */ | |
41 NULL /* merge location configuration */ | |
42 }; | |
43 | |
44 | |
45 ngx_module_t ngx_http_flv_module = { | |
46 NGX_MODULE_V1, | |
47 &ngx_http_flv_module_ctx, /* module context */ | |
48 ngx_http_flv_commands, /* module directives */ | |
49 NGX_HTTP_MODULE, /* module type */ | |
50 NULL, /* init master */ | |
51 NULL, /* init module */ | |
52 NULL, /* init process */ | |
53 NULL, /* init thread */ | |
54 NULL, /* exit thread */ | |
55 NULL, /* exit process */ | |
56 NULL, /* exit master */ | |
57 NGX_MODULE_V1_PADDING | |
58 }; | |
59 | |
60 | |
61 static ngx_int_t | |
62 ngx_http_flv_handler(ngx_http_request_t *r) | |
63 { | |
2415 | 64 u_char *last; |
753 | 65 off_t start, len; |
774
589841f06b87
previous commit broke two modules
Igor Sysoev <igor@sysoev.ru>
parents:
764
diff
changeset
|
66 size_t root; |
753 | 67 ngx_int_t rc; |
764
761a94247118
do not send flv header for full file
Igor Sysoev <igor@sysoev.ru>
parents:
754
diff
changeset
|
68 ngx_uint_t level, i; |
2415 | 69 ngx_str_t path, value; |
753 | 70 ngx_log_t *log; |
71 ngx_buf_t *b; | |
72 ngx_chain_t out[2]; | |
1454 | 73 ngx_open_file_info_t of; |
753 | 74 ngx_http_core_loc_conf_t *clcf; |
75 | |
76 if (!(r->method & (NGX_HTTP_GET|NGX_HTTP_HEAD))) { | |
77 return NGX_HTTP_NOT_ALLOWED; | |
78 } | |
79 | |
80 if (r->uri.data[r->uri.len - 1] == '/') { | |
81 return NGX_DECLINED; | |
82 } | |
83 | |
1370
cc114c85be0f
rename ngx_http_discard_body() to ngx_http_discard_request_body()
Igor Sysoev <igor@sysoev.ru>
parents:
1048
diff
changeset
|
84 rc = ngx_http_discard_request_body(r); |
753 | 85 |
1374 | 86 if (rc != NGX_OK) { |
753 | 87 return rc; |
88 } | |
89 | |
1454 | 90 last = ngx_http_map_uri_to_path(r, &path, &root, 0); |
91 if (last == NULL) { | |
753 | 92 return NGX_HTTP_INTERNAL_SERVER_ERROR; |
93 } | |
94 | |
95 log = r->connection->log; | |
96 | |
1454 | 97 path.len = last - path.data; |
753 | 98 |
1454 | 99 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, log, 0, |
100 "http flv filename: \"%V\"", &path); | |
101 | |
102 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); | |
753 | 103 |
2068
75a8d34459c5
ngx_memzero() ngx_open_file_info_t
Igor Sysoev <igor@sysoev.ru>
parents:
2063
diff
changeset
|
104 ngx_memzero(&of, sizeof(ngx_open_file_info_t)); |
75a8d34459c5
ngx_memzero() ngx_open_file_info_t
Igor Sysoev <igor@sysoev.ru>
parents:
2063
diff
changeset
|
105 |
3178 | 106 of.read_ahead = clcf->read_ahead; |
2129 | 107 of.directio = clcf->directio; |
1767
c42431762903
open_file_cache_retest > open_file_cache_valid
Igor Sysoev <igor@sysoev.ru>
parents:
1696
diff
changeset
|
108 of.valid = clcf->open_file_cache_valid; |
1772 | 109 of.min_uses = clcf->open_file_cache_min_uses; |
1454 | 110 of.errors = clcf->open_file_cache_errors; |
1457 | 111 of.events = clcf->open_file_cache_events; |
4494
13e09cf11d4e
Disable symlinks: initialization of the "disable_symlinks" field in
Valentin Bartenev <vbart@nginx.com>
parents:
4478
diff
changeset
|
112 |
13e09cf11d4e
Disable symlinks: initialization of the "disable_symlinks" field in
Valentin Bartenev <vbart@nginx.com>
parents:
4478
diff
changeset
|
113 if (ngx_http_set_disable_symlinks(r, clcf, &path, &of) != NGX_OK) { |
13e09cf11d4e
Disable symlinks: initialization of the "disable_symlinks" field in
Valentin Bartenev <vbart@nginx.com>
parents:
4478
diff
changeset
|
114 return NGX_HTTP_INTERNAL_SERVER_ERROR; |
13e09cf11d4e
Disable symlinks: initialization of the "disable_symlinks" field in
Valentin Bartenev <vbart@nginx.com>
parents:
4478
diff
changeset
|
115 } |
1560
25ee6eee7573
style fix: remove trailing spaces
Igor Sysoev <igor@sysoev.ru>
parents:
1553
diff
changeset
|
116 |
1799 | 117 if (ngx_open_cached_file(clcf->open_file_cache, &path, &of, r->pool) |
118 != NGX_OK) | |
119 { | |
1454 | 120 switch (of.err) { |
121 | |
122 case 0: | |
123 return NGX_HTTP_INTERNAL_SERVER_ERROR; | |
124 | |
125 case NGX_ENOENT: | |
126 case NGX_ENOTDIR: | |
127 case NGX_ENAMETOOLONG: | |
128 | |
753 | 129 level = NGX_LOG_ERR; |
130 rc = NGX_HTTP_NOT_FOUND; | |
1454 | 131 break; |
753 | 132 |
1454 | 133 case NGX_EACCES: |
4478
08713bac87fc
Support for disable_symlinks in various modules.
Andrey Belov <defan@nginx.com>
parents:
4412
diff
changeset
|
134 #if (NGX_HAVE_OPENAT) |
08713bac87fc
Support for disable_symlinks in various modules.
Andrey Belov <defan@nginx.com>
parents:
4412
diff
changeset
|
135 case NGX_EMLINK: |
08713bac87fc
Support for disable_symlinks in various modules.
Andrey Belov <defan@nginx.com>
parents:
4412
diff
changeset
|
136 case NGX_ELOOP: |
08713bac87fc
Support for disable_symlinks in various modules.
Andrey Belov <defan@nginx.com>
parents:
4412
diff
changeset
|
137 #endif |
1454 | 138 |
753 | 139 level = NGX_LOG_ERR; |
140 rc = NGX_HTTP_FORBIDDEN; | |
1454 | 141 break; |
753 | 142 |
1454 | 143 default: |
144 | |
753 | 145 level = NGX_LOG_CRIT; |
146 rc = NGX_HTTP_INTERNAL_SERVER_ERROR; | |
1454 | 147 break; |
753 | 148 } |
149 | |
150 if (rc != NGX_HTTP_NOT_FOUND || clcf->log_not_found) { | |
1454 | 151 ngx_log_error(level, log, of.err, |
2756
09cab3f8d92e
*) of.test_only to not open file if only stat() is enough
Igor Sysoev <igor@sysoev.ru>
parents:
2721
diff
changeset
|
152 "%s \"%s\" failed", of.failed, path.data); |
753 | 153 } |
154 | |
155 return rc; | |
156 } | |
157 | |
1454 | 158 if (!of.is_file) { |
753 | 159 |
1696 | 160 if (ngx_close_file(of.fd) == NGX_FILE_ERROR) { |
753 | 161 ngx_log_error(NGX_LOG_ALERT, log, ngx_errno, |
162 ngx_close_file_n " \"%s\" failed", path.data); | |
163 } | |
164 | |
165 return NGX_DECLINED; | |
166 } | |
167 | |
2444
aee735f41627
set r->root_tested for non-error_page response only
Igor Sysoev <igor@sysoev.ru>
parents:
2415
diff
changeset
|
168 r->root_tested = !r->error_page; |
2087
c8039b26a949
always test root existence for access_log with variables
Igor Sysoev <igor@sysoev.ru>
parents:
2086
diff
changeset
|
169 |
753 | 170 start = 0; |
1454 | 171 len = of.size; |
764
761a94247118
do not send flv header for full file
Igor Sysoev <igor@sysoev.ru>
parents:
754
diff
changeset
|
172 i = 1; |
753 | 173 |
174 if (r->args.len) { | |
175 | |
2415 | 176 if (ngx_http_arg(r, (u_char *) "start", 5, &value) == NGX_OK) { |
2086
22d36702c654
allow several values in query string
Igor Sysoev <igor@sysoev.ru>
parents:
2068
diff
changeset
|
177 |
2415 | 178 start = ngx_atoof(value.data, value.len); |
753 | 179 |
180 if (start == NGX_ERROR || start >= len) { | |
181 start = 0; | |
182 } | |
183 | |
764
761a94247118
do not send flv header for full file
Igor Sysoev <igor@sysoev.ru>
parents:
754
diff
changeset
|
184 if (start) { |
761a94247118
do not send flv header for full file
Igor Sysoev <igor@sysoev.ru>
parents:
754
diff
changeset
|
185 len = sizeof(ngx_flv_header) - 1 + len - start; |
761a94247118
do not send flv header for full file
Igor Sysoev <igor@sysoev.ru>
parents:
754
diff
changeset
|
186 i = 0; |
761a94247118
do not send flv header for full file
Igor Sysoev <igor@sysoev.ru>
parents:
754
diff
changeset
|
187 } |
753 | 188 } |
189 } | |
190 | |
191 log->action = "sending flv to client"; | |
192 | |
193 r->headers_out.status = NGX_HTTP_OK; | |
764
761a94247118
do not send flv header for full file
Igor Sysoev <igor@sysoev.ru>
parents:
754
diff
changeset
|
194 r->headers_out.content_length_n = len; |
1454 | 195 r->headers_out.last_modified_time = of.mtime; |
753 | 196 |
4748
192f54280a7a
Entity tags: set for static respones.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4611
diff
changeset
|
197 if (ngx_http_set_etag(r) != NGX_OK) { |
192f54280a7a
Entity tags: set for static respones.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4611
diff
changeset
|
198 return NGX_HTTP_INTERNAL_SERVER_ERROR; |
192f54280a7a
Entity tags: set for static respones.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4611
diff
changeset
|
199 } |
192f54280a7a
Entity tags: set for static respones.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4611
diff
changeset
|
200 |
753 | 201 if (ngx_http_set_content_type(r) != NGX_OK) { |
754
4ac89c5aa10d
style fix: remove trailing spaces
Igor Sysoev <igor@sysoev.ru>
parents:
753
diff
changeset
|
202 return NGX_HTTP_INTERNAL_SERVER_ERROR; |
753 | 203 } |
204 | |
764
761a94247118
do not send flv header for full file
Igor Sysoev <igor@sysoev.ru>
parents:
754
diff
changeset
|
205 if (i == 0) { |
6973
99934aade555
Use ngx_calloc_buf() where appropriate.
Ruslan Ermilov <ru@nginx.com>
parents:
4748
diff
changeset
|
206 b = ngx_calloc_buf(r->pool); |
764
761a94247118
do not send flv header for full file
Igor Sysoev <igor@sysoev.ru>
parents:
754
diff
changeset
|
207 if (b == NULL) { |
761a94247118
do not send flv header for full file
Igor Sysoev <igor@sysoev.ru>
parents:
754
diff
changeset
|
208 return NGX_HTTP_INTERNAL_SERVER_ERROR; |
761a94247118
do not send flv header for full file
Igor Sysoev <igor@sysoev.ru>
parents:
754
diff
changeset
|
209 } |
753 | 210 |
764
761a94247118
do not send flv header for full file
Igor Sysoev <igor@sysoev.ru>
parents:
754
diff
changeset
|
211 b->pos = ngx_flv_header; |
761a94247118
do not send flv header for full file
Igor Sysoev <igor@sysoev.ru>
parents:
754
diff
changeset
|
212 b->last = ngx_flv_header + sizeof(ngx_flv_header) - 1; |
761a94247118
do not send flv header for full file
Igor Sysoev <igor@sysoev.ru>
parents:
754
diff
changeset
|
213 b->memory = 1; |
753 | 214 |
764
761a94247118
do not send flv header for full file
Igor Sysoev <igor@sysoev.ru>
parents:
754
diff
changeset
|
215 out[0].buf = b; |
761a94247118
do not send flv header for full file
Igor Sysoev <igor@sysoev.ru>
parents:
754
diff
changeset
|
216 out[0].next = &out[1]; |
761a94247118
do not send flv header for full file
Igor Sysoev <igor@sysoev.ru>
parents:
754
diff
changeset
|
217 } |
753 | 218 |
781
836f099aa5cb
allow ranges for full flv files
Igor Sysoev <igor@sysoev.ru>
parents:
774
diff
changeset
|
219 |
6973
99934aade555
Use ngx_calloc_buf() where appropriate.
Ruslan Ermilov <ru@nginx.com>
parents:
4748
diff
changeset
|
220 b = ngx_calloc_buf(r->pool); |
753 | 221 if (b == NULL) { |
222 return NGX_HTTP_INTERNAL_SERVER_ERROR; | |
223 } | |
224 | |
225 b->file = ngx_pcalloc(r->pool, sizeof(ngx_file_t)); | |
226 if (b->file == NULL) { | |
227 return NGX_HTTP_INTERNAL_SERVER_ERROR; | |
228 } | |
229 | |
2122
d090fa684433
allow range for partial flv response
Igor Sysoev <igor@sysoev.ru>
parents:
2087
diff
changeset
|
230 r->allow_ranges = 1; |
d090fa684433
allow range for partial flv response
Igor Sysoev <igor@sysoev.ru>
parents:
2087
diff
changeset
|
231 |
753 | 232 rc = ngx_http_send_header(r); |
233 | |
234 if (rc == NGX_ERROR || rc > NGX_OK || r->header_only) { | |
235 return rc; | |
236 } | |
237 | |
238 b->file_pos = start; | |
1454 | 239 b->file_last = of.size; |
753 | 240 |
241 b->in_file = b->file_last ? 1: 0; | |
4611
2b6cb7528409
Allows particular modules to handle subrequests properly.
Andrey Belov <defan@nginx.com>
parents:
4494
diff
changeset
|
242 b->last_buf = (r == r->main) ? 1 : 0; |
753 | 243 b->last_in_chain = 1; |
244 | |
1696 | 245 b->file->fd = of.fd; |
753 | 246 b->file->name = path; |
247 b->file->log = log; | |
2231
8564129d49b6
*) handle unaligned file part for directio
Igor Sysoev <igor@sysoev.ru>
parents:
2129
diff
changeset
|
248 b->file->directio = of.is_directio; |
753 | 249 |
250 out[1].buf = b; | |
251 out[1].next = NULL; | |
252 | |
764
761a94247118
do not send flv header for full file
Igor Sysoev <igor@sysoev.ru>
parents:
754
diff
changeset
|
253 return ngx_http_output_filter(r, &out[i]); |
753 | 254 } |
255 | |
256 | |
257 static char * | |
258 ngx_http_flv(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) | |
259 { | |
260 ngx_http_core_loc_conf_t *clcf; | |
261 | |
262 clcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module); | |
263 clcf->handler = ngx_http_flv_handler; | |
264 | |
265 return NGX_CONF_OK; | |
266 } |