ngx_udp_recv()
Igor Sysoev
14 years ago
163 | 163 | src/os/unix/ngx_socket.c \ |
164 | 164 | src/os/unix/ngx_recv.c \ |
165 | 165 | src/os/unix/ngx_readv_chain.c \ |
166 | src/os/unix/ngx_udp_recv.c \ | |
166 | 167 | src/os/unix/ngx_send.c \ |
167 | 168 | src/os/unix/ngx_writev_chain.c \ |
168 | 169 | src/os/unix/ngx_channel.c \ |
228 | 229 | src/os/win32/ngx_socket.c \ |
229 | 230 | src/os/win32/ngx_wsarecv.c \ |
230 | 231 | src/os/win32/ngx_wsarecv_chain.c \ |
232 | src/os/win32/ngx_udp_wsarecv.c \ | |
231 | 233 | src/os/win32/ngx_wsasend_chain.c \ |
232 | 234 | src/os/win32/ngx_win32_init.c \ |
233 | 235 | src/os/win32/ngx_user.c \ |
825 | 825 | c = rev->data; |
826 | 826 | |
827 | 827 | do { |
828 | n = ngx_recv(c, buf, NGX_RESOLVER_UDP_SIZE); | |
829 | ||
830 | if (n == -1) { | |
828 | n = ngx_udp_recv(c, buf, NGX_RESOLVER_UDP_SIZE); | |
829 | ||
830 | if (n < 0) { | |
831 | 831 | return; |
832 | 832 | } |
833 | 833 |
27 | 27 | ngx_os_io_t ngx_os_aio = { |
28 | 28 | ngx_aio_read, |
29 | 29 | ngx_aio_read_chain, |
30 | NULL, | |
30 | 31 | ngx_aio_write, |
31 | 32 | ngx_aio_write_chain, |
32 | 33 | 0 |
89 | 89 | ngx_os_io_t ngx_iocp_io = { |
90 | 90 | ngx_overlapped_wsarecv, |
91 | 91 | NULL, |
92 | ngx_udp_overlapped_wsarecv, | |
92 | 93 | NULL, |
93 | 94 | ngx_overlapped_wsasend_chain, |
94 | 95 | 0 |
428 | 428 | |
429 | 429 | #define ngx_recv ngx_io.recv |
430 | 430 | #define ngx_recv_chain ngx_io.recv_chain |
431 | #define ngx_udp_recv ngx_io.udp_recv | |
431 | 432 | #define ngx_send ngx_io.send |
432 | 433 | #define ngx_send_chain ngx_io.send_chain |
433 | 434 |
29 | 29 | static ngx_os_io_t ngx_freebsd_io = { |
30 | 30 | ngx_unix_recv, |
31 | 31 | ngx_readv_chain, |
32 | ngx_udp_unix_recv, | |
32 | 33 | ngx_unix_send, |
33 | 34 | #if (NGX_HAVE_SENDFILE) |
34 | 35 | ngx_freebsd_sendfile_chain, |
16 | 16 | static ngx_os_io_t ngx_linux_io = { |
17 | 17 | ngx_unix_recv, |
18 | 18 | ngx_readv_chain, |
19 | ngx_udp_unix_recv, | |
19 | 20 | ngx_unix_send, |
20 | 21 | #if (NGX_HAVE_SENDFILE) |
21 | 22 | ngx_linux_sendfile_chain, |
24 | 24 | typedef struct { |
25 | 25 | ngx_recv_pt recv; |
26 | 26 | ngx_recv_chain_pt recv_chain; |
27 | ngx_recv_pt udp_recv; | |
27 | 28 | ngx_send_pt send; |
28 | 29 | ngx_send_chain_pt send_chain; |
29 | 30 | ngx_uint_t flags; |
40 | 41 | |
41 | 42 | ssize_t ngx_unix_recv(ngx_connection_t *c, u_char *buf, size_t size); |
42 | 43 | ssize_t ngx_readv_chain(ngx_connection_t *c, ngx_chain_t *entry); |
44 | ssize_t ngx_udp_unix_recv(ngx_connection_t *c, u_char *buf, size_t size); | |
43 | 45 | ssize_t ngx_unix_send(ngx_connection_t *c, u_char *buf, size_t size); |
44 | 46 | ngx_chain_t *ngx_writev_chain(ngx_connection_t *c, ngx_chain_t *in, |
45 | 47 | off_t limit); |
20 | 20 | ngx_os_io_t ngx_os_io = { |
21 | 21 | ngx_unix_recv, |
22 | 22 | ngx_readv_chain, |
23 | ngx_udp_unix_recv, | |
23 | 24 | NULL, |
24 | 25 | ngx_writev_chain, |
25 | 26 | 0 |
15 | 15 | static ngx_os_io_t ngx_solaris_io = { |
16 | 16 | ngx_unix_recv, |
17 | 17 | ngx_readv_chain, |
18 | ngx_udp_unix_recv, | |
18 | 19 | ngx_unix_send, |
19 | 20 | #if (NGX_HAVE_SENDFILE) |
20 | 21 | ngx_solaris_sendfilev_chain, |
0 | ||
1 | /* | |
2 | * Copyright (C) Igor Sysoev | |
3 | */ | |
4 | ||
5 | ||
6 | #include <ngx_config.h> | |
7 | #include <ngx_core.h> | |
8 | #include <ngx_event.h> | |
9 | ||
10 | ||
11 | #if (NGX_HAVE_KQUEUE) | |
12 | ||
13 | ssize_t | |
14 | ngx_udp_unix_recv(ngx_connection_t *c, u_char *buf, size_t size) | |
15 | { | |
16 | ssize_t n; | |
17 | ngx_err_t err; | |
18 | ngx_event_t *rev; | |
19 | ||
20 | rev = c->read; | |
21 | ||
22 | do { | |
23 | n = recv(c->fd, buf, size, 0); | |
24 | ||
25 | ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0, | |
26 | "recv: fd:%d %d of %d", c->fd, n, size); | |
27 | ||
28 | if (n >= 0) { | |
29 | if (ngx_event_flags & NGX_USE_KQUEUE_EVENT) { | |
30 | rev->available -= n; | |
31 | ||
32 | /* | |
33 | * rev->available may be negative here because some additional | |
34 | * bytes may be received between kevent() and recv() | |
35 | */ | |
36 | ||
37 | if (rev->available <= 0) { | |
38 | rev->ready = 0; | |
39 | rev->available = 0; | |
40 | } | |
41 | } | |
42 | ||
43 | return n; | |
44 | } | |
45 | ||
46 | err = ngx_socket_errno; | |
47 | ||
48 | if (err == NGX_EAGAIN || err == NGX_EINTR) { | |
49 | ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, err, | |
50 | "recv() not ready"); | |
51 | n = NGX_AGAIN; | |
52 | ||
53 | } else { | |
54 | n = ngx_connection_error(c, err, "recv() failed"); | |
55 | break; | |
56 | } | |
57 | ||
58 | } while (err == NGX_EINTR); | |
59 | ||
60 | rev->ready = 0; | |
61 | ||
62 | if (n == NGX_ERROR){ | |
63 | rev->error = 1; | |
64 | } | |
65 | ||
66 | return n; | |
67 | } | |
68 | ||
69 | #else /* ! NGX_HAVE_KQUEUE */ | |
70 | ||
71 | ssize_t | |
72 | ngx_udp_unix_recv(ngx_connection_t *c, u_char *buf, size_t size) | |
73 | { | |
74 | ssize_t n; | |
75 | ngx_err_t err; | |
76 | ngx_event_t *rev; | |
77 | ||
78 | rev = c->read; | |
79 | ||
80 | do { | |
81 | n = recv(c->fd, buf, size, 0); | |
82 | ||
83 | ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0, | |
84 | "recv: fd:%d %d of %d", c->fd, n, size); | |
85 | ||
86 | if (n >= 0) { | |
87 | return n; | |
88 | } | |
89 | ||
90 | err = ngx_socket_errno; | |
91 | ||
92 | if (err == NGX_EAGAIN || err == NGX_EINTR) { | |
93 | ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, err, | |
94 | "recv() not ready"); | |
95 | n = NGX_AGAIN; | |
96 | ||
97 | } else { | |
98 | n = ngx_connection_error(c, err, "recv() failed"); | |
99 | break; | |
100 | } | |
101 | ||
102 | } while (err == NGX_EINTR); | |
103 | ||
104 | rev->ready = 0; | |
105 | ||
106 | if (n == NGX_ERROR){ | |
107 | rev->error = 1; | |
108 | } | |
109 | ||
110 | return n; | |
111 | } | |
112 | ||
113 | #endif /* NGX_HAVE_KQUEUE */ |
19 | 19 | typedef ssize_t (*ngx_recv_chain_pt)(ngx_connection_t *c, ngx_chain_t *in); |
20 | 20 | typedef ssize_t (*ngx_send_pt)(ngx_connection_t *c, u_char *buf, size_t size); |
21 | 21 | typedef ngx_chain_t *(*ngx_send_chain_pt)(ngx_connection_t *c, ngx_chain_t *in, |
22 | off_t limit); | |
22 | off_t limit); | |
23 | 23 | |
24 | 24 | typedef struct { |
25 | 25 | ngx_recv_pt recv; |
26 | 26 | ngx_recv_chain_pt recv_chain; |
27 | ngx_recv_pt udp_recv; | |
27 | 28 | ngx_send_pt send; |
28 | 29 | ngx_send_chain_pt send_chain; |
29 | 30 | ngx_uint_t flags; |
35 | 36 | |
36 | 37 | ssize_t ngx_wsarecv(ngx_connection_t *c, u_char *buf, size_t size); |
37 | 38 | ssize_t ngx_overlapped_wsarecv(ngx_connection_t *c, u_char *buf, size_t size); |
39 | ssize_t ngx_udp_wsarecv(ngx_connection_t *c, u_char *buf, size_t size); | |
40 | ssize_t ngx_udp_overlapped_wsarecv(ngx_connection_t *c, u_char *buf, | |
41 | size_t size); | |
38 | 42 | ssize_t ngx_wsarecv_chain(ngx_connection_t *c, ngx_chain_t *chain); |
39 | 43 | ngx_chain_t *ngx_wsasend_chain(ngx_connection_t *c, ngx_chain_t *in, |
40 | off_t limit); | |
44 | off_t limit); | |
41 | 45 | ngx_chain_t *ngx_overlapped_wsasend_chain(ngx_connection_t *c, ngx_chain_t *in, |
42 | off_t limit); | |
46 | off_t limit); | |
43 | 47 | |
44 | 48 | |
45 | 49 | extern ngx_os_io_t ngx_os_io; |
0 | ||
1 | /* | |
2 | * Copyright (C) Igor Sysoev | |
3 | */ | |
4 | ||
5 | ||
6 | #include <ngx_config.h> | |
7 | #include <ngx_core.h> | |
8 | #include <ngx_event.h> | |
9 | ||
10 | ||
11 | ssize_t | |
12 | ngx_udp_wsarecv(ngx_connection_t *c, u_char *buf, size_t size) | |
13 | { | |
14 | int rc; | |
15 | u_long bytes, flags; | |
16 | WSABUF wsabuf[1]; | |
17 | ngx_err_t err; | |
18 | ngx_event_t *rev; | |
19 | ||
20 | wsabuf[0].buf = (char *) buf; | |
21 | wsabuf[0].len = size; | |
22 | flags = 0; | |
23 | bytes = 0; | |
24 | ||
25 | rc = WSARecv(c->fd, wsabuf, 1, &bytes, &flags, NULL, NULL); | |
26 | ||
27 | ngx_log_debug4(NGX_LOG_DEBUG_EVENT, c->log, 0, | |
28 | "WSARecv: fd:%d rc:%d %ul of %z", c->fd, rc, bytes, size); | |
29 | ||
30 | rev = c->read; | |
31 | ||
32 | if (rc == -1) { | |
33 | rev->ready = 0; | |
34 | err = ngx_socket_errno; | |
35 | ||
36 | if (err == WSAEWOULDBLOCK) { | |
37 | ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, err, | |
38 | "WSARecv() not ready"); | |
39 | return NGX_AGAIN; | |
40 | } | |
41 | ||
42 | rev->error = 1; | |
43 | ngx_connection_error(c, err, "WSARecv() failed"); | |
44 | ||
45 | return NGX_ERROR; | |
46 | } | |
47 | ||
48 | return bytes; | |
49 | } | |
50 | ||
51 | ||
52 | ssize_t | |
53 | ngx_udp_overlapped_wsarecv(ngx_connection_t *c, u_char *buf, size_t size) | |
54 | { | |
55 | int rc; | |
56 | u_long bytes, flags; | |
57 | WSABUF wsabuf[1]; | |
58 | ngx_err_t err; | |
59 | ngx_event_t *rev; | |
60 | LPWSAOVERLAPPED ovlp; | |
61 | ||
62 | rev = c->read; | |
63 | ||
64 | if (!rev->ready) { | |
65 | ngx_log_error(NGX_LOG_ALERT, c->log, 0, "second wsa post"); | |
66 | return NGX_AGAIN; | |
67 | } | |
68 | ||
69 | ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, | |
70 | "rev->complete: %d", rev->complete); | |
71 | ||
72 | if (rev->complete) { | |
73 | rev->complete = 0; | |
74 | ||
75 | if (ngx_event_flags & NGX_USE_IOCP_EVENT) { | |
76 | if (rev->ovlp.error) { | |
77 | ngx_connection_error(c, rev->ovlp.error, "WSARecv() failed"); | |
78 | return NGX_ERROR; | |
79 | } | |
80 | ||
81 | ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0, | |
82 | "WSARecv ovlp: fd:%d %ul of %z", | |
83 | c->fd, rev->available, size); | |
84 | ||
85 | return rev->available; | |
86 | } | |
87 | ||
88 | if (WSAGetOverlappedResult(c->fd, (LPWSAOVERLAPPED) &rev->ovlp, | |
89 | &bytes, 0, NULL) == 0) { | |
90 | ngx_connection_error(c, ngx_socket_errno, | |
91 | "WSARecv() or WSAGetOverlappedResult() failed"); | |
92 | return NGX_ERROR; | |
93 | } | |
94 | ||
95 | ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0, | |
96 | "WSARecv: fd:%d %ul of %z", c->fd, bytes, size); | |
97 | ||
98 | return bytes; | |
99 | } | |
100 | ||
101 | ovlp = (LPWSAOVERLAPPED) &rev->ovlp; | |
102 | ngx_memzero(ovlp, sizeof(WSAOVERLAPPED)); | |
103 | wsabuf[0].buf = (char *) buf; | |
104 | wsabuf[0].len = size; | |
105 | flags = 0; | |
106 | bytes = 0; | |
107 | ||
108 | rc = WSARecv(c->fd, wsabuf, 1, &bytes, &flags, ovlp, NULL); | |
109 | ||
110 | rev->complete = 0; | |
111 | ||
112 | ngx_log_debug4(NGX_LOG_DEBUG_EVENT, c->log, 0, | |
113 | "WSARecv ovlp: fd:%d rc:%d %ul of %z", | |
114 | c->fd, rc, bytes, size); | |
115 | ||
116 | if (rc == -1) { | |
117 | err = ngx_socket_errno; | |
118 | if (err == WSA_IO_PENDING) { | |
119 | rev->active = 1; | |
120 | ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, err, | |
121 | "WSARecv() posted"); | |
122 | return NGX_AGAIN; | |
123 | } | |
124 | ||
125 | rev->error = 1; | |
126 | ngx_connection_error(c, err, "WSARecv() failed"); | |
127 | return NGX_ERROR; | |
128 | } | |
129 | ||
130 | if (ngx_event_flags & NGX_USE_IOCP_EVENT) { | |
131 | ||
132 | /* | |
133 | * if a socket was bound with I/O completion port | |
134 | * then GetQueuedCompletionStatus() would anyway return its status | |
135 | * despite that WSARecv() was already complete | |
136 | */ | |
137 | ||
138 | rev->active = 1; | |
139 | return NGX_AGAIN; | |
140 | } | |
141 | ||
142 | rev->active = 0; | |
143 | ||
144 | return bytes; | |
145 | } |