datapath-windows: Add WMI Script that updates Hyper-V friendly port names.
[cascardo/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 };