[ovs-dev] [PATCH v3 3/3] stream-ssl: Add support for windows platform.
Gurucharan Shetty
shettyg at nicira.com
Mon Feb 10 23:25:38 UTC 2014
This commit creates events and through poll_fd_wait_event()
associates them with socket file descriptors to get woken up
from poll_block().
Some other changes:
* Windows does not have sys/fcntl.h but has a fcntl.h
On Linux, there is fctnl.h too.
* include <openssl/applink.c> to handle different C-Runtime linking
of OVS and openssl libraries as suggested at
https://www.openssl.org/support/faq.html#PROG2
The above include will not be needed if we compile Open vSwitch with
/MD compiler option.
* SHUT_RDWR is equivalent to SD_BOTH on Windows.
Signed-off-by: Gurucharan Shetty <gshetty at nicira.com>
---
lib/socket-util.h | 11 +++++++
lib/stream-ssl.c | 86 +++++++++++++++++++++++++++++++++++++++++++----------
2 files changed, 82 insertions(+), 15 deletions(-)
diff --git a/lib/socket-util.h b/lib/socket-util.h
index d2b9f38..977714a 100644
--- a/lib/socket-util.h
+++ b/lib/socket-util.h
@@ -81,4 +81,15 @@ int af_inet_ifreq_ioctl(const char *name, struct ifreq *,
const char *sock_strerror(int error);
+#ifdef _WIN32
+/* Windows defines the 'optval' argument as char * instead of void *. */
+#define setsockopt(sock, level, optname, optval, optlen) \
+ rpl_setsockopt(sock, level, optname, optval, optlen)
+static inline int rpl_setsockopt(int sock, int level, int optname,
+ const void *optval, socklen_t optlen)
+{
+ return (setsockopt)(sock, level, optname, optval, optlen);
+}
+#endif
+
#endif /* socket-util.h */
diff --git a/lib/stream-ssl.c b/lib/stream-ssl.c
index 2ed5282..8af4e63 100644
--- a/lib/stream-ssl.c
+++ b/lib/stream-ssl.c
@@ -29,7 +29,7 @@
#include <openssl/ssl.h>
#include <openssl/x509v3.h>
#include <poll.h>
-#include <sys/fcntl.h>
+#include <fcntl.h>
#include <sys/stat.h>
#include <unistd.h>
#include "coverage.h"
@@ -47,6 +47,13 @@
#include "timeval.h"
#include "vlog.h"
+#ifdef _WIN32
+#include <openssl/applink.c>
+#define SHUT_RDWR SD_BOTH
+#else
+#define closesocket close
+#endif
+
VLOG_DEFINE_THIS_MODULE(stream_ssl);
/* Active SSL. */
@@ -67,6 +74,7 @@ struct ssl_stream
enum ssl_state state;
enum session_type type;
int fd;
+ HANDLE wevent;
SSL *ssl;
struct ofpbuf *txbuf;
unsigned int session_nr;
@@ -183,6 +191,8 @@ static void stream_ssl_set_ca_cert_file__(const char *file_name,
static void ssl_protocol_cb(int write_p, int version, int content_type,
const void *, size_t, SSL *, void *sslv_);
static bool update_ssl_config(struct ssl_config_file *, const char *file_name);
+static int sock_errno(void);
+static void clear_handle(int fd, HANDLE wevent);
static short int
want_to_poll_events(int want)
@@ -245,8 +255,9 @@ new_ssl_stream(const char *name, int fd, enum session_type type,
/* Disable Nagle. */
retval = setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &on, sizeof on);
if (retval) {
- VLOG_ERR("%s: setsockopt(TCP_NODELAY): %s", name, ovs_strerror(errno));
- retval = errno;
+ retval = sock_errno();
+ VLOG_ERR("%s: setsockopt(TCP_NODELAY): %s", name,
+ sock_strerror(retval));
goto error;
}
@@ -272,6 +283,9 @@ new_ssl_stream(const char *name, int fd, enum session_type type,
sslv->state = state;
sslv->type = type;
sslv->fd = fd;
+#ifdef _WIN32
+ sslv->wevent = CreateEvent(NULL, FALSE, FALSE, NULL);
+#endif
sslv->ssl = ssl;
sslv->txbuf = NULL;
sslv->rx_want = sslv->tx_want = SSL_NOTHING;
@@ -290,7 +304,7 @@ error:
if (ssl) {
SSL_free(ssl);
}
- close(fd);
+ closesocket(fd);
return retval;
}
@@ -500,7 +514,8 @@ ssl_close(struct stream *stream)
ERR_clear_error();
SSL_free(sslv->ssl);
- close(sslv->fd);
+ clear_handle(sslv->fd, sslv->wevent);
+ closesocket(sslv->fd);
free(sslv);
}
@@ -691,7 +706,8 @@ ssl_run_wait(struct stream *stream)
struct ssl_stream *sslv = ssl_stream_cast(stream);
if (sslv->tx_want != SSL_NOTHING) {
- poll_fd_wait(sslv->fd, want_to_poll_events(sslv->tx_want));
+ poll_fd_wait_event(sslv->fd, sslv->wevent,
+ want_to_poll_events(sslv->tx_want));
}
}
@@ -707,14 +723,14 @@ ssl_wait(struct stream *stream, enum stream_wait_type wait)
} else {
switch (sslv->state) {
case STATE_TCP_CONNECTING:
- poll_fd_wait(sslv->fd, POLLOUT);
+ poll_fd_wait_event(sslv->fd, sslv->wevent, POLLOUT);
break;
case STATE_SSL_CONNECTING:
/* ssl_connect() called SSL_accept() or SSL_connect(), which
* set up the status that we test here. */
- poll_fd_wait(sslv->fd,
- want_to_poll_events(SSL_want(sslv->ssl)));
+ poll_fd_wait_event(sslv->fd, sslv->wevent,
+ want_to_poll_events(SSL_want(sslv->ssl)));
break;
default:
@@ -725,7 +741,8 @@ ssl_wait(struct stream *stream, enum stream_wait_type wait)
case STREAM_RECV:
if (sslv->rx_want != SSL_NOTHING) {
- poll_fd_wait(sslv->fd, want_to_poll_events(sslv->rx_want));
+ poll_fd_wait_event(sslv->fd, sslv->wevent,
+ want_to_poll_events(sslv->rx_want));
} else {
poll_immediate_wake();
}
@@ -765,6 +782,7 @@ struct pssl_pstream
{
struct pstream pstream;
int fd;
+ HANDLE wevent;
};
const struct pstream_class pssl_pstream_class;
@@ -802,6 +820,9 @@ pssl_open(const char *name OVS_UNUSED, char *suffix, struct pstream **pstreamp,
pstream_init(&pssl->pstream, &pssl_pstream_class, bound_name);
pstream_set_bound_port(&pssl->pstream, sin.sin_port);
pssl->fd = fd;
+#ifdef _WIN32
+ pssl->wevent = CreateEvent(NULL, FALSE, FALSE, NULL);
+#endif
*pstreamp = &pssl->pstream;
return 0;
}
@@ -810,7 +831,8 @@ static void
pssl_close(struct pstream *pstream)
{
struct pssl_pstream *pssl = pssl_pstream_cast(pstream);
- close(pssl->fd);
+ clear_handle(pssl->fd, pssl->wevent);
+ closesocket(pssl->fd);
free(pssl);
}
@@ -826,16 +848,21 @@ pssl_accept(struct pstream *pstream, struct stream **new_streamp)
new_fd = accept(pssl->fd, (struct sockaddr *) &sin, &sin_len);
if (new_fd < 0) {
- error = errno;
+ error = sock_errno();
+#ifdef _WIN32
+ if (error == WSAEWOULDBLOCK) {
+ error = EAGAIN;
+ }
+#endif
if (error != EAGAIN) {
- VLOG_DBG_RL(&rl, "accept: %s", ovs_strerror(error));
+ VLOG_DBG_RL(&rl, "accept: %s", sock_strerror(error));
}
return error;
}
error = set_nonblocking(new_fd);
if (error) {
- close(new_fd);
+ closesocket(new_fd);
return error;
}
@@ -851,7 +878,7 @@ static void
pssl_wait(struct pstream *pstream)
{
struct pssl_pstream *pssl = pssl_pstream_cast(pstream);
- poll_fd_wait(pssl->fd, POLLIN);
+ poll_fd_wait_event(pssl->fd, pssl->wevent, POLLIN);
}
static int
@@ -899,6 +926,10 @@ do_ssl_init(void)
{
SSL_METHOD *method;
+#ifdef _WIN32
+ /* The following call is needed if we "#include <openssl/applink.c>". */
+ CRYPTO_malloc_init();
+#endif
SSL_library_init();
SSL_load_error_strings();
@@ -1370,3 +1401,28 @@ ssl_protocol_cb(int write_p, int version OVS_UNUSED, int content_type,
ds_destroy(&details);
}
+
+/* In Windows platform, errno is not set for socket calls.
+ * The last error has to be gotten from WSAGetLastError(). */
+static int
+sock_errno(void)
+{
+#ifdef _WIN32
+ return WSAGetLastError();
+#else
+ return errno;
+#endif
+}
+
+static void
+clear_handle(int fd OVS_UNUSED, HANDLE wevent OVS_UNUSED)
+{
+#ifdef _WIN32
+ if (fd) {
+ WSAEventSelect(fd, NULL, 0);
+ }
+ if (wevent) {
+ CloseHandle(wevent);
+ }
+#endif
+}
--
1.7.9.5
More information about the dev
mailing list