Mercurial > hg > nginx-quic
comparison src/stream/ngx_stream_return_module.c @ 6612:4c4ac9e335c4
Stream: return module.
author | Roman Arutyunyan <arut@nginx.com> |
---|---|
date | Wed, 18 May 2016 22:08:49 +0300 |
parents | |
children | 8ed51b02f655 |
comparison
equal
deleted
inserted
replaced
6611:85e7bcb37d6b | 6612:4c4ac9e335c4 |
---|---|
1 | |
2 /* | |
3 * Copyright (C) Roman Arutyunyan | |
4 * Copyright (C) Nginx, Inc. | |
5 */ | |
6 | |
7 | |
8 #include <ngx_config.h> | |
9 #include <ngx_core.h> | |
10 #include <ngx_stream.h> | |
11 | |
12 | |
13 typedef struct { | |
14 ngx_stream_complex_value_t text; | |
15 } ngx_stream_return_srv_conf_t; | |
16 | |
17 | |
18 typedef struct { | |
19 ngx_buf_t buf; | |
20 } ngx_stream_return_ctx_t; | |
21 | |
22 | |
23 static void ngx_stream_return_handler(ngx_stream_session_t *s); | |
24 static void ngx_stream_return_write_handler(ngx_event_t *ev); | |
25 | |
26 static void *ngx_stream_return_create_srv_conf(ngx_conf_t *cf); | |
27 static char *ngx_stream_return(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); | |
28 | |
29 | |
30 static ngx_command_t ngx_stream_return_commands[] = { | |
31 | |
32 { ngx_string("return"), | |
33 NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1, | |
34 ngx_stream_return, | |
35 NGX_STREAM_SRV_CONF_OFFSET, | |
36 0, | |
37 NULL }, | |
38 | |
39 ngx_null_command | |
40 }; | |
41 | |
42 | |
43 static ngx_stream_module_t ngx_stream_return_module_ctx = { | |
44 NULL, /* preconfiguration */ | |
45 NULL, /* postconfiguration */ | |
46 | |
47 NULL, /* create main configuration */ | |
48 NULL, /* init main configuration */ | |
49 | |
50 ngx_stream_return_create_srv_conf, /* create server configuration */ | |
51 NULL, /* merge server configuration */ | |
52 }; | |
53 | |
54 | |
55 ngx_module_t ngx_stream_return_module = { | |
56 NGX_MODULE_V1, | |
57 &ngx_stream_return_module_ctx, /* module context */ | |
58 ngx_stream_return_commands, /* module directives */ | |
59 NGX_STREAM_MODULE, /* module type */ | |
60 NULL, /* init master */ | |
61 NULL, /* init module */ | |
62 NULL, /* init process */ | |
63 NULL, /* init thread */ | |
64 NULL, /* exit thread */ | |
65 NULL, /* exit process */ | |
66 NULL, /* exit master */ | |
67 NGX_MODULE_V1_PADDING | |
68 }; | |
69 | |
70 | |
71 static void | |
72 ngx_stream_return_handler(ngx_stream_session_t *s) | |
73 { | |
74 ngx_str_t text; | |
75 ngx_connection_t *c; | |
76 ngx_stream_return_ctx_t *ctx; | |
77 ngx_stream_return_srv_conf_t *rscf; | |
78 | |
79 c = s->connection; | |
80 | |
81 c->log->action = "returning text"; | |
82 | |
83 rscf = ngx_stream_get_module_srv_conf(s, ngx_stream_return_module); | |
84 | |
85 if (ngx_stream_complex_value(s, &rscf->text, &text) != NGX_OK) { | |
86 ngx_stream_close_connection(c); | |
87 return; | |
88 } | |
89 | |
90 ngx_log_debug1(NGX_LOG_DEBUG_STREAM, c->log, 0, | |
91 "stream return text: \"%V\"", &text); | |
92 | |
93 if (text.len == 0) { | |
94 ngx_stream_close_connection(c); | |
95 return; | |
96 } | |
97 | |
98 ctx = ngx_pcalloc(c->pool, sizeof(ngx_stream_return_ctx_t)); | |
99 if (ctx == NULL) { | |
100 ngx_stream_close_connection(c); | |
101 return; | |
102 } | |
103 | |
104 ngx_stream_set_ctx(s, ctx, ngx_stream_return_module); | |
105 | |
106 ctx->buf.pos = text.data; | |
107 ctx->buf.last = text.data + text.len; | |
108 | |
109 c->write->handler = ngx_stream_return_write_handler; | |
110 | |
111 ngx_stream_return_write_handler(c->write); | |
112 } | |
113 | |
114 | |
115 static void | |
116 ngx_stream_return_write_handler(ngx_event_t *ev) | |
117 { | |
118 ssize_t n; | |
119 ngx_buf_t *b; | |
120 ngx_connection_t *c; | |
121 ngx_stream_session_t *s; | |
122 ngx_stream_return_ctx_t *ctx; | |
123 | |
124 c = ev->data; | |
125 s = c->data; | |
126 | |
127 if (ev->timedout) { | |
128 ngx_connection_error(c, NGX_ETIMEDOUT, "connection timed out"); | |
129 ngx_stream_close_connection(c); | |
130 return; | |
131 } | |
132 | |
133 if (ev->ready) { | |
134 ctx = ngx_stream_get_module_ctx(s, ngx_stream_return_module); | |
135 | |
136 b = &ctx->buf; | |
137 | |
138 n = c->send(c, b->pos, b->last - b->pos); | |
139 if (n == NGX_ERROR) { | |
140 ngx_stream_close_connection(c); | |
141 return; | |
142 } | |
143 | |
144 if (n > 0) { | |
145 b->pos += n; | |
146 | |
147 if (b->pos == b->last) { | |
148 ngx_stream_close_connection(c); | |
149 return; | |
150 } | |
151 } | |
152 } | |
153 | |
154 if (ngx_handle_write_event(ev, 0) != NGX_OK) { | |
155 ngx_stream_close_connection(c); | |
156 return; | |
157 } | |
158 | |
159 ngx_add_timer(ev, 5000); | |
160 } | |
161 | |
162 | |
163 static void * | |
164 ngx_stream_return_create_srv_conf(ngx_conf_t *cf) | |
165 { | |
166 ngx_stream_return_srv_conf_t *conf; | |
167 | |
168 conf = ngx_pcalloc(cf->pool, sizeof(ngx_stream_return_srv_conf_t)); | |
169 if (conf == NULL) { | |
170 return NULL; | |
171 } | |
172 | |
173 return conf; | |
174 } | |
175 | |
176 | |
177 static char * | |
178 ngx_stream_return(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) | |
179 { | |
180 ngx_stream_return_srv_conf_t *rscf = conf; | |
181 | |
182 ngx_str_t *value; | |
183 ngx_stream_core_srv_conf_t *cscf; | |
184 ngx_stream_compile_complex_value_t ccv; | |
185 | |
186 if (rscf->text.value.data) { | |
187 return "is duplicate"; | |
188 } | |
189 | |
190 value = cf->args->elts; | |
191 | |
192 ngx_memzero(&ccv, sizeof(ngx_stream_compile_complex_value_t)); | |
193 | |
194 ccv.cf = cf; | |
195 ccv.value = &value[1]; | |
196 ccv.complex_value = &rscf->text; | |
197 | |
198 if (ngx_stream_compile_complex_value(&ccv) != NGX_OK) { | |
199 return NGX_CONF_ERROR; | |
200 } | |
201 | |
202 cscf = ngx_stream_conf_get_module_srv_conf(cf, ngx_stream_core_module); | |
203 | |
204 cscf->handler = ngx_stream_return_handler; | |
205 | |
206 return NGX_CONF_OK; | |
207 } |