]> git.proxmox.com Git - ovs.git/blob - lib/stream-fd-windows.c
Makefile.am: Properly indent INSTALL.DPDK
[ovs.git] / lib / stream-fd-windows.c
1 /*
2 * Copyright (c) 2014 Nicira, Inc.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at:
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include <config.h>
18 #include "stream-fd.h"
19 #include <errno.h>
20 #include <poll.h>
21 #include <stdlib.h>
22 #include <string.h>
23 #include <sys/types.h>
24 #include <unistd.h>
25 #include <winsock2.h>
26 #include "fatal-signal.h"
27 #include "poll-loop.h"
28 #include "socket-util.h"
29 #include "stream.h"
30 #include "stream-provider.h"
31 #include "util.h"
32 #include "vlog.h"
33
34 VLOG_DEFINE_THIS_MODULE(stream_fd_windows);
35
36 /* Active file descriptor stream. */
37
38 struct stream_fd
39 {
40 struct stream stream;
41 int fd;
42 };
43
44 static const struct stream_class stream_fd_class;
45
46 static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(10, 25);
47
48 /* Creates a new stream named 'name' that will send and receive data on 'fd'
49 * and stores a pointer to the stream in '*streamp'. Initial connection status
50 * 'connect_status' is interpreted as described for stream_init().
51 *
52 * Returns 0 if successful, otherwise a positive errno value. (The current
53 * implementation never fails.) */
54 int
55 new_fd_stream(const char *name, int fd, int connect_status,
56 struct stream **streamp)
57 {
58 struct stream_fd *s;
59
60 s = xmalloc(sizeof *s);
61 stream_init(&s->stream, &stream_fd_class, connect_status, name);
62 s->fd = fd;
63 *streamp = &s->stream;
64 return 0;
65 }
66
67 static struct stream_fd *
68 stream_fd_cast(struct stream *stream)
69 {
70 stream_assert_class(stream, &stream_fd_class);
71 return CONTAINER_OF(stream, struct stream_fd, stream);
72 }
73
74 static void
75 fd_close(struct stream *stream)
76 {
77 struct stream_fd *s = stream_fd_cast(stream);
78 closesocket(s->fd);
79 free(s);
80 }
81
82 static int
83 fd_connect(struct stream *stream)
84 {
85 struct stream_fd *s = stream_fd_cast(stream);
86 return check_connection_completion(s->fd);
87 }
88
89 static ssize_t
90 fd_recv(struct stream *stream, void *buffer, size_t n)
91 {
92 struct stream_fd *s = stream_fd_cast(stream);
93 ssize_t retval;
94
95 retval = recv(s->fd, buffer, n, 0);
96 if (retval < 0) {
97 retval = -sock_errno();
98 }
99 if (retval == -WSAEWOULDBLOCK) {
100 return -EAGAIN;
101 }
102 return retval;
103 }
104
105 static ssize_t
106 fd_send(struct stream *stream, const void *buffer, size_t n)
107 {
108 struct stream_fd *s = stream_fd_cast(stream);
109 ssize_t retval;
110
111 retval = send(s->fd, buffer, n, 0);
112 if (retval < 0) {
113 retval = -sock_errno();
114 }
115 if (retval == -WSAEWOULDBLOCK) {
116 return -EAGAIN;
117 }
118
119 return retval;
120 }
121
122 static void
123 fd_wait(struct stream *stream, enum stream_wait_type wait)
124 {
125 struct stream_fd *s = stream_fd_cast(stream);
126 switch (wait) {
127 case STREAM_CONNECT:
128 case STREAM_SEND:
129 poll_fd_wait(s->fd, POLLOUT);
130 break;
131
132 case STREAM_RECV:
133 poll_fd_wait(s->fd, POLLIN);
134 break;
135
136 default:
137 OVS_NOT_REACHED();
138 }
139 }
140
141 static const struct stream_class stream_fd_class = {
142 "fd", /* name */
143 false, /* needs_probes */
144 NULL, /* open */
145 fd_close, /* close */
146 fd_connect, /* connect */
147 fd_recv, /* recv */
148 fd_send, /* send */
149 NULL, /* run */
150 NULL, /* run_wait */
151 fd_wait, /* wait */
152 };
153 \f
154 /* Passive file descriptor stream. */
155
156 struct fd_pstream
157 {
158 struct pstream pstream;
159 int fd;
160 int (*accept_cb)(int fd, const struct sockaddr_storage *, size_t ss_len,
161 struct stream **);
162 int (*set_dscp_cb)(int fd, uint8_t dscp);
163 char *unlink_path;
164 };
165
166 static const struct pstream_class fd_pstream_class;
167
168 static struct fd_pstream *
169 fd_pstream_cast(struct pstream *pstream)
170 {
171 pstream_assert_class(pstream, &fd_pstream_class);
172 return CONTAINER_OF(pstream, struct fd_pstream, pstream);
173 }
174
175 /* Creates a new pstream named 'name' that will accept new socket connections
176 * on 'fd' and stores a pointer to the stream in '*pstreamp'.
177 *
178 * When a connection has been accepted, 'accept_cb' will be called with the new
179 * socket fd 'fd' and the remote address of the connection 'sa' and 'sa_len'.
180 * accept_cb must return 0 if the connection is successful, in which case it
181 * must initialize '*streamp' to the new stream, or a positive errno value on
182 * error. In either case accept_cb takes ownership of the 'fd' passed in.
183 *
184 * When '*pstreamp' is closed, then 'unlink_path' (if nonnull) will be passed
185 * to fatal_signal_unlink_file_now() and freed with free().
186 *
187 * Returns 0 if successful, otherwise a positive errno value. (The current
188 * implementation never fails.) */
189 int
190 new_fd_pstream(const char *name, int fd,
191 int (*accept_cb)(int fd, const struct sockaddr_storage *ss,
192 size_t ss_len, struct stream **streamp),
193 int (*set_dscp_cb)(int fd, uint8_t dscp),
194 char *unlink_path, struct pstream **pstreamp)
195 {
196 struct fd_pstream *ps = xmalloc(sizeof *ps);
197 pstream_init(&ps->pstream, &fd_pstream_class, name);
198 ps->fd = fd;
199 ps->accept_cb = accept_cb;
200 ps->set_dscp_cb = set_dscp_cb;
201 ps->unlink_path = unlink_path;
202 *pstreamp = &ps->pstream;
203 return 0;
204 }
205
206 static void
207 pfd_close(struct pstream *pstream)
208 {
209 struct fd_pstream *ps = fd_pstream_cast(pstream);
210 closesocket(ps->fd);
211 if (ps->unlink_path) {
212 fatal_signal_unlink_file_now(ps->unlink_path);
213 free(ps->unlink_path);
214 }
215 free(ps);
216 }
217
218 static int
219 pfd_accept(struct pstream *pstream, struct stream **new_streamp)
220 {
221 struct fd_pstream *ps = fd_pstream_cast(pstream);
222 struct sockaddr_storage ss;
223 socklen_t ss_len = sizeof ss;
224 int new_fd;
225 int retval;
226
227 new_fd = accept(ps->fd, (struct sockaddr *) &ss, &ss_len);
228 if (new_fd < 0) {
229 retval = sock_errno();
230 if (retval == WSAEWOULDBLOCK) {
231 return EAGAIN;
232 }
233 return retval;
234 }
235
236 retval = set_nonblocking(new_fd);
237 if (retval) {
238 closesocket(new_fd);
239 return retval;
240 }
241
242 return ps->accept_cb(new_fd, &ss, ss_len, new_streamp);
243 }
244
245 static void
246 pfd_wait(struct pstream *pstream)
247 {
248 struct fd_pstream *ps = fd_pstream_cast(pstream);
249 poll_fd_wait(ps->fd, POLLIN);
250 }
251
252 static int
253 pfd_set_dscp(struct pstream *pstream, uint8_t dscp)
254 {
255 struct fd_pstream *ps = fd_pstream_cast(pstream);
256 if (ps->set_dscp_cb) {
257 return ps->set_dscp_cb(ps->fd, dscp);
258 }
259 return 0;
260 }
261
262 static const struct pstream_class fd_pstream_class = {
263 "pstream",
264 false,
265 NULL,
266 pfd_close,
267 pfd_accept,
268 pfd_wait,
269 pfd_set_dscp,
270 };