Groonga 3.0.9 Source Code Document
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
ngx_recv.c
Go to the documentation of this file.
1 
2 /*
3  * Copyright (C) Igor Sysoev
4  * Copyright (C) Nginx, Inc.
5  */
6 
7 
8 #include <ngx_config.h>
9 #include <ngx_core.h>
10 #include <ngx_event.h>
11 
12 
13 #if (NGX_HAVE_KQUEUE)
14 
15 ssize_t
16 ngx_unix_recv(ngx_connection_t *c, u_char *buf, size_t size)
17 {
18  ssize_t n;
19  ngx_err_t err;
20  ngx_event_t *rev;
21 
22  rev = c->read;
23 
26  "recv: eof:%d, avail:%d, err:%d",
27  rev->pending_eof, rev->available, rev->kq_errno);
28 
29  if (rev->available == 0) {
30  if (rev->pending_eof) {
31  rev->ready = 0;
32  rev->eof = 1;
33 
34  if (rev->kq_errno) {
35  rev->error = 1;
36  ngx_set_socket_errno(rev->kq_errno);
37 
38  return ngx_connection_error(c, rev->kq_errno,
39  "kevent() reported about an closed connection");
40  }
41 
42  return 0;
43 
44  } else {
45  rev->ready = 0;
46  return NGX_AGAIN;
47  }
48  }
49  }
50 
51  do {
52  n = recv(c->fd, buf, size, 0);
53 
55  "recv: fd:%d %d of %d", c->fd, n, size);
56 
57  if (n >= 0) {
58  if (ngx_event_flags & NGX_USE_KQUEUE_EVENT) {
59  rev->available -= n;
60 
61  /*
62  * rev->available may be negative here because some additional
63  * bytes may be received between kevent() and recv()
64  */
65 
66  if (rev->available <= 0) {
67  if (!rev->pending_eof) {
68  rev->ready = 0;
69  }
70 
71  if (rev->available < 0) {
72  rev->available = 0;
73  }
74  }
75 
76  if (n == 0) {
77 
78  /*
79  * on FreeBSD recv() may return 0 on closed socket
80  * even if kqueue reported about available data
81  */
82 
83  rev->eof = 1;
84  rev->available = 0;
85  }
86 
87  return n;
88  }
89 
90  if ((size_t) n < size) {
91  rev->ready = 0;
92  }
93 
94  if (n == 0) {
95  rev->eof = 1;
96  }
97 
98  return n;
99  }
100 
101  err = ngx_socket_errno;
102 
103  if (err == NGX_EAGAIN || err == NGX_EINTR) {
105  "recv() not ready");
106  n = NGX_AGAIN;
107 
108  } else {
109  n = ngx_connection_error(c, err, "recv() failed");
110  break;
111  }
112 
113  } while (err == NGX_EINTR);
114 
115  rev->ready = 0;
116 
117  if (n == NGX_ERROR) {
118  rev->error = 1;
119  }
120 
121  return n;
122 }
123 
124 #else /* ! NGX_HAVE_KQUEUE */
125 
126 ssize_t
127 ngx_unix_recv(ngx_connection_t *c, u_char *buf, size_t size)
128 {
129  ssize_t n;
130  ngx_err_t err;
131  ngx_event_t *rev;
132 
133  rev = c->read;
134 
135  do {
136  n = recv(c->fd, buf, size, 0);
137 
139  "recv: fd:%d %d of %d", c->fd, n, size);
140 
141  if (n == 0) {
142  rev->ready = 0;
143  rev->eof = 1;
144  return n;
145 
146  } else if (n > 0) {
147 
148  if ((size_t) n < size
150  {
151  rev->ready = 0;
152  }
153 
154  return n;
155  }
156 
157  err = ngx_socket_errno;
158 
159  if (err == NGX_EAGAIN || err == NGX_EINTR) {
161  "recv() not ready");
162  n = NGX_AGAIN;
163 
164  } else {
165  n = ngx_connection_error(c, err, "recv() failed");
166  break;
167  }
168 
169  } while (err == NGX_EINTR);
170 
171  rev->ready = 0;
172 
173  if (n == NGX_ERROR) {
174  rev->error = 1;
175  }
176 
177  return n;
178 }
179 
180 #endif /* NGX_HAVE_KQUEUE */