comparison ngx_http_bytes_filter_module.c @ 0:8aec31ab4d52

Bytes filter module skeleton, currently does nothing. Bytes module designed to return only specific range of file as requested in arguments. It's intended to replace flv module as more generic alternative.
author Maxim Dounin <mdounin@mdounin.ru>
date Thu, 26 Jun 2008 04:49:22 +0400
parents
children 6b995d5251ec
comparison
equal deleted inserted replaced
-1:000000000000 0:8aec31ab4d52
1
2 /*
3 * Copyright (C) Maxim Dounin
4 */
5
6 #include <ngx_config.h>
7 #include <ngx_core.h>
8 #include <ngx_http.h>
9
10
11 typedef struct {
12 ngx_flag_t enable;
13 } ngx_http_bytes_conf_t;
14
15
16 typedef struct {
17 off_t start;
18 off_t end;
19 } ngx_http_bytes_t;
20
21
22 typedef struct {
23 off_t offset;
24 ngx_array_t ranges;
25 } ngx_http_bytes_ctx_t;
26
27
28 static void *ngx_http_bytes_create_conf(ngx_conf_t *cf);
29 static char *ngx_http_bytes_merge_conf(ngx_conf_t *cf, void *parent,
30 void *child);
31 static ngx_int_t ngx_http_bytes_init(ngx_conf_t *cf);
32
33
34 static ngx_command_t ngx_http_bytes_commands[] = {
35
36 { ngx_string("bytes"),
37 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
38 ngx_conf_set_flag_slot,
39 NGX_HTTP_LOC_CONF_OFFSET,
40 offsetof(ngx_http_bytes_conf_t, enable),
41 NULL },
42
43 ngx_null_command
44 };
45
46
47 static ngx_http_module_t ngx_http_bytes_module_ctx = {
48 NULL, /* preconfiguration */
49 ngx_http_bytes_init, /* postconfiguration */
50
51 NULL, /* create main configuration */
52 NULL, /* init main configuration */
53
54 NULL, /* create server configuration */
55 NULL, /* merge server configuration */
56
57 ngx_http_bytes_create_conf, /* create location configuration */
58 ngx_http_bytes_merge_conf /* merge location configuration */
59 };
60
61
62 ngx_module_t ngx_http_bytes_filter_module = {
63 NGX_MODULE_V1,
64 &ngx_http_bytes_module_ctx, /* module context */
65 ngx_http_bytes_commands, /* module directives */
66 NGX_HTTP_MODULE, /* module type */
67 NULL, /* init master */
68 NULL, /* init module */
69 NULL, /* init process */
70 NULL, /* init thread */
71 NULL, /* exit thread */
72 NULL, /* exit process */
73 NULL, /* exit master */
74 NGX_MODULE_V1_PADDING
75 };
76
77
78 static ngx_http_output_header_filter_pt ngx_http_next_header_filter;
79 static ngx_http_output_body_filter_pt ngx_http_next_body_filter;
80
81
82 static ngx_int_t
83 ngx_http_bytes_header_filter(ngx_http_request_t *r)
84 {
85 u_char *p;
86 ngx_http_bytes_conf_t *conf;
87 ngx_http_bytes_ctx_t *ctx;
88
89 conf = ngx_http_get_module_loc_conf(r, ngx_http_bytes_filter_module);
90
91 if (!conf->enable || r->args.len == 0) {
92 return ngx_http_next_header_filter(r);
93 }
94
95 p = (u_char *) ngx_strnstr(r->args.data, "bytes=", r->args.len);
96
97 if (p == NULL) {
98 return ngx_http_next_header_filter(r);
99 }
100
101 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
102 "bytes header filter: r %p", r);
103
104 p += sizeof("bytes=") - 1;
105
106 /* create context */
107
108 ctx = ngx_pcalloc(r->pool, sizeof(ngx_http_bytes_ctx_t));
109 if (ctx == NULL) {
110 return NGX_ERROR;
111 }
112
113 if (ngx_array_init(&ctx->ranges, r->pool, 1, sizeof(ngx_http_bytes_t))
114 == NGX_ERROR)
115 {
116 return NGX_ERROR;
117 }
118
119 /*
120 * bytes= contain ranges compatible with RFC 2616, "14.35.1 Byte Ranges",
121 * but no whitespaces permitted
122 */
123
124 #if 0
125 for ( ;; ) {
126 start = 0;
127 end = 0;
128 suffix = 0;
129
130 if (*p != '-') {
131 if (*p < '0' || *p > '9') {
132 break;
133 }
134
135 while (*p >= '0' && *p <= '9') {
136 start = start * 10 + *p++ - '0';
137 }
138
139 if (*p != '-') {
140 break;
141 }
142
143 if (*p == ',' || *p == '\0') {
144 /* no last-byte-pos, assume end of file */
145 end = len - 1;
146 }
147
148 } else {
149 suffix = 1;
150 p++;
151 }
152 }
153 #endif
154
155 /* ... */
156
157 ngx_http_set_ctx(r, ctx, ngx_http_bytes_filter_module);
158
159 return ngx_http_next_header_filter(r);
160 }
161
162
163 static ngx_int_t
164 ngx_http_bytes_body_filter(ngx_http_request_t *r, ngx_chain_t *in)
165 {
166 ngx_http_bytes_ctx_t *ctx;
167
168 ctx = ngx_http_get_module_ctx(r, ngx_http_bytes_filter_module);
169
170 if (ctx == NULL) {
171 return ngx_http_next_body_filter(r, in);
172 }
173
174 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
175 "bytes body filter: r %p, in %p", r, in);
176
177 return ngx_http_next_body_filter(r, in);
178 }
179
180
181 static void *
182 ngx_http_bytes_create_conf(ngx_conf_t *cf)
183 {
184 ngx_http_bytes_conf_t *conf;
185
186 conf = ngx_pcalloc(cf->pool, sizeof(ngx_http_bytes_conf_t));
187 if (conf == NULL) {
188 return NGX_CONF_ERROR;
189 }
190
191 conf->enable = NGX_CONF_UNSET;
192
193 return conf;
194 }
195
196
197 static char *
198 ngx_http_bytes_merge_conf(ngx_conf_t *cf, void *parent, void *child)
199 {
200 ngx_http_bytes_conf_t *prev = parent;
201 ngx_http_bytes_conf_t *conf = child;
202
203 ngx_conf_merge_value(conf->enable, prev->enable, 0);
204
205 return NGX_CONF_OK;
206 }
207
208
209 static ngx_int_t
210 ngx_http_bytes_init(ngx_conf_t *cf)
211 {
212 ngx_http_next_header_filter = ngx_http_top_header_filter;
213 ngx_http_top_header_filter = ngx_http_bytes_header_filter;
214
215 ngx_http_next_body_filter = ngx_http_top_body_filter;
216 ngx_http_top_body_filter = ngx_http_bytes_body_filter;
217
218 return NGX_OK;
219 }