Repository: aaugustin/websockets
Pull request #612 (2019-05-12 01:28:30)

Add a logo.


Patch:
diff --git a/docs/changelog.rst b/docs/changelog.rst
index 9618c1d..ee407d1 100644
--- a/docs/changelog.rst
+++ b/docs/changelog.rst
@@ -31,6 +31,11 @@ Also:
   :meth:`~protocol.WebSocketCommonProtocol.pong` support bytes-like types
   :class:`bytearray` and :class:`memoryview` in addition to :class:`bytes`.
 
+* Added :exc:`~exceptions.ConnectionClosedOK` and
+  :exc:`~exceptions.ConnectionClosedError` subclasses of
+  :exc:`~exceptions.ConnectionClosed` to tell apart normal connection
+  termination from errors.
+
 * :func:`~client.connect()` handles redirects from the server during the
   handshake.
 
diff --git a/logo/horizontal.svg b/logo/horizontal.svg
new file mode 100644
index 0000000..766c706
--- /dev/null
+++ b/logo/horizontal.svg
@@ -0,0 +1,156 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 16.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" [
+	<!ENTITY ns_extend "http://ns.adobe.com/Extensibility/1.0/">
+	<!ENTITY ns_ai "http://ns.adobe.com/AdobeIllustrator/10.0/">
+	<!ENTITY ns_graphs "http://ns.adobe.com/Graphs/1.0/">
+	<!ENTITY ns_vars "http://ns.adobe.com/Variables/1.0/">
+	<!ENTITY ns_imrep "http://ns.adobe.com/ImageReplacement/1.0/">
+	<!ENTITY ns_sfw "http://ns.adobe.com/SaveForWeb/1.0/">
+	<!ENTITY ns_custom "http://ns.adobe.com/GenericCustomNamespace/1.0/">
+	<!ENTITY ns_adobe_xpath "http://ns.adobe.com/XPath/1.0/">
+]>
+<svg version="1.1" id="Layer_1" xmlns:x="&ns_extend;" xmlns:i="&ns_ai;" xmlns:graph="&ns_graphs;"
+	 xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="1183.991px"
+	 height="234.005px" viewBox="0 0 1183.991 234.005" enable-background="new 0 0 1183.991 234.005" xml:space="preserve">
+<metadata>
+	<sfw  xmlns="&ns_sfw;">
+		<slices></slices>
+		<sliceSourceBounds  width="1183.991" height="234.004" y="-855.686" x="329.2" bottomLeftOrigin="true"></sliceSourceBounds>
+	</sfw>
+</metadata>
+<g>
+	<g>
+		<g>
+			<path fill="#FFC331" d="M300.236,178.605c0,5.227,1.839,9.678,5.519,13.357c3.679,3.682,8.133,5.52,13.359,5.52
+				c5.226,0,9.679-1.838,13.358-5.52c3.68-3.68,5.52-8.131,5.52-13.357v-43.916c0-2.666,0.959-4.959,2.879-6.877
+				c1.921-1.922,4.213-2.883,6.88-2.883h0.161c2.718,0,4.984,0.961,6.798,2.883c1.92,1.918,2.88,4.211,2.88,6.877v43.916
+				c0,5.227,1.84,9.678,5.521,13.357c3.679,3.682,8.13,5.52,13.357,5.52c5.28,0,9.759-1.838,13.438-5.52
+				c3.681-3.68,5.521-8.131,5.521-13.357v-43.916c0-2.666,0.958-4.959,2.879-6.877c1.811-1.922,4.078-2.883,6.799-2.883h0.159
+				c2.667,0,4.96,0.961,6.88,2.883c1.867,1.918,2.8,4.211,2.8,6.877v43.916c0,10.613-3.76,19.676-11.278,27.197
+				c-7.52,7.518-16.586,11.279-27.197,11.279c-12.693,0-22.237-4.213-28.639-12.639c-6.451,8.426-16.025,12.639-28.716,12.639
+				c-10.612,0-19.679-3.762-27.197-11.279c-7.52-7.521-11.279-16.584-11.279-27.197v-43.916c0-2.666,0.959-4.959,2.88-6.877
+				c1.919-1.922,4.186-2.883,6.798-2.883h0.241c2.611,0,4.879,0.961,6.801,2.883c1.918,1.918,2.879,4.211,2.879,6.877V178.605z"/>
+			<path fill="#FFC331" d="M516.454,151.809c0.642,1.332,0.961,2.691,0.961,4.078c0,1.121-0.213,2.242-0.64,3.359
+				c-0.908,2.508-2.613,4.32-5.12,5.441c-7.467,3.359-17.277,7.785-29.438,13.277c-15.092,6.826-23.944,10.854-26.557,12.08
+				c4.052,5.119,10.371,7.678,18.958,7.678c5.705,0,10.879-1.678,15.518-5.039c4.532-3.307,7.706-7.572,9.52-12.799
+				c1.548-4.371,4.641-6.561,9.28-6.561c3.305,0,5.946,1.391,7.919,4.16c1.226,1.709,1.84,3.494,1.84,5.361
+				c0,1.119-0.214,2.266-0.64,3.438c-3.146,9.121-8.668,16.479-16.559,22.08c-7.999,5.813-16.959,8.719-26.878,8.719
+				c-12.692,0-23.545-4.506-32.556-13.518c-9.013-9.014-13.52-19.865-13.52-32.559c0-12.691,4.507-23.543,13.52-32.559
+				c9.011-9.01,19.863-13.518,32.556-13.518c9.171,0,17.545,2.508,25.117,7.52C507.255,137.357,512.828,143.807,516.454,151.809z
+				 M474.619,144.686c-7.36,0-13.626,2.59-18.799,7.762c-5.119,5.174-7.68,11.441-7.68,18.799v0.559l44.717-20.076
+				C488.91,147.035,482.831,144.686,474.619,144.686z"/>
+			<path fill="#FFC331" d="M543.013,92.133c2.611,0,4.877,0.936,6.799,2.801c1.92,1.918,2.881,4.213,2.881,6.879v31.117
+				c6.024-5.332,14.851-8,26.476-8c12.692,0,23.545,4.508,32.557,13.518c9.013,9.016,13.52,19.867,13.52,32.559
+				c0,12.693-4.507,23.545-13.52,32.559c-9.012,9.012-19.864,13.518-32.557,13.518s-23.517-4.479-32.476-13.439
+				c-9.014-8.904-13.547-19.705-13.6-32.396v-69.434c0-2.666,0.96-4.961,2.88-6.879c1.92-1.865,4.186-2.801,6.799-2.801H543.013z
+				 M579.168,144.686c-7.358,0-13.626,2.59-18.799,7.762c-5.118,5.174-7.677,11.441-7.677,18.799c0,7.307,2.559,13.545,7.677,18.717
+				c5.173,5.174,11.44,7.76,18.799,7.76c7.307,0,13.545-2.586,18.719-7.76c5.171-5.172,7.759-11.41,7.759-18.717
+				c0-7.357-2.588-13.625-7.759-18.799C592.713,147.275,586.475,144.686,579.168,144.686z"/>
+			<g>
+				<g>
+					<path fill="#366994" d="M663.64,144.529c-2.348,0-4.318,0.799-5.92,2.398c-1.6,1.654-2.398,3.627-2.398,5.918
+						c0,3.201,1.545,5.602,4.639,7.201c1.066,0.586,5.52,1.92,13.359,4c6.346,1.814,11.064,4.188,14.158,7.117
+						c4.426,4.215,6.639,10.215,6.639,18c0,7.68-2.719,14.266-8.158,19.758c-5.494,5.441-12.08,8.16-19.758,8.16h-20.879
+						c-2.613,0-4.878-0.961-6.798-2.881c-1.921-1.813-2.881-4.08-2.881-6.799v-0.162c0-2.664,0.96-4.957,2.881-6.877
+						c1.92-1.92,4.185-2.881,6.798-2.881h21.68c2.344,0,4.318-0.799,5.916-2.398c1.602-1.602,2.4-3.572,2.4-5.92
+						c0-2.932-1.52-5.146-4.559-6.639c-0.799-0.373-5.279-1.705-13.438-4c-6.348-1.865-11.068-4.322-14.16-7.361
+						c-4.426-4.318-6.639-10.424-6.639-18.318c0-7.678,2.721-14.236,8.161-19.676c5.49-5.492,12.078-8.24,19.758-8.24h14.717
+						c2.666,0,4.961,0.961,6.881,2.883c1.92,1.918,2.879,4.211,2.879,6.877v0.16c0,2.719-0.959,4.988-2.879,6.801
+						c-1.92,1.918-4.215,2.879-6.881,2.879H663.64z"/>
+				</g>
+			</g>
+			<g>
+				<g>
+					<path fill="#366994" d="M750.593,124.93c12.689,0,23.543,4.508,32.557,13.518c9.012,9.016,13.518,19.867,13.518,32.559
+						c0,12.693-4.506,23.545-13.518,32.559c-9.014,9.012-19.867,13.518-32.557,13.518c-12.693,0-23.545-4.506-32.557-13.518
+						c-9.014-9.014-13.52-19.865-13.52-32.559c0-12.691,4.506-23.543,13.52-32.559C727.048,129.438,737.899,124.93,750.593,124.93z
+						 M750.593,144.686c-7.361,0-13.627,2.59-18.799,7.762c-5.121,5.174-7.68,11.441-7.68,18.799c0,7.307,2.559,13.545,7.68,18.717
+						c5.172,5.174,11.438,7.76,18.799,7.76c7.305,0,13.545-2.586,18.719-7.76c5.172-5.172,7.758-11.41,7.758-18.717
+						c0-7.357-2.586-13.625-7.758-18.799C764.138,147.275,757.897,144.686,750.593,144.686z"/>
+				</g>
+			</g>
+			<g>
+				<g>
+					<path fill="#366994" d="M867.86,127.09c4.533,1.439,6.801,4.533,6.801,9.279v0.402c0,3.25-1.309,5.836-3.92,7.758
+						c-1.813,1.279-3.682,1.92-5.6,1.92c-1.014,0-2.053-0.162-3.119-0.482c-2.613-0.852-5.307-1.281-8.08-1.281
+						c-7.359,0-13.627,2.59-18.799,7.762c-5.119,5.174-7.68,11.441-7.68,18.799c0,7.307,2.561,13.545,7.68,18.717
+						c5.172,5.174,11.439,7.76,18.799,7.76c2.773,0,5.467-0.426,8.08-1.281c1.012-0.318,2.025-0.479,3.039-0.479
+						c1.971,0,3.867,0.641,5.68,1.922c2.611,1.918,3.92,4.531,3.92,7.838c0,4.693-2.268,7.787-6.801,9.279
+						c-4.479,1.387-9.117,2.08-13.918,2.08c-12.691,0-23.545-4.506-32.557-13.518c-9.014-9.014-13.52-19.865-13.52-32.559
+						c0-12.691,4.506-23.543,13.52-32.559c9.012-9.01,19.865-13.518,32.557-13.518C858.743,124.93,863.382,125.652,867.86,127.09z"
+						/>
+				</g>
+			</g>
+			<g>
+				<g>
+					<path fill="#366994" d="M898.179,92.133c2.609,0,4.877,0.936,6.799,2.801c1.92,1.918,2.879,4.213,2.879,6.879v55.436h3.039
+						c6.826,0,12.771-2.268,17.84-6.803c4.959-4.531,7.783-10.129,8.479-16.795c0.32-2.508,1.387-4.563,3.201-6.16
+						c1.811-1.705,3.971-2.561,6.479-2.561h0.238c2.828,0,5.201,1.068,7.119,3.199c1.707,1.867,2.561,4.027,2.561,6.48
+						c0,0.32-0.027,0.668-0.078,1.039c-1.281,13.387-6.4,23.412-15.359,30.076c4.689,2.881,9.012,7.762,12.959,14.641
+						c4.105,7.094,6.16,14.746,6.16,22.955v4.082c0,2.719-0.961,4.986-2.881,6.799c-1.922,1.92-4.188,2.881-6.801,2.881h-0.24
+						c-2.613,0-4.879-0.961-6.799-2.881c-1.92-1.813-2.879-4.08-2.879-6.799v-4.082c-0.055-7.248-2.641-13.463-7.76-18.637
+						c-5.174-5.121-11.414-7.678-18.719-7.678h-6.559v30.396c0,2.719-0.959,4.986-2.879,6.799c-1.922,1.92-4.189,2.881-6.799,2.881
+						h-0.242c-2.613,0-4.879-0.961-6.799-2.881c-1.92-1.813-2.879-4.08-2.879-6.799v-105.59c0-2.666,0.959-4.961,2.879-6.879
+						c1.92-1.865,4.186-2.801,6.799-2.801H898.179z"/>
+				</g>
+			</g>
+			<g>
+				<g>
+					<path fill="#366994" d="M1059.603,151.809c0.641,1.332,0.961,2.691,0.961,4.078c0,1.121-0.215,2.242-0.641,3.359
+						c-0.908,2.508-2.613,4.32-5.119,5.441c-7.467,3.359-17.279,7.785-29.438,13.277c-15.092,6.826-23.945,10.854-26.559,12.08
+						c4.051,5.119,10.371,7.678,18.959,7.678c5.705,0,10.879-1.678,15.52-5.039c4.531-3.307,7.705-7.572,9.518-12.799
+						c1.547-4.371,4.641-6.561,9.279-6.561c3.307,0,5.945,1.391,7.92,4.16c1.227,1.709,1.838,3.494,1.838,5.361
+						c0,1.119-0.213,2.266-0.639,3.438c-3.146,9.121-8.666,16.479-16.559,22.08c-7.998,5.813-16.959,8.719-26.877,8.719
+						c-12.691,0-23.545-4.506-32.557-13.518c-9.012-9.014-13.52-19.865-13.52-32.559c0-12.691,4.508-23.543,13.52-32.559
+						c9.012-9.01,19.865-13.518,32.557-13.518c9.17,0,17.545,2.508,25.117,7.52C1050.403,137.357,1055.976,143.807,1059.603,151.809
+						z M1017.767,144.686c-7.359,0-13.625,2.59-18.799,7.762c-5.119,5.174-7.678,11.441-7.678,18.799v0.559l44.713-20.076
+						C1032.058,147.035,1025.978,144.686,1017.767,144.686z"/>
+				</g>
+			</g>
+			<g>
+				<g>
+					<path fill="#366994" d="M1086.159,92.133c2.611,0,4.879,0.936,6.799,2.801c1.92,1.918,2.879,4.213,2.879,6.879v23.117h12
+						c2.613,0,4.879,0.961,6.801,2.883c1.92,1.918,2.877,4.211,2.877,6.877v0.16c0,2.719-0.957,4.988-2.877,6.801
+						c-1.922,1.918-4.188,2.879-6.801,2.879h-12v47.434c0,1.547,0.533,2.855,1.602,3.92c1.064,1.068,2.398,1.6,3.998,1.6h6.4
+						c2.613,0,4.879,0.961,6.801,2.881c1.92,1.92,2.877,4.213,2.877,6.877v0.162c0,2.719-0.957,4.986-2.877,6.799
+						c-1.922,1.92-4.188,2.881-6.801,2.881h-6.4c-6.932,0-12.877-2.453-17.838-7.359c-4.908-4.959-7.357-10.881-7.357-17.76v-90.15
+						c0-2.666,0.959-4.961,2.879-6.879c1.92-1.865,4.186-2.801,6.799-2.801H1086.159z"/>
+				</g>
+			</g>
+			<g>
+				<g>
+					<path fill="#366994" d="M1153.515,144.529c-2.348,0-4.318,0.799-5.92,2.398c-1.6,1.654-2.4,3.627-2.4,5.918
+						c0,3.201,1.547,5.602,4.639,7.201c1.066,0.586,5.52,1.92,13.361,4c6.344,1.814,11.064,4.188,14.156,7.117
+						c4.428,4.215,6.641,10.215,6.641,18c0,7.68-2.721,14.266-8.16,19.758c-5.492,5.441-12.078,8.16-19.758,8.16h-20.877
+						c-2.613,0-4.881-0.961-6.801-2.881c-1.918-1.813-2.879-4.08-2.879-6.799v-0.162c0-2.664,0.961-4.957,2.879-6.877
+						c1.92-1.92,4.188-2.881,6.801-2.881h21.678c2.346,0,4.32-0.799,5.918-2.398c1.602-1.602,2.4-3.572,2.4-5.92
+						c0-2.932-1.521-5.146-4.559-6.639c-0.801-0.373-5.281-1.705-13.439-4c-6.348-1.865-11.066-4.322-14.16-7.361
+						c-4.426-4.318-6.639-10.424-6.639-18.318c0-7.678,2.721-14.236,8.16-19.676c5.492-5.492,12.08-8.24,19.758-8.24h14.719
+						c2.666,0,4.961,0.961,6.879,2.883c1.92,1.918,2.881,4.211,2.881,6.877v0.16c0,2.719-0.961,4.988-2.881,6.801
+						c-1.918,1.918-4.213,2.879-6.879,2.879H1153.515z"/>
+				</g>
+			</g>
+		</g>
+	</g>
+	<path fill="#FFC331" d="M152.04,147.17c-0.49,0.084-0.994,0.146-1.52,0.168c-2.756,0.086-4.769-0.66-6.529-2.42l-9.97-9.967
+		l-12.596-12.598l-40.408-40.41c-3.852-3.85-8.221-6.016-12.994-6.439c-2.5-0.223-5.016,0.035-7.445,0.76
+		c-3.635,1.063-6.879,2.998-9.635,5.756c-4.299,4.297-6.574,9.467-6.588,14.949c-0.068,5.572,2.188,10.801,6.512,15.125
+		l62.363,62.367c2.043,2.072,2.982,4.27,2.953,6.914l0.004,0.234c0.059,2.736-0.852,4.889-2.945,6.982
+		c-1.996,1.998-4.271,2.984-7.074,3.1c-2.756,0.086-4.77-0.662-6.531-2.422l-62.971-62.973c-5.846-5.844-13.121-7.861-20.439-5.68
+		c-3.639,1.061-6.879,2.996-9.637,5.754c-4.299,4.299-6.576,9.469-6.588,14.951c-0.063,5.572,2.188,10.803,6.51,15.129
+		l65.148,65.145c9.328,9.328,21.684,13.43,36.711,12.193c14.104-1.148,25.813-6.283,34.795-15.27
+		c8.423-8.422,13.414-18.396,14.897-29.729c11.741-1.893,21.633-6.801,29.459-14.627c4.5-4.5,8.016-9.447,10.545-14.807
+		C182.196,158.906,166.409,154.844,152.04,147.17z"/>
+	<path fill="#366994" d="M202.889,137.385c0.115-14.451-4.967-26.984-15.143-37.277l-40.229-40.229
+		c-0.273-0.271-0.521-0.549-0.77-0.838c-1.664-1.957-2.453-4.031-2.478-6.533c-0.029-2.779,0.952-5.072,3.095-7.209
+		c2.146-2.148,4.32-3.08,7.137-3.02c2.844,0.027,5.188,1.061,7.369,3.242l67.934,67.934l13.582-13.578
+		c1.258-1.021,2.195-1.99,3.227-3.301c6.636-8.455,5.908-20.557-1.693-28.158l-52.969-52.975C181.643,5.141,169.116-0.057,154.764,0
+		c-14.511-0.057-27.067,5.117-37.321,15.371C107.32,25.492,102.15,37.803,102.082,51.92l-0.004,0.16
+		c-0.002,0.189-0.006,0.379-0.006,0.57c-0.102,13.762,4.605,25.828,13.994,35.867c0.451,0.484,0.9,0.965,1.371,1.438l40.083,40.08
+		c2.118,2.117,3.047,4.271,3.02,6.986l0.003,0.236c0.059,2.736-0.853,4.889-2.946,6.984c-1.623,1.619-3.434,2.563-5.557,2.928
+		c14.369,7.674,30.156,11.736,46.027,12.188c3.146-6.666,4.766-13.971,4.82-21.865L202.889,137.385z"/>
+	<path fill="#FFFFFF" d="M223.878,77.83c3.192-3.193,8.368-3.191,11.558,0c3.189,3.189,3.191,8.365-0.002,11.555
+		c-3.188,3.193-8.367,3.193-11.556,0C220.688,86.195,220.685,81.02,223.878,77.83z"/>
+</g>
+</svg>
diff --git a/logo/icon.svg b/logo/icon.svg
new file mode 100644
index 0000000..69592fe
--- /dev/null
+++ b/logo/icon.svg
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 16.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" [
+	<!ENTITY ns_extend "http://ns.adobe.com/Extensibility/1.0/">
+	<!ENTITY ns_ai "http://ns.adobe.com/AdobeIllustrator/10.0/">
+	<!ENTITY ns_graphs "http://ns.adobe.com/Graphs/1.0/">
+	<!ENTITY ns_vars "http://ns.adobe.com/Variables/1.0/">
+	<!ENTITY ns_imrep "http://ns.adobe.com/ImageReplacement/1.0/">
+	<!ENTITY ns_sfw "http://ns.adobe.com/SaveForWeb/1.0/">
+	<!ENTITY ns_custom "http://ns.adobe.com/GenericCustomNamespace/1.0/">
+	<!ENTITY ns_adobe_xpath "http://ns.adobe.com/XPath/1.0/">
+]>
+<svg version="1.1" id="Layer_1" xmlns:x="&ns_extend;" xmlns:i="&ns_ai;" xmlns:graph="&ns_graphs;"
+	 xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="251.145px"
+	 height="234.005px" viewBox="0 0 251.145 234.005" enable-background="new 0 0 251.145 234.005" xml:space="preserve">
+<metadata>
+	<sfw  xmlns="&ns_sfw;">
+		<slices></slices>
+		<sliceSourceBounds  width="251.144" height="234.005" y="-794.094" x="795.619" bottomLeftOrigin="true"></sliceSourceBounds>
+	</sfw>
+</metadata>
+<g>
+	<path fill="#FFC331" d="M152.04,147.17c-0.49,0.084-0.994,0.146-1.52,0.168c-2.756,0.086-4.769-0.66-6.529-2.42l-9.97-9.967
+		l-12.596-12.598l-40.408-40.41c-3.852-3.85-8.221-6.016-12.994-6.439c-2.5-0.223-5.016,0.035-7.445,0.76
+		c-3.635,1.063-6.879,2.998-9.635,5.756c-4.299,4.297-6.574,9.467-6.588,14.949c-0.068,5.572,2.188,10.801,6.512,15.125
+		l62.363,62.367c2.043,2.072,2.982,4.27,2.953,6.914l0.004,0.234c0.059,2.736-0.852,4.889-2.945,6.982
+		c-1.996,1.998-4.271,2.984-7.074,3.1c-2.756,0.086-4.77-0.662-6.531-2.422l-62.971-62.973c-5.846-5.844-13.121-7.861-20.439-5.68
+		c-3.639,1.061-6.879,2.996-9.637,5.754c-4.299,4.299-6.576,9.469-6.588,14.951c-0.063,5.572,2.188,10.803,6.51,15.129
+		l65.148,65.145c9.328,9.328,21.684,13.43,36.711,12.193c14.104-1.148,25.813-6.283,34.795-15.27
+		c8.423-8.422,13.414-18.396,14.897-29.729c11.741-1.893,21.633-6.801,29.459-14.627c4.5-4.5,8.016-9.447,10.545-14.807
+		C182.196,158.906,166.409,154.844,152.04,147.17z"/>
+	<path fill="#366994" d="M202.889,137.385c0.115-14.451-4.967-26.984-15.143-37.277l-40.229-40.229
+		c-0.273-0.271-0.521-0.549-0.77-0.838c-1.664-1.957-2.453-4.031-2.478-6.533c-0.029-2.779,0.952-5.072,3.095-7.209
+		c2.146-2.148,4.32-3.08,7.137-3.02c2.844,0.027,5.188,1.061,7.369,3.242l67.934,67.934l13.582-13.578
+		c1.258-1.021,2.195-1.99,3.227-3.301c6.636-8.455,5.908-20.557-1.693-28.158l-52.969-52.975C181.643,5.141,169.116-0.056,154.764,0
+		c-14.511-0.057-27.067,5.117-37.321,15.371C107.32,25.492,102.15,37.803,102.082,51.92l-0.004,0.16
+		c-0.002,0.189-0.006,0.379-0.006,0.57c-0.102,13.762,4.605,25.828,13.994,35.867c0.451,0.484,0.9,0.965,1.371,1.438l40.083,40.08
+		c2.118,2.117,3.047,4.271,3.02,6.986l0.003,0.236c0.059,2.736-0.853,4.889-2.946,6.984c-1.623,1.619-3.434,2.563-5.557,2.928
+		c14.369,7.674,30.156,11.736,46.027,12.188c3.146-6.666,4.766-13.971,4.82-21.865L202.889,137.385z"/>
+	<path fill="#FFFFFF" d="M223.878,77.83c3.192-3.193,8.368-3.191,11.558,0c3.189,3.189,3.191,8.365-0.002,11.555
+		c-3.188,3.193-8.367,3.193-11.556,0C220.688,86.195,220.685,81.02,223.878,77.83z"/>
+</g>
+</svg>
diff --git a/logo/vertical.svg b/logo/vertical.svg
new file mode 100644
index 0000000..e83e1fe
--- /dev/null
+++ b/logo/vertical.svg
@@ -0,0 +1,157 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 16.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" [
+	<!ENTITY ns_extend "http://ns.adobe.com/Extensibility/1.0/">
+	<!ENTITY ns_ai "http://ns.adobe.com/AdobeIllustrator/10.0/">
+	<!ENTITY ns_graphs "http://ns.adobe.com/Graphs/1.0/">
+	<!ENTITY ns_vars "http://ns.adobe.com/Variables/1.0/">
+	<!ENTITY ns_imrep "http://ns.adobe.com/ImageReplacement/1.0/">
+	<!ENTITY ns_sfw "http://ns.adobe.com/SaveForWeb/1.0/">
+	<!ENTITY ns_custom "http://ns.adobe.com/GenericCustomNamespace/1.0/">
+	<!ENTITY ns_adobe_xpath "http://ns.adobe.com/XPath/1.0/">
+]>
+<svg version="1.1" id="Layer_1" xmlns:x="&ns_extend;" xmlns:i="&ns_ai;" xmlns:graph="&ns_graphs;"
+	 xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="683.564px"
+	 height="357.889px" viewBox="0 0 683.564 357.889" enable-background="new 0 0 683.564 357.889" xml:space="preserve">
+<metadata>
+	<sfw  xmlns="&ns_sfw;">
+		<slices></slices>
+		<sliceSourceBounds  width="683.564" height="357.889" y="-917.979" x="579.409" bottomLeftOrigin="true"></sliceSourceBounds>
+	</sfw>
+</metadata>
+<g>
+	<g>
+		<g>
+			<path fill="#FFC331" d="M14.83,328.775c0,3.953,1.392,7.322,4.176,10.105c2.784,2.787,6.154,4.178,10.109,4.178
+				c3.954,0,7.324-1.391,10.107-4.178c2.785-2.783,4.178-6.152,4.178-10.105v-33.232c0-2.016,0.726-3.752,2.179-5.203
+				c1.453-1.455,3.188-2.182,5.206-2.182h0.121c2.057,0,3.771,0.727,5.145,2.182c1.453,1.451,2.18,3.188,2.18,5.203v33.232
+				c0,3.953,1.392,7.322,4.178,10.105c2.783,2.787,6.151,4.178,10.107,4.178c3.995,0,7.384-1.391,10.168-4.178
+				c2.785-2.783,4.178-6.152,4.178-10.105v-33.232c0-2.016,0.725-3.752,2.179-5.203c1.37-1.455,3.086-2.182,5.145-2.182h0.12
+				c2.019,0,3.754,0.727,5.206,2.182c1.413,1.451,2.119,3.188,2.119,5.203v33.232c0,8.029-2.846,14.889-8.534,20.578
+				c-5.69,5.689-12.551,8.535-20.58,8.535c-9.605,0-16.827-3.186-21.671-9.563c-4.882,6.377-12.126,9.563-21.729,9.563
+				c-8.03,0-14.891-2.846-20.58-8.535S0,336.805,0,328.775v-33.232c0-2.016,0.727-3.752,2.18-5.203
+				c1.452-1.455,3.167-2.182,5.145-2.182h0.182c1.977,0,3.691,0.727,5.146,2.182c1.451,1.451,2.178,3.188,2.178,5.203V328.775z"/>
+			<path fill="#FFC331" d="M178.441,308.498c0.485,1.008,0.728,2.035,0.728,3.086c0,0.848-0.161,1.695-0.484,2.543
+				c-0.687,1.896-1.978,3.268-3.874,4.115c-5.65,2.543-13.074,5.893-22.275,10.049c-11.42,5.164-18.119,8.211-20.096,9.141
+				c3.066,3.873,7.849,5.809,14.346,5.809c4.317,0,8.232-1.27,11.742-3.813c3.43-2.502,5.832-5.73,7.204-9.686
+				c1.171-3.309,3.511-4.963,7.021-4.963c2.501,0,4.499,1.051,5.992,3.146c0.928,1.293,1.392,2.645,1.392,4.057
+				c0,0.848-0.161,1.715-0.483,2.602c-2.381,6.902-6.559,12.471-12.529,16.709c-6.053,4.396-12.833,6.596-20.339,6.596
+				c-9.604,0-17.816-3.408-24.635-10.229c-6.82-6.82-10.23-15.031-10.23-24.637c0-9.604,3.41-17.814,10.23-24.637
+				c6.818-6.818,15.031-10.229,24.635-10.229c6.939,0,13.275,1.898,19.006,5.689C171.48,297.563,175.697,302.443,178.441,308.498z
+				 M146.785,303.107c-5.569,0-10.311,1.959-14.225,5.873c-3.874,3.916-5.811,8.658-5.811,14.225v0.424l33.836-15.193
+				C157.6,304.887,152.999,303.107,146.785,303.107z"/>
+			<path fill="#FFC331" d="M198.539,263.342c1.977,0,3.691,0.707,5.145,2.119c1.453,1.451,2.18,3.188,2.18,5.205v23.545
+				c4.559-4.033,11.238-6.053,20.034-6.053c9.604,0,17.816,3.41,24.636,10.229c6.819,6.822,10.23,15.033,10.23,24.637
+				c0,9.605-3.411,17.816-10.23,24.637s-15.031,10.229-24.636,10.229s-17.795-3.389-24.574-10.17
+				c-6.821-6.736-10.251-14.908-10.291-24.514v-52.539c0-2.018,0.727-3.754,2.18-5.205c1.452-1.412,3.167-2.119,5.145-2.119H198.539
+				z M225.897,303.107c-5.568,0-10.31,1.959-14.225,5.873c-3.872,3.916-5.81,8.658-5.81,14.225c0,5.529,1.938,10.25,5.81,14.164
+				c3.915,3.914,8.656,5.871,14.225,5.871c5.529,0,10.25-1.957,14.165-5.871c3.912-3.914,5.87-8.635,5.87-14.164
+				c0-5.566-1.958-10.309-5.87-14.225C236.147,305.066,231.427,303.107,225.897,303.107z"/>
+			<g>
+				<g>
+					<path fill="#366994" d="M289.817,302.99c-1.776,0-3.269,0.604-4.479,1.814c-1.211,1.252-1.816,2.744-1.816,4.479
+						c0,2.422,1.17,4.238,3.512,5.447c0.806,0.445,4.176,1.453,10.108,3.027c4.802,1.373,8.372,3.168,10.712,5.387
+						c3.351,3.189,5.024,7.729,5.024,13.621c0,5.809-2.058,10.793-6.173,14.949c-4.157,4.117-9.141,6.174-14.951,6.174h-15.798
+						c-1.979,0-3.692-0.725-5.146-2.18c-1.453-1.371-2.18-3.086-2.18-5.143v-0.123c0-2.016,0.727-3.752,2.18-5.205
+						s3.167-2.18,5.146-2.18h16.403c1.775,0,3.269-0.604,4.479-1.814c1.211-1.211,1.816-2.703,1.816-4.479
+						c0-2.221-1.15-3.896-3.449-5.023c-0.605-0.285-3.996-1.293-10.17-3.027c-4.803-1.412-8.375-3.271-10.715-5.57
+						c-3.35-3.268-5.023-7.889-5.023-13.861c0-5.811,2.059-10.773,6.175-14.889c4.155-4.156,9.14-6.236,14.95-6.236h11.138
+						c2.017,0,3.753,0.727,5.206,2.182c1.452,1.451,2.179,3.188,2.179,5.203v0.121c0,2.059-0.727,3.775-2.179,5.146
+						c-1.453,1.451-3.189,2.18-5.206,2.18H289.817z"/>
+				</g>
+			</g>
+			<g>
+				<g>
+					<path fill="#366994" d="M355.613,288.158c9.604,0,17.815,3.41,24.636,10.229c6.819,6.822,10.229,15.033,10.229,24.637
+						c0,9.605-3.41,17.816-10.229,24.637c-6.82,6.82-15.032,10.229-24.636,10.229c-9.604,0-17.816-3.408-24.635-10.229
+						c-6.82-6.82-10.23-15.031-10.23-24.637c0-9.604,3.41-17.814,10.23-24.637C337.797,291.568,346.009,288.158,355.613,288.158z
+						 M355.613,303.107c-5.569,0-10.311,1.959-14.225,5.873c-3.875,3.916-5.812,8.658-5.812,14.225
+						c0,5.529,1.937,10.25,5.812,14.164c3.914,3.914,8.655,5.871,14.225,5.871c5.528,0,10.249-1.957,14.164-5.871
+						c3.914-3.914,5.871-8.635,5.871-14.164c0-5.566-1.957-10.309-5.871-14.225C365.862,305.066,361.142,303.107,355.613,303.107z"
+						/>
+				</g>
+			</g>
+			<g>
+				<g>
+					<path fill="#366994" d="M444.35,289.793c3.431,1.09,5.146,3.43,5.146,7.021v0.305c0,2.459-0.99,4.416-2.967,5.871
+						c-1.372,0.967-2.785,1.451-4.236,1.451c-0.768,0-1.555-0.121-2.361-0.363c-1.978-0.645-4.016-0.971-6.113-0.971
+						c-5.569,0-10.312,1.959-14.225,5.873c-3.875,3.916-5.811,8.658-5.811,14.225c0,5.529,1.936,10.25,5.811,14.164
+						c3.913,3.914,8.655,5.871,14.225,5.871c2.098,0,4.136-0.322,6.113-0.969c0.766-0.242,1.533-0.363,2.3-0.363
+						c1.491,0,2.926,0.486,4.298,1.455c1.977,1.451,2.967,3.43,2.967,5.932c0,3.551-1.716,5.891-5.146,7.021
+						c-3.389,1.049-6.899,1.572-10.531,1.572c-9.604,0-17.816-3.408-24.637-10.229c-6.818-6.82-10.229-15.031-10.229-24.637
+						c0-9.604,3.41-17.814,10.229-24.637c6.82-6.818,15.032-10.229,24.637-10.229C437.45,288.158,440.961,288.705,444.35,289.793z"
+						/>
+				</g>
+			</g>
+			<g>
+				<g>
+					<path fill="#366994" d="M467.291,263.342c1.976,0,3.691,0.707,5.146,2.119c1.452,1.451,2.179,3.188,2.179,5.205v41.947h2.3
+						c5.165,0,9.663-1.715,13.499-5.146c3.752-3.43,5.89-7.666,6.415-12.711c0.242-1.896,1.05-3.451,2.422-4.66
+						c1.371-1.291,3.005-1.938,4.902-1.938h0.181c2.14,0,3.936,0.809,5.388,2.422c1.292,1.412,1.937,3.047,1.937,4.902
+						c0,0.242-0.021,0.506-0.06,0.787c-0.969,10.129-4.843,17.715-11.622,22.758c3.55,2.182,6.819,5.873,9.807,11.078
+						c3.106,5.367,4.661,11.16,4.661,17.371v3.09c0,2.057-0.728,3.771-2.179,5.143c-1.455,1.455-3.169,2.18-5.146,2.18h-0.182
+						c-1.978,0-3.692-0.725-5.145-2.18c-1.453-1.371-2.179-3.086-2.179-5.143v-3.09c-0.042-5.484-1.999-10.188-5.872-14.104
+						c-3.915-3.873-8.637-5.809-14.164-5.809h-4.963v23.002c0,2.057-0.727,3.771-2.179,5.143c-1.454,1.455-3.17,2.18-5.146,2.18
+						h-0.184c-1.977,0-3.69-0.725-5.144-2.18c-1.452-1.371-2.179-3.086-2.179-5.143v-79.9c0-2.018,0.727-3.754,2.179-5.205
+						c1.453-1.412,3.167-2.119,5.144-2.119H467.291z"/>
+				</g>
+			</g>
+			<g>
+				<g>
+					<path fill="#366994" d="M589.44,308.498c0.484,1.008,0.726,2.035,0.726,3.086c0,0.848-0.162,1.695-0.483,2.543
+						c-0.687,1.896-1.978,3.268-3.874,4.115c-5.65,2.543-13.075,5.893-22.275,10.049c-11.42,5.164-18.119,8.211-20.096,9.141
+						c3.065,3.873,7.848,5.809,14.346,5.809c4.316,0,8.231-1.27,11.743-3.813c3.429-2.502,5.83-5.73,7.202-9.686
+						c1.17-3.309,3.512-4.963,7.021-4.963c2.502,0,4.5,1.051,5.994,3.146c0.926,1.293,1.391,2.645,1.391,4.057
+						c0,0.848-0.161,1.715-0.484,2.602c-2.381,6.902-6.557,12.471-12.529,16.709c-6.053,4.396-12.832,6.596-20.338,6.596
+						c-9.604,0-17.816-3.408-24.635-10.229c-6.82-6.82-10.23-15.031-10.23-24.637c0-9.604,3.41-17.814,10.23-24.637
+						c6.818-6.818,15.031-10.229,24.635-10.229c6.939,0,13.276,1.898,19.006,5.689C582.479,297.563,586.695,302.443,589.44,308.498z
+						 M557.783,303.107c-5.568,0-10.311,1.959-14.225,5.873c-3.874,3.916-5.811,8.658-5.811,14.225v0.424l33.836-15.193
+						C568.597,304.887,563.997,303.107,557.783,303.107z"/>
+				</g>
+			</g>
+			<g>
+				<g>
+					<path fill="#366994" d="M609.535,263.342c1.977,0,3.692,0.707,5.146,2.119c1.452,1.451,2.179,3.188,2.179,5.205v17.492h9.08
+						c1.977,0,3.691,0.727,5.146,2.182c1.452,1.451,2.177,3.188,2.177,5.203v0.121c0,2.059-0.725,3.775-2.177,5.146
+						c-1.454,1.451-3.169,2.18-5.146,2.18h-9.08v35.891c0,1.172,0.402,2.162,1.211,2.967c0.807,0.809,1.816,1.211,3.026,1.211h4.843
+						c1.977,0,3.691,0.727,5.146,2.18c1.452,1.453,2.177,3.189,2.177,5.205v0.123c0,2.057-0.725,3.771-2.177,5.143
+						c-1.454,1.455-3.169,2.18-5.146,2.18h-4.843c-5.246,0-9.745-1.855-13.498-5.568c-3.714-3.752-5.568-8.232-5.568-13.439v-68.215
+						c0-2.018,0.726-3.754,2.179-5.205c1.453-1.412,3.168-2.119,5.145-2.119H609.535z"/>
+				</g>
+			</g>
+			<g>
+				<g>
+					<path fill="#366994" d="M660.503,302.99c-1.776,0-3.269,0.604-4.479,1.814c-1.211,1.252-1.816,2.744-1.816,4.479
+						c0,2.422,1.17,4.238,3.51,5.447c0.809,0.445,4.178,1.453,10.11,3.027c4.801,1.373,8.372,3.168,10.713,5.387
+						c3.349,3.189,5.024,7.729,5.024,13.621c0,5.809-2.059,10.793-6.174,14.949c-4.156,4.117-9.141,6.174-14.951,6.174h-15.798
+						c-1.978,0-3.692-0.725-5.146-2.18c-1.453-1.371-2.178-3.086-2.178-5.143v-0.123c0-2.016,0.725-3.752,2.178-5.205
+						s3.168-2.18,5.146-2.18h16.403c1.775,0,3.27-0.604,4.479-1.814c1.211-1.211,1.816-2.703,1.816-4.479
+						c0-2.221-1.15-3.896-3.449-5.023c-0.607-0.285-3.996-1.293-10.17-3.027c-4.803-1.412-8.375-3.271-10.715-5.57
+						c-3.35-3.268-5.023-7.889-5.023-13.861c0-5.811,2.059-10.773,6.175-14.889c4.155-4.156,9.14-6.236,14.951-6.236h11.137
+						c2.019,0,3.753,0.727,5.205,2.182c1.453,1.451,2.179,3.188,2.179,5.203v0.121c0,2.059-0.726,3.775-2.179,5.146
+						c-1.452,1.451-3.187,2.18-5.205,2.18H660.503z"/>
+				</g>
+			</g>
+		</g>
+	</g>
+	<path fill="#FFC331" d="M368.249,147.17c-0.49,0.084-0.994,0.146-1.52,0.168c-2.756,0.086-4.769-0.66-6.529-2.42l-9.97-9.967
+		l-12.596-12.598l-40.408-40.41c-3.852-3.85-8.221-6.016-12.994-6.439c-2.5-0.223-5.016,0.035-7.445,0.76
+		c-3.635,1.063-6.879,2.998-9.635,5.756c-4.299,4.297-6.574,9.467-6.588,14.949c-0.068,5.572,2.188,10.801,6.512,15.125
+		l62.363,62.367c2.043,2.072,2.982,4.27,2.953,6.914l0.004,0.234c0.059,2.736-0.852,4.889-2.945,6.982
+		c-1.996,1.998-4.271,2.984-7.074,3.1c-2.756,0.086-4.77-0.662-6.531-2.422l-62.971-62.973c-5.846-5.844-13.121-7.861-20.439-5.68
+		c-3.639,1.061-6.879,2.996-9.637,5.754c-4.299,4.299-6.576,9.469-6.588,14.951c-0.063,5.572,2.188,10.803,6.51,15.129
+		l65.148,65.145c9.328,9.328,21.684,13.43,36.711,12.193c14.104-1.148,25.813-6.283,34.795-15.27
+		c8.423-8.422,13.414-18.396,14.897-29.729c11.741-1.893,21.633-6.801,29.459-14.627c4.5-4.5,8.016-9.447,10.545-14.807
+		C398.405,158.906,382.618,154.844,368.249,147.17z"/>
+	<path fill="#366994" d="M419.099,137.385c0.115-14.451-4.967-26.984-15.143-37.277l-40.229-40.229
+		c-0.273-0.271-0.521-0.549-0.77-0.838c-1.664-1.957-2.453-4.031-2.478-6.533c-0.029-2.779,0.952-5.072,3.095-7.209
+		c2.146-2.148,4.32-3.08,7.137-3.02c2.844,0.027,5.188,1.061,7.369,3.242l67.934,67.934l13.582-13.578
+		c1.258-1.021,2.195-1.99,3.227-3.301c6.636-8.455,5.908-20.557-1.693-28.158l-52.969-52.975C397.853,5.141,385.325-0.056,370.974,0
+		c-14.511-0.057-27.067,5.117-37.321,15.371c-10.123,10.121-15.293,22.432-15.361,36.549l-0.004,0.16
+		c-0.002,0.189-0.006,0.379-0.006,0.57c-0.102,13.762,4.605,25.828,13.994,35.867c0.451,0.484,0.9,0.965,1.371,1.438l40.083,40.08
+		c2.118,2.117,3.047,4.271,3.02,6.986l0.003,0.236c0.059,2.736-0.853,4.889-2.946,6.984c-1.623,1.619-3.434,2.563-5.557,2.928
+		c14.369,7.674,30.156,11.736,46.027,12.188c3.146-6.666,4.766-13.971,4.82-21.865L419.099,137.385z"/>
+	<path fill="#FFFFFF" d="M440.088,77.83c3.192-3.193,8.368-3.191,11.558,0c3.189,3.189,3.191,8.365-0.002,11.555
+		c-3.188,3.193-8.367,3.193-11.556,0C436.897,86.195,436.895,81.02,440.088,77.83z"/>
+</g>
+</svg>
diff --git a/src/websockets/exceptions.py b/src/websockets/exceptions.py
index 73eb8bb..7fdc971 100644
--- a/src/websockets/exceptions.py
+++ b/src/websockets/exceptions.py
@@ -7,6 +7,8 @@ from .http import Headers, HeadersLike
 __all__ = [
     "AbortHandshake",
     "ConnectionClosed",
+    "ConnectionClosedError",
+    "ConnectionClosedOK",
     "DuplicateParameter",
     "InvalidHandshake",
     "InvalidHeader",
@@ -203,7 +205,6 @@ def format_close(code: int, reason: str) -> str:
     """
     Display a human-readable version of the close code and reason.
 
-
     """
     if 3000 <= code < 4000:
         explanation = "registered"
@@ -238,6 +239,32 @@ class ConnectionClosed(InvalidState):
         super().__init__(message)
 
 
+class ConnectionClosedError(ConnectionClosed):
+    """
+    Like :exc:`ConnectionClosed`, when the connection terminated with an error.
+
+    This means the close code is different from 1000 (OK) and 1001 (going away).
+
+    """
+
+    def __init__(self, code: int, reason: str) -> None:
+        assert code != 1000 and code != 1001
+        super().__init__(code, reason)
+
+
+class ConnectionClosedOK(ConnectionClosed):
+    """
+    Like :exc:`ConnectionClosed`, when the connection terminated properly.
+
+    This means the close code is 1000 (OK) or 1001 (going away).
+
+    """
+
+    def __init__(self, code: int, reason: str) -> None:
+        assert code == 1000 or code == 1001
+        super().__init__(code, reason)
+
+
 class InvalidURI(Exception):
     """
     Exception raised when an URI isn't a valid websocket URI.
diff --git a/src/websockets/protocol.py b/src/websockets/protocol.py
index b0fff8f..c07aef9 100644
--- a/src/websockets/protocol.py
+++ b/src/websockets/protocol.py
@@ -30,6 +30,8 @@ from typing import (
 
 from .exceptions import (
     ConnectionClosed,
+    ConnectionClosedError,
+    ConnectionClosedOK,
     InvalidState,
     PayloadTooBig,
     WebSocketProtocolError,
@@ -78,8 +80,8 @@ class WebSocketCommonProtocol(asyncio.StreamReaderProtocol):
 
     The iterator yields incoming messages. It exits normally when the
     connection is closed with the close code 1000 (OK) or 1001 (going away).
-    It raises a :exc:`~websockets.exceptions.ConnectionClosed` exception when
-    the connection is closed with any other status code.
+    It raises a :exc:`~websockets.exceptions.ConnectionClosedError` exception
+    when the connection is closed with any other status code.
 
     The ``host``, ``port`` and ``secure`` parameters are simply stored as
     attributes for handlers that need them.
@@ -114,8 +116,8 @@ class WebSocketCommonProtocol(asyncio.StreamReaderProtocol):
     The ``max_size`` parameter enforces the maximum size for incoming messages
     in bytes. The default value is 1 MiB. ``None`` disables the limit. If a
     message larger than the maximum size is received, :meth:`recv()` will
-    raise :exc:`~websockets.exceptions.ConnectionClosed` and the connection
-    will be closed with status code 1009.
+    raise :exc:`~websockets.exceptions.ConnectionClosedError` and the
+    connection will be closed with status code 1009.
 
     The ``max_queue`` parameter sets the maximum length of the queue that
     holds incoming messages. The default value is ``32``. ``None`` disables
@@ -382,11 +384,8 @@ class WebSocketCommonProtocol(asyncio.StreamReaderProtocol):
         try:
             while True:
                 yield await self.recv()
-        except ConnectionClosed as exc:
-            if exc.code == 1000 or exc.code == 1001:
-                return
-            else:
-                raise
+        except ConnectionClosedOK:
+            return
 
     async def recv(self) -> Data:
         """
@@ -396,8 +395,11 @@ class WebSocketCommonProtocol(asyncio.StreamReaderProtocol):
         binary frame.
 
         When the end of the message stream is reached, :meth:`recv` raises
-        :exc:`~websockets.exceptions.ConnectionClosed`. This can happen after
-        a normal connection closure, a protocol error or a network failure.
+        :exc:`~websockets.exceptions.ConnectionClosed`. Specifically, it
+        raises :exc:`~websockets.exceptions.ConnectionClosedOK` after a normal
+        connection closure and
+        :exc:`~websockets.exceptions.ConnectionClosedError`after a protocol
+        error or a network failure.
 
         .. versionchanged:: 3.0
 
@@ -659,6 +661,16 @@ class WebSocketCommonProtocol(asyncio.StreamReaderProtocol):
 
     # Private methods - no guarantees.
 
+    def connection_closed_exc(self) -> ConnectionClosed:
+        exception: ConnectionClosed
+        if self.close_code == 1000 or self.close_code == 1001:
+            exception = ConnectionClosedOK(self.close_code, self.close_reason)
+        else:
+            exception = ConnectionClosedError(self.close_code, self.close_reason)
+        # Chain to the exception that terminated data transfer, if any.
+        exception.__cause__ = self.transfer_data_exc
+        return exception
+
     async def ensure_open(self) -> None:
         """
         Check that the WebSocket connection is open.
@@ -673,16 +685,12 @@ class WebSocketCommonProtocol(asyncio.StreamReaderProtocol):
             # from OPEN to CLOSED.
             if self.transfer_data_task.done():
                 await asyncio.shield(self.close_connection_task)
-                raise ConnectionClosed(
-                    self.close_code, self.close_reason
-                ) from self.transfer_data_exc
+                raise self.connection_closed_exc()
             else:
                 return
 
         if self.state is State.CLOSED:
-            raise ConnectionClosed(
-                self.close_code, self.close_reason
-            ) from self.transfer_data_exc
+            raise self.connection_closed_exc()
 
         if self.state is State.CLOSING:
             # If we started the closing handshake, wait for its completion to
@@ -691,9 +699,7 @@ class WebSocketCommonProtocol(asyncio.StreamReaderProtocol):
             # CLOSING state also occurs when failing the connection. In that
             # case self.close_connection_task will complete even faster.
             await asyncio.shield(self.close_connection_task)
-            raise ConnectionClosed(
-                self.close_code, self.close_reason
-            ) from self.transfer_data_exc
+            raise self.connection_closed_exc()
 
         # Control may only reach this point in buggy third-party subclasses.
         assert self.state is State.CONNECTING
@@ -1163,8 +1169,7 @@ class WebSocketCommonProtocol(asyncio.StreamReaderProtocol):
 
         """
         assert self.state is State.CLOSED
-        exc = ConnectionClosed(self.close_code, self.close_reason)
-        exc.__cause__ = self.transfer_data_exc  # emulate raise ... from ...
+        exc = self.connection_closed_exc()
 
         for ping in self.pings.values():
             ping.set_exception(exc)
diff --git a/src/websockets/server.py b/src/websockets/server.py
index fca6c2c..e202ea2 100644
--- a/src/websockets/server.py
+++ b/src/websockets/server.py
@@ -782,8 +782,8 @@ class Serve:
     When a server is closed with :meth:`~WebSocketServer.close`, it closes all
     connections with close code 1001 (going away). WebSocket handlers — which
     are running the coroutine passed in the ``ws_handler`` — will receive a
-    :exc:`~websockets.exceptions.ConnectionClosed` exception on their current
-    or next interaction with the WebSocket connection.
+    :exc:`~websockets.exceptions.ConnectionClosedOK` exception on their
+    current or next interaction with the WebSocket connection.
 
     Since there's no useful way to propagate exceptions triggered in handlers,
     they're sent to the ``'websockets.server'`` logger instead. Debugging is
diff --git a/tox.ini b/tox.ini
index 7397c90..801d4d5 100644
--- a/tox.ini
+++ b/tox.ini
@@ -25,4 +25,4 @@ deps = isort
 
 [testenv:mypy]
 commands = mypy --strict src
-deps = mypy
+deps = mypy==0.670


Test patch:
diff --git a/tests/test_exceptions.py b/tests/test_exceptions.py
index 3ccdadb..4b98303 100644
--- a/tests/test_exceptions.py
+++ b/tests/test_exceptions.py
@@ -13,7 +13,7 @@ class ExceptionsTests(unittest.TestCase):
                 "Invalid request",
             ),
             (
-                AbortHandshake(200, Headers(), b'OK\n'),
+                AbortHandshake(200, Headers(), b"OK\n"),
                 "HTTP 200, 0 headers, 3 bytes",
             ),
             (
@@ -21,44 +21,44 @@ class ExceptionsTests(unittest.TestCase):
                 "Malformed HTTP message",
             ),
             (
-                InvalidHeader('Name'),
+                InvalidHeader("Name"),
                 "Missing Name header",
             ),
             (
-                InvalidHeader('Name', None),
+                InvalidHeader("Name", None),
                 "Missing Name header",
             ),
             (
-                InvalidHeader('Name', ''),
+                InvalidHeader("Name", ""),
                 "Empty Name header",
             ),
             (
-                InvalidHeader('Name', 'Value'),
+                InvalidHeader("Name", "Value"),
                 "Invalid Name header: Value",
             ),
             (
                 InvalidHeaderFormat(
-                    'Sec-WebSocket-Protocol', "expected token", 'a=|', 3
+                    "Sec-WebSocket-Protocol", "expected token", "a=|", 3
                 ),
                 "Invalid Sec-WebSocket-Protocol header: "
                 "expected token at 3 in a=|",
             ),
             (
-                InvalidHeaderValue('Sec-WebSocket-Version', '42'),
+                InvalidHeaderValue("Sec-WebSocket-Version", "42"),
                 "Invalid Sec-WebSocket-Version header: 42",
             ),
 
             (
-                InvalidUpgrade('Upgrade'),
+                InvalidUpgrade("Upgrade"),
                 "Missing Upgrade header",
             ),
             (
-                InvalidUpgrade('Connection', 'websocket'),
+                InvalidUpgrade("Connection", "websocket"),
                 "Invalid Connection header: websocket",
             ),
             (
-                InvalidOrigin('http://bad.origin'),
-                'Invalid Origin header: http://bad.origin',
+                InvalidOrigin("http://bad.origin"),
+                "Invalid Origin header: http://bad.origin",
             ),
             (
                 InvalidStatusCode(403),
@@ -69,15 +69,15 @@ class ExceptionsTests(unittest.TestCase):
                 "Unsupported subprotocol: spam",
             ),
             (
-                InvalidParameterName('|'),
+                InvalidParameterName("|"),
                 "Invalid parameter name: |",
             ),
             (
-                InvalidParameterValue('a', '|'),
+                InvalidParameterValue("a", "|"),
                 "Invalid value for parameter a: |",
             ),
             (
-                DuplicateParameter('a'),
+                DuplicateParameter("a"),
                 "Duplicate parameter: a",
             ),
             (
@@ -85,12 +85,12 @@ class ExceptionsTests(unittest.TestCase):
                 "WebSocket connection isn't established yet",
             ),
             (
-                ConnectionClosed(1000, ''),
+                ConnectionClosed(1000, ""),
                 "WebSocket connection is closed: code = 1000 "
                 "(OK), no reason",
             ),
             (
-                ConnectionClosed(1001, 'bye'),
+                ConnectionClosedOK(1001, "bye"),
                 "WebSocket connection is closed: code = 1001 "
                 "(going away), reason = bye",
             ),
@@ -100,7 +100,7 @@ class ExceptionsTests(unittest.TestCase):
                 "(connection closed abnormally [internal]), no reason"
             ),
             (
-                ConnectionClosed(1016, None),
+                ConnectionClosedError(1016, None),
                 "WebSocket connection is closed: code = 1016 "
                 "(unknown), no reason"
             ),