Skip to content

Commit

Permalink
Python tests: Ported UNIX sockets to Windows
Browse files Browse the repository at this point in the history
Unix sockets (AF_UNIX) are not supported on Windows.
The replacement of Unix sockets on Windows is implemented
using named pipes, we are trying to mimic the behaviour
of unix sockets.

Instead of using Unix sockets to communicate
between components Named Pipes are used. This
makes the python sockets compatible with the
Named Pipe used in Windows applications.

Signed-off-by: Paul-Daniel Boca <[email protected]>
Signed-off-by: Alin Balutoiu <[email protected]>
Acked-by: Alin Gabriel Serdean <aserdean@cloudbasesolutions>
Tested-by: Alin Gabriel Serdean <aserdean@cloudbasesolutions>
Signed-off-by: Gurucharan Shetty <[email protected]>
  • Loading branch information
alinbalutoiu authored and shettyg committed Jan 3, 2017
1 parent f98c8a0 commit 03947eb
Show file tree
Hide file tree
Showing 6 changed files with 437 additions and 44 deletions.
6 changes: 6 additions & 0 deletions python/ovs/jsonrpc.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@

import errno
import os
import sys

import six

Expand Down Expand Up @@ -274,6 +275,11 @@ def recv(self):
except UnicodeError:
error = errno.EILSEQ
if error:
if (sys.platform == "win32" and
error == errno.WSAEWOULDBLOCK):
# WSAEWOULDBLOCK would be the equivalent on Windows
# for EAGAIN on Unix.
error = errno.EAGAIN
if error == errno.EAGAIN:
return error, None
else:
Expand Down
72 changes: 54 additions & 18 deletions python/ovs/poller.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@
import select
import socket
import os
import sys

if sys.platform == "win32":
import ovs.winutils as winutils

try:
from OpenSSL import SSL
Expand Down Expand Up @@ -62,7 +66,9 @@ def register(self, fd, events):
if SSL and isinstance(fd, SSL.Connection):
fd = fd.fileno()

assert isinstance(fd, int)
if sys.platform != 'win32':
# Skip this on Windows, it also register events
assert isinstance(fd, int)
if events & POLLIN:
self.rlist.append(fd)
events &= ~POLLIN
Expand All @@ -73,28 +79,58 @@ def register(self, fd, events):
self.xlist.append(fd)

def poll(self, timeout):
if timeout == -1:
# epoll uses -1 for infinite timeout, select uses None.
timeout = None
else:
timeout = float(timeout) / 1000
# XXX workaround a bug in eventlet
# see https://github.com/eventlet/eventlet/pull/25
if timeout == 0 and _using_eventlet_green_select():
timeout = 0.1
if sys.platform == 'win32':
events = self.rlist + self.wlist + self.xlist
if not events:
return []
if len(events) > winutils.win32event.MAXIMUM_WAIT_OBJECTS:
raise WindowsError("Cannot handle more than maximum wait"
"objects\n")

# win32event.INFINITE timeout is -1
# timeout must be an int number, expressed in ms
if timeout == 0.1:
timeout = 100
else:
timeout = int(timeout)

# Wait until any of the events is set to signaled
try:
retval = winutils.win32event.WaitForMultipleObjects(
events,
False, # Wait all
timeout)
except winutils.pywintypes.error:
return [(0, POLLERR)]

rlist, wlist, xlist = select.select(self.rlist, self.wlist, self.xlist,
timeout)
events_dict = {}
for fd in rlist:
events_dict[fd] = events_dict.get(fd, 0) | POLLIN
for fd in wlist:
events_dict[fd] = events_dict.get(fd, 0) | POLLOUT
for fd in xlist:
events_dict[fd] = events_dict.get(fd, 0) | (POLLERR |
POLLHUP |
POLLNVAL)
return list(events_dict.items())
if retval == winutils.winerror.WAIT_TIMEOUT:
return []

return [(events[retval], 0)]
else:
if timeout == -1:
# epoll uses -1 for infinite timeout, select uses None.
timeout = None
else:
timeout = float(timeout) / 1000
rlist, wlist, xlist = select.select(self.rlist,
self.wlist,
self.xlist,
timeout)
events_dict = {}
for fd in rlist:
events_dict[fd] = events_dict.get(fd, 0) | POLLIN
for fd in wlist:
events_dict[fd] = events_dict.get(fd, 0) | POLLOUT
for fd in xlist:
events_dict[fd] = events_dict.get(fd, 0) | (POLLERR |
POLLHUP |
POLLNVAL)
return list(events_dict.items())


SelectPoll = _SelectSelect
Expand Down
31 changes: 27 additions & 4 deletions python/ovs/socket_util.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
import os.path
import random
import socket
import sys

import six
from six.moves import range
Expand All @@ -25,6 +26,10 @@
import ovs.poller
import ovs.vlog

if sys.platform == 'win32':
import ovs.winutils as winutils
import win32file

vlog = ovs.vlog.Vlog("socket_util")


Expand Down Expand Up @@ -158,7 +163,17 @@ def make_unix_socket(style, nonblock, bind_path, connect_path, short=False):

def check_connection_completion(sock):
p = ovs.poller.SelectPoll()
p.register(sock, ovs.poller.POLLOUT)
if sys.platform == "win32":
event = winutils.get_new_event(None, False, True, None)
# Receive notification of readiness for writing, of completed
# connection or multipoint join operation, and of socket closure.
win32file.WSAEventSelect(sock, event,
win32file.FD_WRITE |
win32file.FD_CONNECT |
win32file.FD_CLOSE)
p.register(event, ovs.poller.POLLOUT)
else:
p.register(sock, ovs.poller.POLLOUT)
pfds = p.poll(0)
if len(pfds) == 1:
revents = pfds[0][1]
Expand Down Expand Up @@ -228,7 +243,12 @@ def inet_open_active(style, target, default_port, dscp):
try:
sock.connect(address)
except socket.error as e:
if get_exception_errno(e) != errno.EINPROGRESS:
error = get_exception_errno(e)
if sys.platform == 'win32' and error == errno.WSAEWOULDBLOCK:
# WSAEWOULDBLOCK would be the equivalent on Windows
# for EINPROGRESS on Unix.
error = errno.EINPROGRESS
if error != errno.EINPROGRESS:
raise
return 0, sock
except socket.error as e:
Expand Down Expand Up @@ -257,9 +277,12 @@ def get_null_fd():
global null_fd
if null_fd < 0:
try:
null_fd = os.open("/dev/null", os.O_RDWR)
# os.devnull ensures compatibility with Windows, returns
# '/dev/null' for Unix and 'nul' for Windows
null_fd = os.open(os.devnull, os.O_RDWR)
except OSError as e:
vlog.err("could not open /dev/null: %s" % os.strerror(e.errno))
vlog.err("could not open %s: %s" % (os.devnull,
os.strerror(e.errno)))
return -e.errno
return null_fd

Expand Down
Loading

0 comments on commit 03947eb

Please sign in to comment.