Mercurial > hg > nginx
comparison src/http/ngx_http_spdy_module.c @ 5121:c0f7b94e88ba
Preliminary experimental support for SPDY draft 2.
author | Valentin Bartenev <vbart@nginx.com> |
---|---|
date | Wed, 20 Mar 2013 10:36:57 +0000 |
parents | |
children | e5fb14e85040 |
comparison
equal
deleted
inserted
replaced
5120:7956af6b6a02 | 5121:c0f7b94e88ba |
---|---|
1 | |
2 /* | |
3 * Copyright (C) Nginx, Inc. | |
4 * Copyright (C) Valentin V. Bartenev | |
5 */ | |
6 | |
7 | |
8 #include <ngx_config.h> | |
9 #include <ngx_core.h> | |
10 #include <ngx_http.h> | |
11 #include <ngx_http_spdy_module.h> | |
12 | |
13 | |
14 static ngx_int_t ngx_http_spdy_add_variables(ngx_conf_t *cf); | |
15 | |
16 static ngx_int_t ngx_http_spdy_variable(ngx_http_request_t *r, | |
17 ngx_http_variable_value_t *v, uintptr_t data); | |
18 static ngx_int_t ngx_http_spdy_request_priority_variable(ngx_http_request_t *r, | |
19 ngx_http_variable_value_t *v, uintptr_t data); | |
20 | |
21 static ngx_int_t ngx_http_spdy_module_init(ngx_cycle_t *cycle); | |
22 | |
23 static void *ngx_http_spdy_create_main_conf(ngx_conf_t *cf); | |
24 static char *ngx_http_spdy_init_main_conf(ngx_conf_t *cf, void *conf); | |
25 | |
26 static void *ngx_http_spdy_create_srv_conf(ngx_conf_t *cf); | |
27 static char *ngx_http_spdy_merge_srv_conf(ngx_conf_t *cf, void *parent, | |
28 void *child); | |
29 | |
30 static char *ngx_http_spdy_recv_buffer_size(ngx_conf_t *cf, void *post, | |
31 void *data); | |
32 static char *ngx_http_spdy_pool_size(ngx_conf_t *cf, void *post, void *data); | |
33 static char *ngx_http_spdy_streams_index_mask(ngx_conf_t *cf, void *post, | |
34 void *data); | |
35 | |
36 | |
37 static ngx_conf_num_bounds_t ngx_http_spdy_headers_comp_bounds = { | |
38 ngx_conf_check_num_bounds, 0, 9 | |
39 }; | |
40 | |
41 static ngx_conf_post_t ngx_http_spdy_recv_buffer_size_post = | |
42 { ngx_http_spdy_recv_buffer_size }; | |
43 static ngx_conf_post_t ngx_http_spdy_pool_size_post = | |
44 { ngx_http_spdy_pool_size }; | |
45 static ngx_conf_post_t ngx_http_spdy_streams_index_mask_post = | |
46 { ngx_http_spdy_streams_index_mask }; | |
47 | |
48 | |
49 static ngx_command_t ngx_http_spdy_commands[] = { | |
50 | |
51 { ngx_string("spdy_recv_buffer_size"), | |
52 NGX_HTTP_MAIN_CONF|NGX_CONF_TAKE1, | |
53 ngx_conf_set_size_slot, | |
54 NGX_HTTP_MAIN_CONF_OFFSET, | |
55 offsetof(ngx_http_spdy_main_conf_t, recv_buffer_size), | |
56 &ngx_http_spdy_recv_buffer_size_post }, | |
57 | |
58 { ngx_string("spdy_pool_size"), | |
59 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1, | |
60 ngx_conf_set_size_slot, | |
61 NGX_HTTP_SRV_CONF_OFFSET, | |
62 offsetof(ngx_http_spdy_srv_conf_t, pool_size), | |
63 &ngx_http_spdy_pool_size_post }, | |
64 | |
65 { ngx_string("spdy_max_concurrent_streams"), | |
66 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1, | |
67 ngx_conf_set_num_slot, | |
68 NGX_HTTP_SRV_CONF_OFFSET, | |
69 offsetof(ngx_http_spdy_srv_conf_t, concurrent_streams), | |
70 NULL }, | |
71 | |
72 { ngx_string("spdy_streams_index_size"), | |
73 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1, | |
74 ngx_conf_set_num_slot, | |
75 NGX_HTTP_SRV_CONF_OFFSET, | |
76 offsetof(ngx_http_spdy_srv_conf_t, streams_index_mask), | |
77 &ngx_http_spdy_streams_index_mask_post }, | |
78 | |
79 { ngx_string("spdy_recv_timeout"), | |
80 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1, | |
81 ngx_conf_set_msec_slot, | |
82 NGX_HTTP_SRV_CONF_OFFSET, | |
83 offsetof(ngx_http_spdy_srv_conf_t, recv_timeout), | |
84 NULL }, | |
85 | |
86 { ngx_string("spdy_keepalive_timeout"), | |
87 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1, | |
88 ngx_conf_set_msec_slot, | |
89 NGX_HTTP_SRV_CONF_OFFSET, | |
90 offsetof(ngx_http_spdy_srv_conf_t, keepalive_timeout), | |
91 NULL }, | |
92 | |
93 { ngx_string("spdy_headers_comp"), | |
94 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1, | |
95 ngx_conf_set_num_slot, | |
96 NGX_HTTP_SRV_CONF_OFFSET, | |
97 offsetof(ngx_http_spdy_srv_conf_t, headers_comp), | |
98 &ngx_http_spdy_headers_comp_bounds }, | |
99 | |
100 ngx_null_command | |
101 }; | |
102 | |
103 | |
104 static ngx_http_module_t ngx_http_spdy_module_ctx = { | |
105 ngx_http_spdy_add_variables, /* preconfiguration */ | |
106 NULL, /* postconfiguration */ | |
107 | |
108 ngx_http_spdy_create_main_conf, /* create main configuration */ | |
109 ngx_http_spdy_init_main_conf, /* init main configuration */ | |
110 | |
111 ngx_http_spdy_create_srv_conf, /* create server configuration */ | |
112 ngx_http_spdy_merge_srv_conf, /* merge server configuration */ | |
113 | |
114 NULL, /* create location configuration */ | |
115 NULL /* merge location configuration */ | |
116 }; | |
117 | |
118 | |
119 ngx_module_t ngx_http_spdy_module = { | |
120 NGX_MODULE_V1, | |
121 &ngx_http_spdy_module_ctx, /* module context */ | |
122 ngx_http_spdy_commands, /* module directives */ | |
123 NGX_HTTP_MODULE, /* module type */ | |
124 NULL, /* init master */ | |
125 ngx_http_spdy_module_init, /* init module */ | |
126 NULL, /* init process */ | |
127 NULL, /* init thread */ | |
128 NULL, /* exit thread */ | |
129 NULL, /* exit process */ | |
130 NULL, /* exit master */ | |
131 NGX_MODULE_V1_PADDING | |
132 }; | |
133 | |
134 | |
135 static ngx_http_variable_t ngx_http_spdy_vars[] = { | |
136 | |
137 { ngx_string("spdy"), NULL, | |
138 ngx_http_spdy_variable, 0, 0, 0 }, | |
139 | |
140 { ngx_string("spdy_request_priority"), NULL, | |
141 ngx_http_spdy_request_priority_variable, 0, 0, 0 }, | |
142 | |
143 { ngx_null_string, NULL, NULL, 0, 0, 0 } | |
144 }; | |
145 | |
146 | |
147 static ngx_int_t | |
148 ngx_http_spdy_add_variables(ngx_conf_t *cf) | |
149 { | |
150 ngx_http_variable_t *var, *v; | |
151 | |
152 for (v = ngx_http_spdy_vars; v->name.len; v++) { | |
153 var = ngx_http_add_variable(cf, &v->name, v->flags); | |
154 if (var == NULL) { | |
155 return NGX_ERROR; | |
156 } | |
157 | |
158 var->get_handler = v->get_handler; | |
159 var->data = v->data; | |
160 } | |
161 | |
162 return NGX_OK; | |
163 } | |
164 | |
165 | |
166 static ngx_int_t | |
167 ngx_http_spdy_variable(ngx_http_request_t *r, | |
168 ngx_http_variable_value_t *v, uintptr_t data) | |
169 { | |
170 if (r->spdy_stream) { | |
171 v->len = 1; | |
172 v->valid = 1; | |
173 v->no_cacheable = 0; | |
174 v->not_found = 0; | |
175 v->data = (u_char *) "2"; | |
176 | |
177 return NGX_OK; | |
178 } | |
179 | |
180 *v = ngx_http_variable_null_value; | |
181 | |
182 return NGX_OK; | |
183 } | |
184 | |
185 | |
186 static ngx_int_t | |
187 ngx_http_spdy_request_priority_variable(ngx_http_request_t *r, | |
188 ngx_http_variable_value_t *v, uintptr_t data) | |
189 { | |
190 if (r->spdy_stream) { | |
191 v->len = 1; | |
192 v->valid = 1; | |
193 v->no_cacheable = 0; | |
194 v->not_found = 0; | |
195 | |
196 v->data = ngx_pnalloc(r->pool, 1); | |
197 if (v->data == NULL) { | |
198 return NGX_ERROR; | |
199 } | |
200 | |
201 v->data[0] = '0' + (u_char) r->spdy_stream->priority; | |
202 | |
203 return NGX_OK; | |
204 } | |
205 | |
206 *v = ngx_http_variable_null_value; | |
207 | |
208 return NGX_OK; | |
209 } | |
210 | |
211 | |
212 static ngx_int_t | |
213 ngx_http_spdy_module_init(ngx_cycle_t *cycle) | |
214 { | |
215 ngx_http_spdy_request_headers_init(); | |
216 | |
217 return NGX_OK; | |
218 } | |
219 | |
220 | |
221 static void * | |
222 ngx_http_spdy_create_main_conf(ngx_conf_t *cf) | |
223 { | |
224 ngx_http_spdy_main_conf_t *smcf; | |
225 | |
226 smcf = ngx_pcalloc(cf->pool, sizeof(ngx_http_spdy_main_conf_t)); | |
227 if (smcf == NULL) { | |
228 return NULL; | |
229 } | |
230 | |
231 smcf->recv_buffer_size = NGX_CONF_UNSET_SIZE; | |
232 | |
233 return smcf; | |
234 } | |
235 | |
236 | |
237 static char * | |
238 ngx_http_spdy_init_main_conf(ngx_conf_t *cf, void *conf) | |
239 { | |
240 ngx_http_spdy_main_conf_t *smcf = conf; | |
241 | |
242 if (smcf->recv_buffer_size == NGX_CONF_UNSET_SIZE) { | |
243 smcf->recv_buffer_size = 256 * 1024; | |
244 } | |
245 | |
246 return NGX_CONF_OK; | |
247 } | |
248 | |
249 | |
250 static void * | |
251 ngx_http_spdy_create_srv_conf(ngx_conf_t *cf) | |
252 { | |
253 ngx_http_spdy_srv_conf_t *sscf; | |
254 | |
255 sscf = ngx_pcalloc(cf->pool, sizeof(ngx_http_spdy_srv_conf_t)); | |
256 if (sscf == NULL) { | |
257 return NULL; | |
258 } | |
259 | |
260 sscf->pool_size = NGX_CONF_UNSET_SIZE; | |
261 | |
262 sscf->concurrent_streams = NGX_CONF_UNSET_UINT; | |
263 sscf->streams_index_mask = NGX_CONF_UNSET_UINT; | |
264 | |
265 sscf->recv_timeout = NGX_CONF_UNSET_MSEC; | |
266 sscf->keepalive_timeout = NGX_CONF_UNSET_MSEC; | |
267 | |
268 sscf->headers_comp = NGX_CONF_UNSET; | |
269 | |
270 return sscf; | |
271 } | |
272 | |
273 | |
274 static char * | |
275 ngx_http_spdy_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child) | |
276 { | |
277 ngx_http_spdy_srv_conf_t *prev = parent; | |
278 ngx_http_spdy_srv_conf_t *conf = child; | |
279 | |
280 ngx_conf_merge_size_value(conf->pool_size, prev->pool_size, 4096); | |
281 | |
282 ngx_conf_merge_uint_value(conf->concurrent_streams, | |
283 prev->concurrent_streams, 100); | |
284 | |
285 ngx_conf_merge_uint_value(conf->streams_index_mask, | |
286 prev->streams_index_mask, 32 - 1); | |
287 | |
288 ngx_conf_merge_msec_value(conf->recv_timeout, | |
289 prev->recv_timeout, 30000); | |
290 ngx_conf_merge_msec_value(conf->keepalive_timeout, | |
291 prev->keepalive_timeout, 180000); | |
292 | |
293 ngx_conf_merge_value(conf->headers_comp, prev->headers_comp, 0); | |
294 | |
295 return NGX_CONF_OK; | |
296 } | |
297 | |
298 | |
299 static char * | |
300 ngx_http_spdy_recv_buffer_size(ngx_conf_t *cf, void *post, void *data) | |
301 { | |
302 size_t *sp = data; | |
303 | |
304 if (*sp <= 2 * NGX_SPDY_STATE_BUFFER_SIZE) { | |
305 return "value is too small"; | |
306 } | |
307 | |
308 return NGX_CONF_OK; | |
309 } | |
310 | |
311 | |
312 static char * | |
313 ngx_http_spdy_pool_size(ngx_conf_t *cf, void *post, void *data) | |
314 { | |
315 size_t *sp = data; | |
316 | |
317 if (*sp < NGX_MIN_POOL_SIZE) { | |
318 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, | |
319 "the pool size must be no less than %uz", | |
320 NGX_MIN_POOL_SIZE); | |
321 return NGX_CONF_ERROR; | |
322 } | |
323 | |
324 if (*sp % NGX_POOL_ALIGNMENT) { | |
325 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, | |
326 "the pool size must be a multiple of %uz", | |
327 NGX_POOL_ALIGNMENT); | |
328 return NGX_CONF_ERROR; | |
329 } | |
330 | |
331 return NGX_CONF_OK; | |
332 } | |
333 | |
334 | |
335 static char * | |
336 ngx_http_spdy_streams_index_mask(ngx_conf_t *cf, void *post, void *data) | |
337 { | |
338 ngx_uint_t *np = data; | |
339 | |
340 ngx_uint_t mask; | |
341 | |
342 mask = *np - 1; | |
343 | |
344 if (*np == 0 || (*np & mask)) { | |
345 return "must be a power of two"; | |
346 } | |
347 | |
348 *np = mask; | |
349 | |
350 return NGX_CONF_OK; | |
351 } |