Setting tag sliver-openvswitch-2.2.90-1
[sliver-openvswitch.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     HANDLE wevent;
43 };
44
45 static const struct stream_class stream_fd_class;
46
47 static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(10, 25);
48
49 /* Creates a new stream named 'name' that will send and receive data on 'fd'
50  * and stores a pointer to the stream in '*streamp'.  Initial connection status
51  * 'connect_status' is interpreted as described for stream_init().
52  *
53  * Returns 0 if successful, otherwise a positive errno value.  (The current
54  * implementation never fails.) */
55 int
56 new_fd_stream(const char *name, int fd, int connect_status,
57               struct stream **streamp)
58 {
59     struct stream_fd *s;
60
61     s = xmalloc(sizeof *s);
62     stream_init(&s->stream, &stream_fd_class, connect_status, name);
63     s->fd = fd;
64     s->wevent = CreateEvent(NULL, FALSE, FALSE, NULL);
65     *streamp = &s->stream;
66     return 0;
67 }
68
69 static struct stream_fd *
70 stream_fd_cast(struct stream *stream)
71 {
72     stream_assert_class(stream, &stream_fd_class);
73     return CONTAINER_OF(stream, struct stream_fd, stream);
74 }
75
76 static void
77 fd_close(struct stream *stream)
78 {
79     struct stream_fd *s = stream_fd_cast(stream);
80     WSAEventSelect(s->fd, NULL, 0);
81     CloseHandle(s->wevent);
82     closesocket(s->fd);
83     free(s);
84 }
85
86 static int
87 fd_connect(struct stream *stream)
88 {
89     struct stream_fd *s = stream_fd_cast(stream);
90     return check_connection_completion(s->fd);
91 }
92
93 static ssize_t
94 fd_recv(struct stream *stream, void *buffer, size_t n)
95 {
96     struct stream_fd *s = stream_fd_cast(stream);
97     ssize_t retval;
98
99     retval = recv(s->fd, buffer, n, 0);
100     if (retval < 0) {
101         retval = -sock_errno();
102     }
103     if (retval == -WSAEWOULDBLOCK) {
104         return -EAGAIN;
105     }
106     return retval;
107 }
108
109 static ssize_t
110 fd_send(struct stream *stream, const void *buffer, size_t n)
111 {
112     struct stream_fd *s = stream_fd_cast(stream);
113     ssize_t retval;
114
115     retval = send(s->fd, buffer, n, 0);
116     if (retval < 0) {
117         retval = -sock_errno();
118     }
119     if (retval == -WSAEWOULDBLOCK) {
120         return -EAGAIN;
121     }
122
123     return retval;
124 }
125
126 static void
127 fd_wait(struct stream *stream, enum stream_wait_type wait)
128 {
129     struct stream_fd *s = stream_fd_cast(stream);
130     switch (wait) {
131     case STREAM_CONNECT:
132     case STREAM_SEND:
133         poll_fd_wait_event(s->fd, s->wevent, POLLOUT);
134         break;
135
136     case STREAM_RECV:
137         poll_fd_wait_event(s->fd, s->wevent, POLLIN);
138         break;
139
140     default:
141         OVS_NOT_REACHED();
142     }
143 }
144
145 static const struct stream_class stream_fd_class = {
146     "fd",                       /* name */
147     false,                      /* needs_probes */
148     NULL,                       /* open */
149     fd_close,                   /* close */
150     fd_connect,                 /* connect */
151     fd_recv,                    /* recv */
152     fd_send,                    /* send */
153     NULL,                       /* run */
154     NULL,                       /* run_wait */
155     fd_wait,                    /* wait */
156 };
157 \f
158 /* Passive file descriptor stream. */
159
160 struct fd_pstream
161 {
162     struct pstream pstream;
163     int fd;
164     HANDLE wevent;
165     int (*accept_cb)(int fd, const struct sockaddr_storage *, size_t ss_len,
166                      struct stream **);
167     int (*set_dscp_cb)(int fd, uint8_t dscp);
168     char *unlink_path;
169 };
170
171 static const struct pstream_class fd_pstream_class;
172
173 static struct fd_pstream *
174 fd_pstream_cast(struct pstream *pstream)
175 {
176     pstream_assert_class(pstream, &fd_pstream_class);
177     return CONTAINER_OF(pstream, struct fd_pstream, pstream);
178 }
179
180 /* Creates a new pstream named 'name' that will accept new socket connections
181  * on 'fd' and stores a pointer to the stream in '*pstreamp'.
182  *
183  * When a connection has been accepted, 'accept_cb' will be called with the new
184  * socket fd 'fd' and the remote address of the connection 'sa' and 'sa_len'.
185  * accept_cb must return 0 if the connection is successful, in which case it
186  * must initialize '*streamp' to the new stream, or a positive errno value on
187  * error.  In either case accept_cb takes ownership of the 'fd' passed in.
188  *
189  * When '*pstreamp' is closed, then 'unlink_path' (if nonnull) will be passed
190  * to fatal_signal_unlink_file_now() and freed with free().
191  *
192  * Returns 0 if successful, otherwise a positive errno value.  (The current
193  * implementation never fails.) */
194 int
195 new_fd_pstream(const char *name, int fd,
196                int (*accept_cb)(int fd, const struct sockaddr_storage *ss,
197                                 size_t ss_len, struct stream **streamp),
198                int (*set_dscp_cb)(int fd, uint8_t dscp),
199                char *unlink_path, struct pstream **pstreamp)
200 {
201     struct fd_pstream *ps = xmalloc(sizeof *ps);
202     pstream_init(&ps->pstream, &fd_pstream_class, name);
203     ps->fd = fd;
204     ps->wevent = CreateEvent(NULL, FALSE, FALSE, NULL);
205     ps->accept_cb = accept_cb;
206     ps->set_dscp_cb = set_dscp_cb;
207     ps->unlink_path = unlink_path;
208     *pstreamp = &ps->pstream;
209     return 0;
210 }
211
212 static void
213 pfd_close(struct pstream *pstream)
214 {
215     struct fd_pstream *ps = fd_pstream_cast(pstream);
216     WSAEventSelect(ps->fd, NULL, 0);
217     CloseHandle(ps->wevent);
218     closesocket(ps->fd);
219     free(ps);
220 }
221
222 static int
223 pfd_accept(struct pstream *pstream, struct stream **new_streamp)
224 {
225     struct fd_pstream *ps = fd_pstream_cast(pstream);
226     struct sockaddr_storage ss;
227     socklen_t ss_len = sizeof ss;
228     int new_fd;
229     int retval;
230
231     new_fd = accept(ps->fd, (struct sockaddr *) &ss, &ss_len);
232     if (new_fd < 0) {
233         retval = sock_errno();
234         if (retval == WSAEWOULDBLOCK) {
235             return EAGAIN;
236         }
237         return retval;
238     }
239
240     retval = set_nonblocking(new_fd);
241     if (retval) {
242         closesocket(new_fd);
243         return retval;
244     }
245
246     return ps->accept_cb(new_fd, &ss, ss_len, new_streamp);
247 }
248
249 static void
250 pfd_wait(struct pstream *pstream)
251 {
252     struct fd_pstream *ps = fd_pstream_cast(pstream);
253     poll_fd_wait_event(ps->fd, ps->wevent, POLLIN);
254 }
255
256 static int
257 pfd_set_dscp(struct pstream *pstream, uint8_t dscp)
258 {
259     struct fd_pstream *ps = fd_pstream_cast(pstream);
260     if (ps->set_dscp_cb) {
261         return ps->set_dscp_cb(ps->fd, dscp);
262     }
263     return 0;
264 }
265
266 static const struct pstream_class fd_pstream_class = {
267     "pstream",
268     false,
269     NULL,
270     pfd_close,
271     pfd_accept,
272     pfd_wait,
273     pfd_set_dscp,
274 };