Issue #23197, asyncio: On SSL handshake failure, check if the waiter is
cancelled before setting its exception.

* Add unit tests for this case.
* Cleanup also sslproto.py
diff --git a/Lib/asyncio/selector_events.py b/Lib/asyncio/selector_events.py
index b2f29c7..ca86264 100644
--- a/Lib/asyncio/selector_events.py
+++ b/Lib/asyncio/selector_events.py
@@ -750,7 +750,7 @@
             self._loop.remove_reader(self._sock_fd)
             self._loop.remove_writer(self._sock_fd)
             self._sock.close()
-            if self._waiter is not None:
+            if self._waiter is not None and not self._waiter.cancelled():
                 self._waiter.set_exception(exc)
             if isinstance(exc, Exception):
                 return
diff --git a/Lib/asyncio/sslproto.py b/Lib/asyncio/sslproto.py
index 987c158..541e252 100644
--- a/Lib/asyncio/sslproto.py
+++ b/Lib/asyncio/sslproto.py
@@ -530,10 +530,11 @@
         self._in_handshake = False
 
         sslobj = self._sslpipe.ssl_object
-        peercert = None if handshake_exc else sslobj.getpeercert()
         try:
             if handshake_exc is not None:
                 raise handshake_exc
+
+            peercert = sslobj.getpeercert()
             if not hasattr(self._sslcontext, 'check_hostname'):
                 # Verify hostname if requested, Python 3.4+ uses check_hostname
                 # and checks the hostname in do_handshake()
@@ -551,7 +552,7 @@
                                    self, exc_info=True)
             self._transport.close()
             if isinstance(exc, Exception):
-                if self._waiter is not None:
+                if self._waiter is not None and not self._waiter.cancelled():
                     self._waiter.set_exception(exc)
                 return
             else: