1 # Copyright (c) 2010, 2011, 2012 Nicira, Inc.
3 # Licensed under the Apache License, Version 2.0 (the "License");
4 # you may not use this file except in compliance with the License.
5 # You may obtain a copy of the License at:
7 # http://www.apache.org/licenses/LICENSE-2.0
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 # See the License for the specific language governing permissions and
13 # limitations under the License.
21 import ovs
.socket_util
27 from OpenSSL
import SSL
31 if sys
.platform
== 'win32':
32 import ovs
.winutils
as winutils
38 vlog
= ovs
.vlog
.Vlog("stream")
41 def stream_or_pstream_needs_probes(name
):
42 """ True if the stream or pstream specified by 'name' needs periodic probes
43 to verify connectivity. For [p]streams which need probes, it can take a
44 long time to notice the connection was dropped. Returns False if probes
45 aren't needed, and None if 'name' is invalid"""
47 cls
= Stream
._find
_method
(name
)
49 return cls
.needs_probes()
50 elif PassiveStream
.is_valid_name(name
):
51 return PassiveStream
.needs_probes(name
)
57 """Bidirectional byte stream. Unix domain sockets, tcp and ssl
65 # Kinds of events that one might wait for.
66 W_CONNECT
= 0 # Connect complete (success or failure).
67 W_RECV
= 1 # Data received.
68 W_SEND
= 2 # Send buffer room available.
72 _SSL_private_key_file
= None
73 _SSL_certificate_file
= None
74 _SSL_ca_cert_file
= None
77 _write
= None # overlapped for write operation
78 _read
= None # overlapped for read operation
79 _write_pending
= False
81 _retry_connect
= False
84 def register_method(method
, cls
):
85 Stream
._SOCKET
_METHODS
[method
+ ":"] = cls
88 def _find_method(name
):
89 for method
, cls
in six
.iteritems(Stream
._SOCKET
_METHODS
):
90 if name
.startswith(method
):
95 def is_valid_name(name
):
96 """Returns True if 'name' is a stream name in the form "TYPE:ARGS" and
97 TYPE is a supported stream type ("unix:", "tcp:" and "ssl:"),
99 return bool(Stream
._find
_method
(name
))
101 def __init__(self
, socket
, name
, status
, pipe
=None, is_server
=False):
104 if sys
.platform
== 'win32':
106 # Flag to check if fd is a server HANDLE. In the case of a
107 # server handle we have to issue a disconnect before closing
109 self
._server
= is_server
110 suffix
= name
.split(":", 1)[1]
111 suffix
= ovs
.util
.abs_file_name(ovs
.dirs
.RUNDIR
, suffix
)
112 self
._pipename
= winutils
.get_pipe_name(suffix
)
113 self
._read
= pywintypes
.OVERLAPPED()
114 self
._read
.hEvent
= winutils
.get_new_event()
115 self
._write
= pywintypes
.OVERLAPPED()
116 self
._write
.hEvent
= winutils
.get_new_event()
118 self
._wevent
= winutils
.get_new_event(bManualReset
=False,
122 if status
== errno
.EAGAIN
:
123 self
.state
= Stream
.__S
_CONNECTING
125 self
.state
= Stream
.__S
_CONNECTED
127 self
.state
= Stream
.__S
_DISCONNECTED
131 # Default value of dscp bits for connection between controller and manager.
132 # Value of IPTOS_PREC_INTERNETCONTROL = 0xc0 which is defined
133 # in <netinet/ip.h> is used.
134 IPTOS_PREC_INTERNETCONTROL
= 0xc0
135 DSCP_DEFAULT
= IPTOS_PREC_INTERNETCONTROL
>> 2
138 def open(name
, dscp
=DSCP_DEFAULT
):
139 """Attempts to connect a stream to a remote peer. 'name' is a
140 connection name in the form "TYPE:ARGS", where TYPE is an active stream
141 class's name and ARGS are stream class-specific. The supported TYPEs
142 include "unix", "tcp", and "ssl".
144 Returns (error, stream): on success 'error' is 0 and 'stream' is the
145 new Stream, on failure 'error' is a positive errno value and 'stream'
148 Never returns errno.EAGAIN or errno.EINPROGRESS. Instead, returns 0
149 and a new Stream. The connect() method can be used to check for
150 successful connection completion."""
151 cls
= Stream
._find
_method
(name
)
153 return errno
.EAFNOSUPPORT
, None
155 suffix
= name
.split(":", 1)[1]
156 if name
.startswith("unix:"):
157 suffix
= ovs
.util
.abs_file_name(ovs
.dirs
.RUNDIR
, suffix
)
158 if sys
.platform
== 'win32':
159 pipename
= winutils
.get_pipe_name(suffix
)
161 if len(suffix
) > 255:
162 # Return invalid argument if the name is too long
163 return errno
.ENOENT
, None
166 # In case of "unix:" argument, the assumption is that
167 # there is a file created in the path (suffix).
168 open(suffix
, 'r').close()
170 return errno
.ENOENT
, None
173 npipe
= winutils
.create_file(pipename
)
175 winutils
.set_pipe_mode(npipe
,
176 win32pipe
.PIPE_READMODE_BYTE
)
177 except pywintypes
.error
:
178 return errno
.ENOENT
, None
179 except pywintypes
.error
as e
:
180 if e
.winerror
== winutils
.winerror
.ERROR_PIPE_BUSY
:
181 # Pipe is busy, set the retry flag to true and retry
182 # again during the connect function.
183 Stream
.retry_connect
= True
184 return 0, cls(None, name
, errno
.EAGAIN
,
185 pipe
=win32file
.INVALID_HANDLE_VALUE
,
187 return errno
.ENOENT
, None
188 return 0, cls(None, name
, 0, pipe
=npipe
, is_server
=False)
190 error
, sock
= cls
._open
(suffix
, dscp
)
194 err
= ovs
.socket_util
.check_connection_completion(sock
)
195 if err
== errno
.EAGAIN
or err
== errno
.EINPROGRESS
:
196 status
= errno
.EAGAIN
202 return err
, cls(sock
, name
, status
)
205 def _open(suffix
, dscp
):
206 raise NotImplementedError("This method must be overrided by subclass")
209 def open_block(error_stream
, timeout
=None):
210 """Blocks until a Stream completes its connection attempt, either
211 succeeding or failing, but no more than 'timeout' milliseconds.
212 (error, stream) should be the tuple returned by Stream.open().
213 Negative value of 'timeout' means infinite waiting.
214 Returns a tuple of the same form.
217 error, stream = Stream.open_block(Stream.open("unix:/tmp/socket"))"""
219 # Py3 doesn't support tuple parameter unpacking - PEP 3113
220 error
, stream
= error_stream
223 if timeout
is not None and timeout
>= 0:
224 deadline
= ovs
.timeval
.msec() + timeout
226 error
= stream
.connect()
227 if sys
.platform
== 'win32' and error
== errno
.WSAEWOULDBLOCK
:
228 # WSAEWOULDBLOCK would be the equivalent on Windows
229 # for EAGAIN on Unix.
231 if error
!= errno
.EAGAIN
:
233 if deadline
is not None and ovs
.timeval
.msec() > deadline
:
234 error
= errno
.ETIMEDOUT
237 poller
= ovs
.poller
.Poller()
238 stream
.run_wait(poller
)
239 stream
.connect_wait(poller
)
240 if deadline
is not None:
241 poller
.timer_wait_until(deadline
)
243 if stream
.socket
is not None:
244 assert error
!= errno
.EINPROGRESS
252 if self
.socket
is not None:
254 if self
.pipe
is not None:
256 # Flush the pipe to allow the client to read the pipe
257 # before disconnecting.
258 win32pipe
.FlushFileBuffers(self
.pipe
)
259 win32pipe
.DisconnectNamedPipe(self
.pipe
)
260 winutils
.close_handle(self
.pipe
, vlog
.warn
)
261 winutils
.close_handle(self
._read
.hEvent
, vlog
.warn
)
262 winutils
.close_handle(self
._write
.hEvent
, vlog
.warn
)
264 def __scs_connecting(self
):
265 if self
.socket
is not None:
266 retval
= ovs
.socket_util
.check_connection_completion(self
.socket
)
267 assert retval
!= errno
.EINPROGRESS
268 elif sys
.platform
== 'win32':
269 if self
.retry_connect
:
271 self
.pipe
= winutils
.create_file(self
._pipename
)
272 self
._retry
_connect
= False
274 except pywintypes
.error
as e
:
275 if e
.winerror
== winutils
.winerror
.ERROR_PIPE_BUSY
:
276 retval
= errno
.EAGAIN
278 self
._retry
_connect
= False
279 retval
= errno
.ENOENT
281 # If retry_connect is false, it means it's already
282 # connected so we can set the value of retval to 0
286 self
.state
= Stream
.__S
_CONNECTED
287 elif retval
!= errno
.EAGAIN
:
288 self
.state
= Stream
.__S
_DISCONNECTED
292 """Tries to complete the connection on this stream. If the connection
293 is complete, returns 0 if the connection was successful or a positive
294 errno value if it failed. If the connection is still in progress,
295 returns errno.EAGAIN."""
297 if self
.state
== Stream
.__S
_CONNECTING
:
298 self
.__scs
_connecting
()
300 if self
.state
== Stream
.__S
_CONNECTING
:
302 elif self
.state
== Stream
.__S
_CONNECTED
:
305 assert self
.state
== Stream
.__S
_DISCONNECTED
309 """Tries to receive up to 'n' bytes from this stream. Returns a
310 (error, string) tuple:
312 - If successful, 'error' is zero and 'string' contains between 1
313 and 'n' bytes of data.
315 - On error, 'error' is a positive errno value.
317 - If the connection has been closed in the normal fashion or if 'n'
318 is 0, the tuple is (0, "").
320 The recv function will not block waiting for data to arrive. If no
321 data have been received, it returns (errno.EAGAIN, "") immediately."""
323 retval
= self
.connect()
329 if sys
.platform
== 'win32' and self
.socket
is None:
330 return self
.__recv
_windows
(n
)
333 return (0, self
.socket
.recv(n
))
334 except socket
.error
as e
:
335 return (ovs
.socket_util
.get_exception_errno(e
), "")
337 def __recv_windows(self
, n
):
338 if self
._read
_pending
:
340 nBytesRead
= winutils
.get_overlapped_result(self
.pipe
,
343 self
._read
_pending
= False
344 except pywintypes
.error
as e
:
345 if e
.winerror
== winutils
.winerror
.ERROR_IO_INCOMPLETE
:
346 # The operation is still pending, try again
347 self
._read
_pending
= True
348 return (errno
.EAGAIN
, "")
349 elif e
.winerror
in winutils
.pipe_disconnected_errors
:
350 # If the pipe was disconnected, return 0.
353 return (errno
.EINVAL
, "")
355 (errCode
, self
._read
_buffer
) = winutils
.read_file(self
.pipe
,
359 if errCode
== winutils
.winerror
.ERROR_IO_PENDING
:
360 self
._read
_pending
= True
361 return (errno
.EAGAIN
, "")
362 elif errCode
in winutils
.pipe_disconnected_errors
:
363 # If the pipe was disconnected, return 0.
369 nBytesRead
= winutils
.get_overlapped_result(self
.pipe
,
372 winutils
.win32event
.SetEvent(self
._read
.hEvent
)
373 except pywintypes
.error
as e
:
374 if e
.winerror
in winutils
.pipe_disconnected_errors
:
375 # If the pipe was disconnected, return 0.
378 return (e
.winerror
, "")
380 recvBuffer
= self
._read
_buffer
[:nBytesRead
]
381 # recvBuffer will have the type memoryview in Python3.
382 # We can use bytes to convert it to type bytes which works on
383 # both Python2 and Python3.
384 return (0, bytes(recvBuffer
))
387 """Tries to send 'buf' on this stream.
389 If successful, returns the number of bytes sent, between 1 and
390 len(buf). 0 is only a valid return value if len(buf) is 0.
392 On error, returns a negative errno value.
394 Will not block. If no bytes can be immediately accepted for
395 transmission, returns -errno.EAGAIN immediately."""
397 retval
= self
.connect()
403 # We must have bytes for sending.
404 if isinstance(buf
, six
.text_type
):
405 buf
= buf
.encode('utf-8')
407 if sys
.platform
== 'win32' and self
.socket
is None:
408 return self
.__send
_windows
(buf
)
411 return self
.socket
.send(buf
)
412 except socket
.error
as e
:
413 return -ovs
.socket_util
.get_exception_errno(e
)
415 def __send_windows(self
, buf
):
416 if self
._write
_pending
:
418 nBytesWritten
= winutils
.get_overlapped_result(self
.pipe
,
421 self
._write
_pending
= False
422 except pywintypes
.error
as e
:
423 if e
.winerror
== winutils
.winerror
.ERROR_IO_INCOMPLETE
:
424 # The operation is still pending, try again
425 self
._read
_pending
= True
427 elif e
.winerror
in winutils
.pipe_disconnected_errors
:
428 # If the pipe was disconnected, return connection reset.
429 return -errno
.ECONNRESET
433 (errCode
, nBytesWritten
) = winutils
.write_file(self
.pipe
,
437 if errCode
== winutils
.winerror
.ERROR_IO_PENDING
:
438 self
._write
_pending
= True
440 if (not nBytesWritten
and
441 errCode
in winutils
.pipe_disconnected_errors
):
442 # If the pipe was disconnected, return connection reset.
443 return -errno
.ECONNRESET
449 def run_wait(self
, poller
):
452 def wait(self
, poller
, wait
):
453 assert wait
in (Stream
.W_CONNECT
, Stream
.W_RECV
, Stream
.W_SEND
)
455 if self
.state
== Stream
.__S
_DISCONNECTED
:
456 poller
.immediate_wake()
459 if self
.state
== Stream
.__S
_CONNECTING
:
460 wait
= Stream
.W_CONNECT
462 if sys
.platform
== 'win32':
463 self
.__wait
_windows
(poller
, wait
)
466 if wait
== Stream
.W_RECV
:
467 poller
.fd_wait(self
.socket
, ovs
.poller
.POLLIN
)
469 poller
.fd_wait(self
.socket
, ovs
.poller
.POLLOUT
)
471 def __wait_windows(self
, poller
, wait
):
472 if self
.socket
is not None:
473 if wait
== Stream
.W_RECV
:
474 mask
= (win32file
.FD_READ |
475 win32file
.FD_ACCEPT |
477 event
= ovs
.poller
.POLLIN
479 mask
= (win32file
.FD_WRITE |
480 win32file
.FD_CONNECT |
482 event
= ovs
.poller
.POLLOUT
485 win32file
.WSAEventSelect(self
.socket
,
488 except pywintypes
.error
as e
:
489 vlog
.err("failed to associate events with socket: %s"
491 poller
.fd_wait(self
._wevent
, event
)
493 if wait
== Stream
.W_RECV
:
495 poller
.fd_wait(self
._read
.hEvent
, ovs
.poller
.POLLIN
)
496 elif wait
== Stream
.W_SEND
:
498 poller
.fd_wait(self
._write
.hEvent
, ovs
.poller
.POLLOUT
)
499 elif wait
== Stream
.W_CONNECT
:
502 def connect_wait(self
, poller
):
503 self
.wait(poller
, Stream
.W_CONNECT
)
505 def recv_wait(self
, poller
):
506 self
.wait(poller
, Stream
.W_RECV
)
508 def send_wait(self
, poller
):
509 self
.wait(poller
, Stream
.W_SEND
)
512 # Don't delete the file: we might have forked.
513 if self
.socket
is not None:
515 if self
.pipe
is not None:
516 # Check if there are any remaining valid handles and close them
518 winutils
.close_handle(self
.pipe
)
519 if self
._read
.hEvent
:
520 winutils
.close_handle(self
._read
.hEvent
)
521 if self
._write
.hEvent
:
522 winutils
.close_handle(self
._write
.hEvent
)
525 def ssl_set_private_key_file(file_name
):
526 Stream
._SSL
_private
_key
_file
= file_name
529 def ssl_set_certificate_file(file_name
):
530 Stream
._SSL
_certificate
_file
= file_name
533 def ssl_set_ca_cert_file(file_name
):
534 Stream
._SSL
_ca
_cert
_file
= file_name
537 class PassiveStream(object):
539 connect
= None # overlapped for read operation
540 connect_pending
= False
543 def needs_probes(name
):
544 return False if name
.startswith("punix:") else True
547 def is_valid_name(name
):
548 """Returns True if 'name' is a passive stream name in the form
549 "TYPE:ARGS" and TYPE is a supported passive stream type (currently
550 "punix:" or "ptcp"), otherwise False."""
551 return name
.startswith("punix:") | name
.startswith("ptcp:")
553 def __init__(self
, sock
, name
, bind_path
, pipe
=None):
558 self
.connect
= pywintypes
.OVERLAPPED()
559 self
.connect
.hEvent
= winutils
.get_new_event()
560 self
.connect_pending
= False
561 suffix
= name
.split(":", 1)[1]
562 suffix
= ovs
.util
.abs_file_name(ovs
.dirs
.RUNDIR
, suffix
)
563 self
._pipename
= winutils
.get_pipe_name(suffix
)
565 self
.bind_path
= bind_path
569 """Attempts to start listening for remote stream connections. 'name'
570 is a connection name in the form "TYPE:ARGS", where TYPE is an passive
571 stream class's name and ARGS are stream class-specific. Currently the
572 supported values for TYPE are "punix" and "ptcp".
574 Returns (error, pstream): on success 'error' is 0 and 'pstream' is the
575 new PassiveStream, on failure 'error' is a positive errno value and
576 'pstream' is None."""
577 if not PassiveStream
.is_valid_name(name
):
578 return errno
.EAFNOSUPPORT
, None
581 if name
.startswith("punix:"):
582 bind_path
= ovs
.util
.abs_file_name(ovs
.dirs
.RUNDIR
, bind_path
)
583 if sys
.platform
!= 'win32':
584 error
, sock
= ovs
.socket_util
.make_unix_socket(
585 socket
.SOCK_STREAM
, True, bind_path
, None)
589 # Branch used only on Windows
591 open(bind_path
, 'w').close()
593 return errno
.ENOENT
, None
595 pipename
= winutils
.get_pipe_name(bind_path
)
596 if len(pipename
) > 255:
597 # Return invalid argument if the name is too long
598 return errno
.ENOENT
, None
600 npipe
= winutils
.create_named_pipe(pipename
)
602 return errno
.ENOENT
, None
603 return 0, PassiveStream(None, name
, bind_path
, pipe
=npipe
)
605 elif name
.startswith("ptcp:"):
606 sock
= socket
.socket(socket
.AF_INET
, socket
.SOCK_STREAM
)
607 sock
.setsockopt(socket
.SOL_SOCKET
, socket
.SO_REUSEADDR
, 1)
608 remote
= name
.split(':')
609 sock
.bind((remote
[1], int(remote
[2])))
612 raise Exception('Unknown connection string')
616 except socket
.error
as e
:
617 vlog
.err("%s: listen: %s" % (name
, os
.strerror(e
.error
)))
621 return 0, PassiveStream(sock
, name
, bind_path
)
624 """Closes this PassiveStream."""
625 if self
.socket
is not None:
627 if self
.pipe
is not None:
628 winutils
.close_handle(self
.pipe
, vlog
.warn
)
629 winutils
.close_handle(self
.connect
.hEvent
, vlog
.warn
)
630 if self
.bind_path
is not None:
631 ovs
.fatal_signal
.unlink_file_now(self
.bind_path
)
632 self
.bind_path
= None
635 """Tries to accept a new connection on this passive stream. Returns
636 (error, stream): if successful, 'error' is 0 and 'stream' is the new
637 Stream object, and on failure 'error' is a positive errno value and
640 Will not block waiting for a connection. If no connection is ready to
641 be accepted, returns (errno.EAGAIN, None) immediately."""
642 if sys
.platform
== 'win32' and self
.socket
is None:
643 return self
.__accept
_windows
()
646 sock
, addr
= self
.socket
.accept()
647 ovs
.socket_util
.set_nonblocking(sock
)
648 if (sys
.platform
!= 'win32' and sock
.family
== socket
.AF_UNIX
):
649 return 0, Stream(sock
, "unix:%s" % addr
, 0)
650 return 0, Stream(sock
, 'ptcp:%s:%s' % (addr
[0],
652 except socket
.error
as e
:
653 error
= ovs
.socket_util
.get_exception_errno(e
)
654 if sys
.platform
== 'win32' and error
== errno
.WSAEWOULDBLOCK
:
655 # WSAEWOULDBLOCK would be the equivalent on Windows
656 # for EAGAIN on Unix.
658 if error
!= errno
.EAGAIN
:
660 vlog
.dbg("accept: %s" % os
.strerror(error
))
663 def __accept_windows(self
):
664 if self
.connect_pending
:
666 winutils
.get_overlapped_result(self
.pipe
, self
.connect
, False)
667 except pywintypes
.error
as e
:
668 if e
.winerror
== winutils
.winerror
.ERROR_IO_INCOMPLETE
:
669 # The operation is still pending, try again
670 self
.connect_pending
= True
671 return errno
.EAGAIN
, None
674 win32pipe
.DisconnectNamedPipe(self
.pipe
)
675 return errno
.EINVAL
, None
676 self
.connect_pending
= False
678 error
= winutils
.connect_named_pipe(self
.pipe
, self
.connect
)
680 if error
== winutils
.winerror
.ERROR_IO_PENDING
:
681 self
.connect_pending
= True
682 return errno
.EAGAIN
, None
683 elif error
!= winutils
.winerror
.ERROR_PIPE_CONNECTED
:
685 win32pipe
.DisconnectNamedPipe(self
.pipe
)
686 self
.connect_pending
= False
687 return errno
.EINVAL
, None
689 win32event
.SetEvent(self
.connect
.hEvent
)
691 npipe
= winutils
.create_named_pipe(self
._pipename
)
693 return errno
.ENOENT
, None
697 winutils
.win32event
.ResetEvent(self
.connect
.hEvent
)
698 return 0, Stream(None, self
.name
, 0, pipe
=old_pipe
)
700 def wait(self
, poller
):
701 if sys
.platform
!= 'win32' or self
.socket
is not None:
702 poller
.fd_wait(self
.socket
, ovs
.poller
.POLLIN
)
704 poller
.fd_wait(self
.connect
.hEvent
, ovs
.poller
.POLLIN
)
707 # Don't delete the file: we might have forked.
708 if self
.socket
is not None:
710 if self
.pipe
is not None:
711 # Check if there are any remaining valid handles and close them
713 winutils
.close_handle(self
.pipe
)
714 if self
._connect
.hEvent
:
715 winutils
.close_handle(self
._read
.hEvent
)
720 Active %s connection methods:
721 unix:FILE Unix domain socket named FILE
722 tcp:HOST:PORT TCP socket to HOST with port no of PORT
723 ssl:HOST:PORT SSL socket to HOST with port no of PORT
725 Passive %s connection methods:
726 punix:FILE Listen on Unix domain socket FILE""" % (name
, name
)
729 class UnixStream(Stream
):
735 def _open(suffix
, dscp
):
736 connect_path
= suffix
737 return ovs
.socket_util
.make_unix_socket(socket
.SOCK_STREAM
,
738 True, None, connect_path
)
741 Stream
.register_method("unix", UnixStream
)
744 class TCPStream(Stream
):
750 def _open(suffix
, dscp
):
751 error
, sock
= ovs
.socket_util
.inet_open_active(socket
.SOCK_STREAM
,
755 sock
.setsockopt(socket
.IPPROTO_TCP
, socket
.TCP_NODELAY
, 1)
756 except socket
.error
as e
:
758 return ovs
.socket_util
.get_exception_errno(e
), None
762 Stream
.register_method("tcp", TCPStream
)
765 class SSLStream(Stream
):
771 def verify_cb(conn
, cert
, errnum
, depth
, ok
):
775 def _open(suffix
, dscp
):
776 error
, sock
= TCPStream
._open
(suffix
, dscp
)
780 # Create an SSL context
781 ctx
= SSL
.Context(SSL
.SSLv23_METHOD
)
782 ctx
.set_verify(SSL
.VERIFY_PEER
, SSLStream
.verify_cb
)
783 ctx
.set_options(SSL
.OP_NO_SSLv2 | SSL
.OP_NO_SSLv3
)
784 # If the client has not set the SSL configuration files
785 # exception would be raised.
786 ctx
.use_privatekey_file(Stream
._SSL
_private
_key
_file
)
787 ctx
.use_certificate_file(Stream
._SSL
_certificate
_file
)
788 ctx
.load_verify_locations(Stream
._SSL
_ca
_cert
_file
)
790 ssl_sock
= SSL
.Connection(ctx
, sock
)
791 ssl_sock
.set_connect_state()
792 return error
, ssl_sock
795 retval
= super(SSLStream
, self
).connect()
800 # TCP Connection is successful. Now do the SSL handshake
802 self
.socket
.do_handshake()
803 except SSL
.WantReadError
:
805 except SSL
.SysCallError
as e
:
806 return ovs
.socket_util
.get_exception_errno(e
)
812 return super(SSLStream
, self
).recv(n
)
813 except SSL
.WantReadError
:
814 return (errno
.EAGAIN
, "")
815 except SSL
.SysCallError
as e
:
816 return (ovs
.socket_util
.get_exception_errno(e
), "")
817 except SSL
.ZeroReturnError
:
822 return super(SSLStream
, self
).send(buf
)
823 except SSL
.WantWriteError
:
825 except SSL
.SysCallError
as e
:
826 return -ovs
.socket_util
.get_exception_errno(e
)
830 # Register SSL only if the OpenSSL module is available
831 Stream
.register_method("ssl", SSLStream
)