Klaus Demo nginx / 2e6ba93
nginx-0.0.10-2004-09-09-19:40:48 import Igor Sysoev 17 years ago
16 changed file(s) with 503 addition(s) and 118 deletion(s). Raw diff Collapse all Expand all
298298 IMAP_MODULE=ngx_imap_module
299299 IMAP_SRCS="src/imap/ngx_imap.c \
300300 src/imap/ngx_imap_handler.c \
301 src/imap/ngx_imap_parse.c \
301302 src/imap/ngx_imap_proxy.c"
4848 #if (HAVE_DEFERRED_ACCEPT)
4949 unsigned deferred_accept:1;
5050 #endif
51
52 unsigned addr_ntop:1;
5153 } ngx_listening_t;
5254
5355
1010 } ngx_accept_log_ctx_t;
1111
1212
13 static void ngx_close_accepted_socket(ngx_socket_t s, ngx_log_t *log);
1314 static size_t ngx_accept_log_error(void *data, char *buf, size_t len);
1415
1516
137138 "closing the connection",
138139 ls->listening->addr_text.data, s, ecf->connections);
139140
140 if (ngx_close_socket(s) == -1) {
141 ngx_log_error(NGX_LOG_ALERT, log, ngx_socket_errno,
142 ngx_close_socket_n "failed");
143 }
144
141 ngx_close_accepted_socket(s, log);
145142 ngx_destroy_pool(pool);
146143 return;
147144 }
154151 ngx_log_error(NGX_LOG_ALERT, log, ngx_socket_errno,
155152 ngx_blocking_n " failed");
156153
157 if (ngx_close_socket(s) == -1) {
158 ngx_log_error(NGX_LOG_ALERT, log, ngx_socket_errno,
159 ngx_close_socket_n " failed");
160 }
161
154 ngx_close_accepted_socket(s, log);
162155 ngx_destroy_pool(pool);
163156 return;
164157 }
170163 ngx_log_error(NGX_LOG_ALERT, log, ngx_socket_errno,
171164 ngx_nonblocking_n " failed");
172165
173 if (ngx_close_socket(s) == -1) {
174 ngx_log_error(NGX_LOG_ALERT, log, ngx_socket_errno,
175 ngx_close_socket_n " failed");
176 }
177
166 ngx_close_accepted_socket(s, log);
178167 ngx_destroy_pool(pool);
179168 return;
180169 }
285274 ngx_log_debug2(NGX_LOG_DEBUG_EVENT, ev->log, 0,
286275 "accept: fd:%d c:%d", s, c->number);
287276
277 if (c->listening->addr_ntop) {
278 c->addr_text.data = ngx_palloc(c->pool,
279 c->listening->addr_text_max_len);
280 if (c->addr_text.data == NULL) {
281 ngx_close_accepted_socket(s, log);
282 ngx_destroy_pool(pool);
283 return;
284 }
285
286 c->addr_text.len = ngx_sock_ntop(c->listening->family, c->sockaddr,
287 c->addr_text.data,
288 c->listening->addr_text_max_len);
289 if (c->addr_text.len == 0) {
290 ngx_close_accepted_socket(s, log);
291 ngx_destroy_pool(pool);
292 return;
293 }
294 }
295
288296 #if (NGX_DEBUG)
289297 {
290298
306314
307315 if (ngx_add_conn && (ngx_event_flags & NGX_USE_EPOLL_EVENT) == 0) {
308316 if (ngx_add_conn(c) == NGX_ERROR) {
309 if (ngx_close_socket(s) == -1) {
310 ngx_log_error(NGX_LOG_ALERT, ev->log, ngx_socket_errno,
311 ngx_close_socket_n " failed");
312 }
313
317 ngx_close_accepted_socket(s, log);
314318 ngx_destroy_pool(pool);
315319 return;
316320 }
439443 }
440444
441445
446 static void ngx_close_accepted_socket(ngx_socket_t s, ngx_log_t *log)
447 {
448 if (ngx_close_socket(s) == -1) {
449 ngx_log_error(NGX_LOG_ALERT, log, ngx_socket_errno,
450 ngx_close_socket_n " failed");
451 }
452 }
453
454
442455 static size_t ngx_accept_log_error(void *data, char *buf, size_t len)
443456 {
444457 ngx_accept_log_ctx_t *ctx = data;
1212 typedef struct {
1313 in_addr_t addr;
1414 ngx_str_t host;
15 int port;
15 in_port_t port;
1616 ngx_str_t addr_port_text;
1717
18 int fails;
18 ngx_int_t fails;
1919 time_t accessed;
2020 } ngx_peer_t;
2121
2222
2323 typedef struct {
24 int current;
25 int number;
26 int max_fails;
27 int fail_timeout;
28 int last_cached;
24 ngx_int_t current;
25 ngx_int_t number;
26 ngx_int_t max_fails;
27 ngx_int_t fail_timeout;
28 ngx_int_t last_cached;
2929
3030 /* ngx_mutex_t *mutex; */
3131 ngx_connection_t **cached;
3636
3737 typedef struct {
3838 ngx_peers_t *peers;
39 int cur_peer;
40 int tries;
39 ngx_int_t cur_peer;
40 ngx_int_t tries;
4141
4242 ngx_connection_t *connection;
4343 #if (NGX_THREADS)
12261226 u->port_text.len = &url->data[i] - u->port_text.data;
12271227
12281228 if (u->port_text.len > 0) {
1229 u->port = ngx_atoi(u->port_text.data, u->port_text.len);
1229 u->port = (in_port_t) ngx_atoi(u->port_text.data,
1230 u->port_text.len);
12301231 if (u->port > 0) {
12311232
12321233 if (u->port == 80) {
12621263 u->port_text.len = &url->data[i] - u->port_text.data;
12631264
12641265 if (u->port_text.len > 0) {
1265 u->port = ngx_atoi(u->port_text.data, u->port_text.len);
1266 u->port = (in_port_t) ngx_atoi(u->port_text.data, u->port_text.len);
12661267 if (u->port > 0) {
12671268 u->port = htons(u->port);
12681269 return NULL;
5353
5454 static char *ngx_http_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
5555 {
56 char *rv;
5657 ngx_uint_t mi, m, s, l, p, a, n;
5758 ngx_uint_t port_found, addr_found, virtual_names;
58 char *rv;
59 struct sockaddr_in *addr_in;
6059 ngx_conf_t pcf;
6160 ngx_array_t in_ports;
6261 ngx_listening_t *ls;
513512 ls->nonblocking = 0;
514513 #endif
515514 #endif
515 ls->addr_ntop = 1;
516516
517517 ls->handler = ngx_http_init_connection;
518518
6464
6565 if (r->method_end - m == 3) {
6666
67 if (*m == 'G' && *(m + 1) == 'E' && *(m + 2) == 'T') {
67 if (m[0] == 'G' && m[1] == 'E' && m[2] == 'T') {
6868 r->method = NGX_HTTP_GET;
6969 }
7070
7171 } else if (r->method_end - m == 4) {
7272
73 if (*m == 'P' && *(m + 1) == 'O'
74 && *(m + 2) == 'T' && *(m + 3) == 'T')
73 if (m[0] == 'P' && m[1] == 'O'
74 && m[2] == 'T' && m[3] == 'T')
7575 {
7676 r->method = NGX_HTTP_POST;
7777
78 } else if (*m == 'H' && *(m + 1) == 'E'
79 && *(m + 2) == 'A' && *(m + 3) == 'D')
78 } else if (m[0] == 'H' && m[1] == 'E'
79 && m[2] == 'A' && m[3] == 'D')
8080 {
8181 r->method = NGX_HTTP_HEAD;
8282 }
9595 {
9696 ngx_event_t *rev;
9797 ngx_http_log_ctx_t *ctx;
98
99 c->addr_text.data = ngx_palloc(c->pool, c->listening->addr_text_max_len);
100 if (c->addr_text.data == NULL) {
101 ngx_http_close_connection(c);
102 return;
103 }
104
105 c->addr_text.len = ngx_sock_ntop(c->listening->family, c->sockaddr,
106 c->addr_text.data,
107 c->listening->addr_text_max_len);
108
109 if (c->addr_text.len == 0) {
110 ngx_http_close_connection(c);
111 return;
112 }
11398
11499 if (!(ctx = ngx_pcalloc(c->pool, sizeof(ngx_http_log_ctx_t)))) {
115100 ngx_http_close_connection(c);
310310 ngx_uint_t headers_n;
311311
312312 /* used to parse HTTP headers */
313 ngx_int_t state;
313 ngx_uint_t state;
314314 u_char *uri_start;
315315 u_char *uri_end;
316316 u_char *uri_ext;
4949 }
5050
5151 ls->backlog = -1;
52 ls->addr_ntop = 1;
5253 ls->handler = ngx_imap_init_connection;
5354 ls->pool_size = 16384;
5455 /* ls->post_accept_timeout = 0; */
33
44 #include <ngx_config.h>
55 #include <ngx_core.h>
6 #include <ngx_event.h>
7 #include <ngx_event_connect.h>
68
79
810 typedef struct {
9 ngx_connection_t *connection;
11 ngx_peer_connection_t upstream;
1012
11 ngx_buf_t *downstream_buffer;
12 ngx_buf_t *upstream_buffer;
13 ngx_buf_t *buffer;
1314 } ngx_imap_proxy_ctx_t;
1415
1516
1617 typedef struct {
17 uint32_t signature; /* "IMAP" */
18 uint32_t signature; /* "IMAP" */
1819
19 ngx_connection_t *connection;
20 ngx_imap_proxy_ctx_t *proxy;
20 ngx_connection_t *connection;
21 ngx_buf_t *buffer;
22
23 ngx_imap_proxy_ctx_t *proxy;
24
25 ngx_uint_t command;
26 ngx_array_t args;
27
28 /* used to parse IMAP/POP3 command */
29
30 ngx_uint_t state;
31 u_char *arg_start;
32 u_char *arg_end;
2133 } ngx_imap_session_t;
2234
2335
24 #define NGX_POP3_USER 1
25 #define NGX_POP3_PASS 2
26 #define NGX_POP3_APOP 3
27 #define NGX_POP3_STAT 4
28 #define NGX_POP3_LIST 5
29 #define NGX_POP3_RETR 6
30 #define NGX_POP3_DELE 7
31 #define NGX_POP3_NOOP 8
32 #define NGX_POP3_RSET 9
33 #define NGX_POP3_TOP 10
34 #define NGX_POP3_UIDL 11
35 #define NGX_POP3_QUIT 12
36 #define NGX_POP3_USER 1
37 #define NGX_POP3_PASS 2
38 #define NGX_POP3_APOP 3
39 #define NGX_POP3_STAT 4
40 #define NGX_POP3_LIST 5
41 #define NGX_POP3_RETR 6
42 #define NGX_POP3_DELE 7
43 #define NGX_POP3_NOOP 8
44 #define NGX_POP3_RSET 9
45 #define NGX_POP3_TOP 10
46 #define NGX_POP3_UIDL 11
47 #define NGX_POP3_QUIT 12
48
49
50 #define NGX_IMAP_PARSE_INVALID_COMMAND 10
51
52
53 #define NGX_IMAP_PROXY_INVALID 10
54 #define NGX_IMAP_PROXY_ERROR 11
3655
3756
3857 void ngx_imap_init_connection(ngx_connection_t *c);
3958 void ngx_imap_close_connection(ngx_connection_t *c);
4059
60 void ngx_imap_proxy_init(ngx_imap_session_t *s);
61
62 ngx_int_t ngx_pop3_parse_command(ngx_imap_session_t *s);
63
4164
4265 #endif /* _NGX_IMAP_H_INCLUDED_ */
55 #include <nginx.h>
66
77
8 static void ngx_imap_auth_state(ngx_event_t *rev);
8 static void ngx_imap_init_session(ngx_event_t *rev);
99
1010
1111 static char pop3_greeting[] = "+OK " NGINX_VER " ready" CRLF;
1414
1515 void ngx_imap_init_connection(ngx_connection_t *c)
1616 {
17 ngx_int_t n;
17 char *greeting;
18 ssize_t size;
19 ngx_int_t n;
1820
1921 ngx_log_debug0(NGX_LOG_DEBUG_IMAP, c->log, 0,
2022 "imap init connection");
2123
2224 c->log_error = NGX_ERROR_INFO;
2325
24 n = ngx_send(c, pop3_greeting, sizeof(pop3_greeting) - 1);
26 greeting = pop3_greeting;
27 size = sizeof(pop3_greeting) - 1;
2528
26 if (n == NGX_ERROR) {
29 n = ngx_send(c, greeting, size);
30
31 if (n < size) {
32 /*
33 * we treat the incomplete sending as NGX_ERROR
34 * because it is very strange here
35 */
2736 ngx_imap_close_connection(c);
2837 return;
2938 }
3039
31 c->read->event_handler = ngx_imap_auth_state;
40 c->read->event_handler = ngx_imap_init_session;
41
42 ngx_add_timer(c->read, /* STUB */ 60000);
3243
3344 if (ngx_handle_read_event(c->read, 0) == NGX_ERROR) {
3445 ngx_imap_close_connection(c);
35 return;
3646 }
3747 }
3848
3949
40 static void ngx_imap_auth_state(ngx_event_t *rev)
50 static void ngx_imap_init_session(ngx_event_t *rev)
4151 {
42 ngx_connection_t *c;
52 ngx_connection_t *c;
53 ngx_imap_session_t *s;
4354
4455 c = rev->data;
4556
46 ngx_imap_close_connection(c);
57 if (!(s = ngx_pcalloc(c->pool, sizeof(ngx_imap_session_t)))) {
58 ngx_imap_close_connection(c);
59 return;
60 }
61
62 c->data = s;
63 s->connection = c;
64
65 if (ngx_array_init(&s->args, c->pool, 2, sizeof(ngx_str_t)) == NGX_ERROR) {
66 ngx_imap_close_connection(s->connection);
67 return;
68 }
69
70 s->buffer = ngx_create_temp_buf(s->connection->pool, /* STUB */ 4096);
71 if (s->buffer == NULL) {
72 ngx_imap_close_connection(s->connection);
73 return;
74 }
75
76 ngx_imap_proxy_init(s);
4777 }
4878
4979
44 #include <ngx_imap.h>
55
66
7 ngx_int_t ngx_pop3_parse_command(ngx_imap_request_t *r)
7 ngx_int_t ngx_pop3_parse_command(ngx_imap_session_t *s)
88 {
9 u_char ch, *p, *c;
9 u_char ch, *p, *c;
10 ngx_str_t *arg;
1011 enum {
1112 sw_start = 0,
13 sw_spaces_before_argument,
14 sw_argument,
15 sw_almost_done,
1216 sw_done
1317 } state;
1418
15 while (p < r->buf->last && state < sw_done) {
19 state = s->state;
20 p = s->buffer->pos;
21
22 while (p < s->buffer->last && state < sw_done) {
1623 ch = *p++;
1724
1825 switch (state) {
1926
20 /* POP3 commands */
27 /* POP3 command */
28
2129 case sw_start:
22 if (ch == ' ') {
23 c = r->buf->start;
30 if (ch == ' ' || ch == CR || ch == LF) {
31 c = s->buffer->start;
2432
25 if (p - 1 - m == 4) {
33 if (p - 1 - c == 4) {
2634
27 if (*c == 'U' && *(c + 1) == 'S'
28 && *(c + 2) == 'E' && *(c + 3) == 'R')
35 if (c[0] == 'U' && c[1] == 'S'
36 && c[2] == 'E' && c[3] == 'R')
2937 {
30 r->command = NGX_POP3_USER;
38 s->command = NGX_POP3_USER;
3139
32 } else if (*c == 'P' && *(c + 1) == 'A'
33 && *(c + 2) == 'A' && *(c + 3) == 'S')
40 } else if (c[0] == 'P' && c[1] == 'A'
41 && c[2] == 'A' && c[3] == 'S')
3442 {
35 r->method = NGX_POP3_PASS;
43 s->command = NGX_POP3_PASS;
3644
37 } else if (*c == 'Q' && *(c + 1) == 'U'
38 && *(c + 2) == 'I' && *(c + 3) == 'T')
45 } else if (c[0] == 'Q' && c[1] == 'U'
46 && c[2] == 'I' && c[3] == 'T')
3947 {
40 r->method = NGX_POP3_QUIT;
48 s->command = NGX_POP3_QUIT;
4149
42 } else if (*c == 'N' && *(c + 1) == 'O'
43 && *(c + 2) == 'O' && *(c + 3) == 'P')
50 #if 0
51 } else if (c[0] == 'N' && c[1] == 'O'
52 && c[2] == 'O' && c[3] == 'P')
4453 {
45 r->method = NGX_POP3_NOOP;
54 s->command = NGX_POP3_NOOP;
55 #endif
56
57 } else {
58 return NGX_IMAP_PARSE_INVALID_COMMAND;
4659 }
60
61 } else {
62 return NGX_IMAP_PARSE_INVALID_COMMAND;
4763 }
4864
49 state = sw_spaces_before_arg;
65 switch (ch) {
66 case ' ':
67 state = sw_spaces_before_argument;
68 break;
69 case CR:
70 state = sw_almost_done;
71 break;
72 case LF:
73 state = sw_done;
74 break;
75 }
5076 break;
5177 }
5278
5581 }
5682
5783 break;
58 }
84
85 /* the spaces before the argument */
86 case sw_spaces_before_argument:
87 switch (ch) {
88 case ' ':
89 break;
90 case CR:
91 state = sw_almost_done;
92 s->arg_end = p - 1;
93 break;
94 case LF:
95 state = sw_done;
96 s->arg_end = p - 1;
97 break;
98 default:
99 if (s->args.nelts > 2) {
100 return NGX_IMAP_PARSE_INVALID_COMMAND;
101 }
102
103 state = sw_argument;
104 s->arg_start = p - 1;
105 break;
106 }
107 break;
108
109 /* the argument */
110 case sw_argument:
111 switch (ch) {
112 case ' ':
113 case CR:
114 case LF:
115 if (!(arg = ngx_array_push(&s->args))) {
116 return NGX_ERROR;
117 }
118 arg->len = p - s->arg_start;
119 arg->data = s->arg_start;
120 s->arg_start = NULL;
121
122 switch (ch) {
123 case ' ':
124 state = sw_spaces_before_argument;
125 break;
126 case CR:
127 state = sw_almost_done;
128 break;
129 case LF:
130 state = sw_done;
131 break;
132 }
133 break;
134
135 default:
136 break;
137 }
138 break;
139
140 /* end of request line */
141 case sw_almost_done:
142 switch (ch) {
143 case LF:
144 state = sw_done;
145 break;
146 default:
147 return NGX_IMAP_PARSE_INVALID_COMMAND;
148 }
149 break;
59150
60151 /* suppress warning */
61152 case sw_done:
63154 }
64155 }
65156
66 return NGX_OK;
157 s->buffer->pos = p;
158
159 if (state == sw_done) {
160 if (s->arg_start) {
161 if (!(arg = ngx_array_push(&s->args))) {
162 return NGX_ERROR;
163 }
164 arg->len = s->arg_end - s->arg_start;
165 arg->data = s->arg_start;
166 s->arg_start = NULL;
167 }
168
169 return NGX_OK;
170
171 } else {
172 s->state = state;
173 return NGX_AGAIN;
174 }
67175 }
11 #include <ngx_config.h>
22 #include <ngx_core.h>
33 #include <ngx_event.h>
4 #include <ngx_event_connect.h>
45 #include <ngx_imap.h>
56
67
8 static void ngx_imap_proxy_block_read(ngx_event_t *rev);
9 static void ngx_imap_proxy_greeting_handler(ngx_event_t *rev);
10 static void ngx_imap_proxy_init_handler(ngx_event_t *wev);
11 static void ngx_imap_proxy_dummy_handler(ngx_event_t *ev);
12 static ngx_int_t ngx_imap_proxy_read_response(ngx_imap_session_t *s);
13 static void ngx_imap_proxy_handler(ngx_event_t *ev);
714 static void ngx_imap_proxy_close_session(ngx_imap_session_t *s);
815
916
10 void ngx_imap_proxy_handler(ngx_event_t *ev)
11 {
17 void ngx_imap_proxy_init(ngx_imap_session_t *s)
18 {
19 ngx_int_t rc;
20 ngx_peers_t *peers;
21 ngx_imap_proxy_ctx_t *p;
22
23 if (!(p = ngx_pcalloc(s->connection->pool, sizeof(ngx_imap_proxy_ctx_t)))) {
24 ngx_imap_close_connection(s->connection);
25 return;
26 }
27
28 s->proxy = p;
29
30 /**/
31
32 if (!(peers = ngx_pcalloc(s->connection->pool, sizeof(ngx_peers_t)))) {
33 ngx_imap_close_connection(s->connection);
34 return;
35 }
36
37 p->upstream.peers = peers;
38 p->upstream.log = s->connection->log;
39 p->upstream.log_error = NGX_ERROR_ERR;
40
41 peers->number = 1;
42 peers->max_fails = 1;
43 peers->peers[0].addr = inet_addr("81.19.69.70");
44 peers->peers[0].addr_port_text.len = sizeof("81.19.69.70:110") - 1;
45 peers->peers[0].addr_port_text.data = "81.19.69.70:110";
46 peers->peers[0].port = htons(110);
47
48 rc = ngx_event_connect_peer(&p->upstream);
49
50 if (rc == NGX_ERROR) {
51 ngx_imap_proxy_close_session(s);
52 return;
53 }
54
55 p->upstream.connection->data = s;
56 p->upstream.connection->pool = s->connection->pool;
57
58 s->connection->read->event_handler = ngx_imap_proxy_block_read;
59 p->upstream.connection->read->event_handler =
60 ngx_imap_proxy_greeting_handler;
61 p->upstream.connection->write->event_handler = ngx_imap_proxy_dummy_handler;
62 }
63
64
65 static void ngx_imap_proxy_block_read(ngx_event_t *rev)
66 {
67 ngx_connection_t *c;
68 ngx_imap_session_t *s;
69
70 ngx_log_debug0(NGX_LOG_DEBUG_IMAP, rev->log, 0, "imap proxy block read");
71
72 if (ngx_handle_read_event(rev, 0) == NGX_ERROR) {
73 c = rev->data;
74 s = c->data;
75
76 ngx_imap_proxy_close_session(s);
77 }
78 }
79
80
81 static void ngx_imap_proxy_greeting_handler(ngx_event_t *rev)
82 {
83 ngx_int_t rc;
84 ngx_buf_t *b;
85 ngx_connection_t *c;
86 ngx_imap_session_t *s;
87
88 ngx_log_debug0(NGX_LOG_DEBUG_IMAP, rev->log, 0,
89 "imap proxy greeting handler");
90
91 c = rev->data;
92 s = c->data;
93
94 if (s->proxy->buffer == NULL) {
95 s->proxy->buffer = ngx_create_temp_buf(c->pool, /* STUB */ 4096);
96 if (s->proxy->buffer == NULL) {
97 ngx_imap_proxy_close_session(s);
98 return;
99 }
100 }
101
102 rc = ngx_imap_proxy_read_response(s);
103
104 if (rc == NGX_AGAIN) {
105 return;
106 }
107
108 if (rc == NGX_OK) {
109 s->connection->read->event_handler = ngx_imap_proxy_handler;
110 s->connection->write->event_handler = ngx_imap_proxy_handler;
111 rev->event_handler = ngx_imap_proxy_handler;
112 c->write->event_handler = ngx_imap_proxy_handler;
113
114 b = s->proxy->buffer;
115 b->pos = b->start;
116 b->last = b->start;
117
118 if (ngx_handle_read_event(s->connection->read, 0) == NGX_ERROR) {
119 ngx_imap_proxy_close_session(s);
120 return;
121 }
122
123 if (s->connection->read->ready) {
124 ngx_imap_proxy_handler(s->connection->read);
125 }
126
127 return;
128 }
129
130 /* TODO: ngx_imap_proxy_finalize_session(s, NGX_IMAP_INTERNAL_ERROR) */
131 ngx_imap_proxy_close_session(s);
132 }
133
134
135 static void ngx_imap_proxy_dummy_handler(ngx_event_t *ev)
136 {
137 ngx_log_debug0(NGX_LOG_DEBUG_IMAP, ev->log, 0, "imap proxy dummy handler");
138 }
139
140
141 static ngx_int_t ngx_imap_proxy_read_response(ngx_imap_session_t *s)
142 {
143 u_char *p;
144 ssize_t n;
145 ngx_buf_t *b;
146
147 b = s->proxy->buffer;
148
149 n = ngx_recv(s->proxy->upstream.connection, b->last, b->end - b->last);
150
151 if (n == NGX_ERROR || n == 0) {
152 return NGX_ERROR;
153 }
154
155 if (n == NGX_AGAIN) {
156 return NGX_AGAIN;
157 }
158
159 b->last += n;
160
161 if (b->last - b->pos < 5) {
162 return NGX_AGAIN;
163 }
164
165 if (*(b->last - 2) != CR || *(b->last - 1) != LF) {
166 if (b->last == b->end) {
167 *(b->last - 1) = '\0';
168 ngx_log_error(NGX_LOG_ERR, s->connection->log, 0,
169 "upstream sent too long response line: \"%s\"",
170 b->pos);
171 return NGX_IMAP_PROXY_INVALID;
172 }
173
174 return NGX_AGAIN;
175 }
176
177 p = b->pos;
178
179 if (p[0] == '+' && p[1] == 'O' && p[2] == 'K') {
180 return NGX_OK;
181 }
182
183 if (p[0] == '-' && p[1] == 'E' && p[2] == 'R' && p[3] == 'R') {
184 return NGX_IMAP_PROXY_ERROR;
185 }
186
187 *(b->last - 2) = '\0';
188 ngx_log_error(NGX_LOG_ERR, s->connection->log, 0,
189 "upstream sent invalid greeting line: \"%s\"", p);
190
191 return NGX_IMAP_PROXY_INVALID;
192 }
193
194
195 static void ngx_imap_proxy_handler(ngx_event_t *ev)
196 {
197 size_t size;
12198 ssize_t n;
13199 ngx_buf_t *b;
14200 ngx_uint_t data, do_write;
20206
21207 if (c == s->connection) {
22208 src = c;
23 dst = s->proxy->connection;
24 b = s->proxy->downstream_buffer;
209 dst = s->proxy->upstream.connection;
210 b = s->buffer;
25211
26212 } else {
27 src = s->proxy->connection;
28 dst = c;
29 b = s->proxy->upstream_buffer;
213 src = c;
214 dst = s->connection;
215 b = s->proxy->buffer;
30216 }
31217
32218 do_write = ev->write ? 1 : 0;
219
220 ngx_log_debug3(NGX_LOG_DEBUG_IMAP, ev->log, 0,
221 "imap proxy handler: %d, #%d > #%d",
222 do_write, src->fd, dst->fd);
33223
34224 do {
35225 data = 0;
36226
37227 if (do_write == 1) {
38 if (dst->write->ready && b->pos < b->last) {
39 n = ngx_send(dst, b->pos, b->last - b->pos);
228
229 size = b->last - b->pos;
230
231 if (dst->write->ready && size) {
232 n = ngx_send(dst, b->pos, size);
40233
41234 if (n == NGX_ERROR) {
42235 ngx_imap_proxy_close_session(s);
52245 b->last = b->start;
53246 }
54247 }
55 }
56 }
57
58 if (src->read->ready && b->last < b->end) {
59 n = ngx_recv(src, b->last, b->end - b->last);
248
249 if (n == NGX_AGAIN || n < (ssize_t) size) {
250 dst->write->available = 0;
251 if (ngx_handle_write_event(dst->write, NGX_LOWAT_EVENT)
252 == NGX_ERROR)
253 {
254 ngx_imap_proxy_close_session(s);
255 return;
256 }
257 }
258 }
259 }
260
261 size = b->end - b->last;
262
263 if (src->read->ready && size) {
264 n = ngx_recv(src, b->last, size);
60265
61266 if (n == NGX_ERROR || n == 0) {
62267 ngx_imap_proxy_close_session(s);
68273 do_write = 1;
69274 b->last += n;
70275 }
276
277 if (n == NGX_AGAIN || n < (ssize_t) size) {
278 if (ngx_handle_read_event(src->read, 0) == NGX_ERROR) {
279 ngx_imap_proxy_close_session(s);
280 return;
281 }
282 }
71283 }
72284
73285 } while (data);
76288
77289 static void ngx_imap_proxy_close_session(ngx_imap_session_t *s)
78290 {
79 }
291 if (ngx_close_socket(s->proxy->upstream.connection->fd) == -1) {
292 ngx_log_error(NGX_LOG_ALERT, s->connection->log, ngx_socket_errno,
293 ngx_close_socket_n " failed");
294 }
295
296 ngx_imap_close_connection(s->connection);
297 }
4141
4242 if (n == 0) {
4343 ngx_log_error(NGX_LOG_ALERT, c->log, err, "send() returned zero");
44 wev->ready = 0;
45 return n;
4446 }
4547
4648 if (err == NGX_EAGAIN || err == NGX_EINTR) {
9696 typedef long time_t;
9797 typedef __int64 off_t;
9898 typedef uint32_t in_addr_t;
99 typedef u_short in_port_t;
99100 typedef int sig_atomic_t;
100101 typedef uint32_t ngx_atomic_t;
101102