Add an example demonstrating SNI usage.
diff --git a/examples/sni/README b/examples/sni/README
new file mode 100644
index 0000000..4c74eb5
--- /dev/null
+++ b/examples/sni/README
@@ -0,0 +1,19 @@
+This directory contains client and server examples for the "Server Name
+Indication" (SNI) feature.
+
+Run server.py with no arguments.  It will accept one client connection and
+then exit.  It has two certificates it can use, one for "example.invalid"
+and another for "another.invalid".  If a client indicates one of these names
+to it, it will use the corresponding certificate for that connection (if a
+client doesn't indicate a name or indicates another name, it won't try to
+use any certificate).
+
+Run client.py with one argument, the server name to indicate.  For example:
+
+  $ python client.py example.invalid
+  Connecting... connected ('127.0.0.1', 8443)
+  Server subject is <X509Name object '/OU=Security/O=pyOpenSSL/CN=example.invalid/ST=New York/C=US/emailAddress=invalid@example.invalid/L=New York'>
+  $
+
+Depending on what hostname is supplied, the server will select a different
+certificate to use and the client output will be different.
diff --git a/examples/sni/another.invalid.crt b/examples/sni/another.invalid.crt
new file mode 100644
index 0000000..995e14c
--- /dev/null
+++ b/examples/sni/another.invalid.crt
@@ -0,0 +1,17 @@
+-----BEGIN CERTIFICATE-----
+MIICqTCCAhICAQEwDQYJKoZIhvcNAQEEBQAwgZwxETAPBgNVBAsTCFNlY3VyaXR5
+MRIwEAYDVQQKEwlweU9wZW5TU0wxGDAWBgNVBAMTD2Fub3RoZXIuaW52YWxpZDER
+MA8GA1UECBMITmV3IFlvcmsxCzAJBgNVBAYTAlVTMSYwJAYJKoZIhvcNAQkBFhdp
+bnZhbGlkQGFub3RoZXIuaW52YWxpZDERMA8GA1UEBxMITmV3IFlvcmswHhcNMTEw
+NjA2MTIyMTQyWhcNMTIwNjA1MTIyMTQyWjCBnDERMA8GA1UECxMIU2VjdXJpdHkx
+EjAQBgNVBAoTCXB5T3BlblNTTDEYMBYGA1UEAxMPYW5vdGhlci5pbnZhbGlkMREw
+DwYDVQQIEwhOZXcgWW9yazELMAkGA1UEBhMCVVMxJjAkBgkqhkiG9w0BCQEWF2lu
+dmFsaWRAYW5vdGhlci5pbnZhbGlkMREwDwYDVQQHEwhOZXcgWW9yazCBnzANBgkq
+hkiG9w0BAQEFAAOBjQAwgYkCgYEA7jUOM0EnH0/bvqyQfrGlZ5ROc29JWEq3wp7/
+n96cxQ/oSf5G6rlQ5ZYnDlp44csQOY3DIq5/7cRju/Qf5cZ03YMOjzYSi4ElS0+o
+3Av/VgL/ssC6Z0PfQO4+NyXIQTn+cS6P6T65AVBdqn6Z5t0eY0wkU6QznpdJ/1c2
+a7gIYnUCAwEAATANBgkqhkiG9w0BAQQFAAOBgQBqyrP1wmpTmfeZnoB7piJd+qIj
+VHpCDRAZcdsxKUl/8PahjtWPMB0G5VaMwOoIGIlMxZ/LPKf44cA+QNEIXq8rohr2
+XFaA4t4X4aP7OmwQ4pa8mh4r86mP+vQU2iRJOqRYP+/gKaAqI2+ZbORZXJ7bewb5
+DTvvQRw2PRBf270h8g==
+-----END CERTIFICATE-----
diff --git a/examples/sni/another.invalid.key b/examples/sni/another.invalid.key
new file mode 100644
index 0000000..8d955f6
--- /dev/null
+++ b/examples/sni/another.invalid.key
@@ -0,0 +1,15 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIICXgIBAAKBgQDuNQ4zQScfT9u+rJB+saVnlE5zb0lYSrfCnv+f3pzFD+hJ/kbq
+uVDllicOWnjhyxA5jcMirn/txGO79B/lxnTdgw6PNhKLgSVLT6jcC/9WAv+ywLpn
+Q99A7j43JchBOf5xLo/pPrkBUF2qfpnm3R5jTCRTpDOel0n/VzZruAhidQIDAQAB
+AoGBAOGaJBHM8fWI17DVlKA5NVNNNaPEUW2qjjFoDuflmQpWD4UMqzOhQYm/VMwW
+SYhnnr0zkw1kwUp6Bo87HX6sH37b1GeqIyp+b0Hqc+vLyiXPo0suqV23B9K8jjZ0
+6ap8h6hxpa5D1HtYKKDzWLhLJVtmtslxsvimR/CS+rmpUgBBAkEA+lJ2dXMDsUzB
+xOpX8MLfQsl8XB5tx4ejmXGyNp/hmRFqFi38FFemJXX1YC3wL5jbQ2Ltz9rnbdnG
+Xb/IWrn25QJBAPOcPua6xiNTWW5519JGaNgWdYnUgbj/ib8waLoElHp5Hl5DLuYX
+y8U96Xl/wAE4aQnp5R/PS75tYrKZo79z9FECQQDALk1J8IpWNbLSRoRLkKEtulji
+tG3d8VH1/WcwLuFZzhfffWB6Eay6N+yx8bLkJ/u2qZ4gpVRmbvqvgQ0GMp3NAkBE
+FFczzeCPgLyOdjiNSCYGtYgVg7DZDXjmWFX8HkmMTIrjFu1lWiMVNS8pSD1VWflo
+zte8Ywcs6Y7akLtFRtdxAkEA346J1/Zqtibez2TcjzCK+s9Ihwta23ZN2YTjo60o
+sDZ5AVJwyLa7VFEzO/e9v2ytD7k9fCJjHcxIWIe8zj0dYA==
+-----END RSA PRIVATE KEY-----
diff --git a/examples/sni/client.py b/examples/sni/client.py
new file mode 100644
index 0000000..5b93671
--- /dev/null
+++ b/examples/sni/client.py
@@ -0,0 +1,35 @@
+# Copyright (C) Jean-Paul Calderone
+# See LICENSE for details.
+
+if __name__ == '__main__':
+    import client
+    raise SystemExit(client.main())
+
+from sys import argv, stdout
+from socket import socket
+
+from OpenSSL.SSL import TLSv1_METHOD, Context, Connection
+
+def main():
+    """
+    Connect to an SNI-enabled server and request a specific hostname, specified
+    by argv[1], of it.
+    """
+    if len(argv) < 2:
+        print 'Usage: %s <hostname>' % (argv[0],)
+        return 1
+
+    client = socket()
+
+    print 'Connecting...',
+    stdout.flush()
+    client.connect(('127.0.0.1', 8443))
+    print 'connected', client.getpeername()
+
+    client_ssl = Connection(Context(TLSv1_METHOD), client)
+    client_ssl.set_connect_state()
+    client_ssl.set_tlsext_host_name(argv[1])
+    client_ssl.do_handshake()
+    print 'Server subject is', client_ssl.get_peer_certificate().get_subject()
+    client_ssl.close()
+
diff --git a/examples/sni/example.invalid.crt b/examples/sni/example.invalid.crt
new file mode 100644
index 0000000..b0cabac
--- /dev/null
+++ b/examples/sni/example.invalid.crt
@@ -0,0 +1,17 @@
+-----BEGIN CERTIFICATE-----
+MIICqTCCAhICAQEwDQYJKoZIhvcNAQEEBQAwgZwxETAPBgNVBAsTCFNlY3VyaXR5
+MRIwEAYDVQQKEwlweU9wZW5TU0wxGDAWBgNVBAMTD2V4YW1wbGUuaW52YWxpZDER
+MA8GA1UECBMITmV3IFlvcmsxCzAJBgNVBAYTAlVTMSYwJAYJKoZIhvcNAQkBFhdp
+bnZhbGlkQGV4YW1wbGUuaW52YWxpZDERMA8GA1UEBxMITmV3IFlvcmswHhcNMTEw
+NjA2MTIyMTMzWhcNMTIwNjA1MTIyMTMzWjCBnDERMA8GA1UECxMIU2VjdXJpdHkx
+EjAQBgNVBAoTCXB5T3BlblNTTDEYMBYGA1UEAxMPZXhhbXBsZS5pbnZhbGlkMREw
+DwYDVQQIEwhOZXcgWW9yazELMAkGA1UEBhMCVVMxJjAkBgkqhkiG9w0BCQEWF2lu
+dmFsaWRAZXhhbXBsZS5pbnZhbGlkMREwDwYDVQQHEwhOZXcgWW9yazCBnzANBgkq
+hkiG9w0BAQEFAAOBjQAwgYkCgYEAwmLucR0IXvoGTOfzb2WJlHis2s/FFJfmYAKd
+hq9bs+XzPeAPG0VQqAsy+om1gBOb8KPGtSet2SeNc25FU+QuwAza8uws7EaxD9b9
+CcarIh2X5LMcmiI/p34FuVGUSVsfc4QCTYFWGA0Mrw4jz9sGGeSEmTjVRnc3uAix
+31orKScCAwEAATANBgkqhkiG9w0BAQQFAAOBgQBxm8Qta5wYFmQ3l3EAne9+HaQ5
+gPStgox6STmyOGfRkybSePgOeKftOasaXpKboiNg6PJEkaFEnl9epNwS+8PIjQqv
+mPiZdlrNIfw+YVWpqgcTAIzkhYFH0K4v6d5Wn2adNgd5KbrxYOjsr2w0ixQEtdW/
++z1x/ngjc08EPqOIPQ==
+-----END CERTIFICATE-----
diff --git a/examples/sni/example.invalid.key b/examples/sni/example.invalid.key
new file mode 100644
index 0000000..192e346
--- /dev/null
+++ b/examples/sni/example.invalid.key
@@ -0,0 +1,15 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIICXQIBAAKBgQDCYu5xHQhe+gZM5/NvZYmUeKzaz8UUl+ZgAp2Gr1uz5fM94A8b
+RVCoCzL6ibWAE5vwo8a1J63ZJ41zbkVT5C7ADNry7CzsRrEP1v0JxqsiHZfksxya
+Ij+nfgW5UZRJWx9zhAJNgVYYDQyvDiPP2wYZ5ISZONVGdze4CLHfWispJwIDAQAB
+AoGBAL8L8qNTUHXgL68ITRZP6g71J5YKm/zoafA0wdOsp2lA+Hb4roAz+Nif4SOh
+krPlEd9JZ7OF4vRJTlmDqDmSS2qY7hJuZpdrdvhdxaPGeX4uftC43thEzxLxPQHd
+gCCxugbGJOHChjMPk06oC0w1q70ex3gWmki82Jt/5INV6Z6RAkEA4km0s0RvbVmW
+AT12PROplCRE86eJNlLCVp2TJNl0LPZe5uWqaZZ8wBvfFd1PXEk/Qcpj4IotMZ5M
+1Ai4zw2+6QJBANvo6R5yLRrY8/7YKw9Y/1bbSRLhGYok2Ur4fFz64G28wA1VI3yS
+uXrJ7NjTVykfrBq59WEfh3a15P9g/TMAPY8CQQDdW3Z9iqtpj6IScnowgwR22wfs
+RW4PCuP6cMhY2rMvrI3nVrDd+wzrrBgNPmF8iFZt2Drdkq1lBVJodGO8f9jJAj9O
+K3yyVeOyp2wUKsMjsX8SYOCY1Ws+r9qNy8ZpRsSAPZgHJTx4C6/i9eQ7LuTMuXV0
+CqYu4AZHLGE6Zj+a4XsCQQC8Ken471EXuahfPcKTzsphuZnYZkoVUsFUxJFfqG+S
+8k2Jo/4c+2NyyvVXhXu2at8kmu45c92BrCTXIvLEwtnn
+-----END RSA PRIVATE KEY-----
diff --git a/examples/sni/server.py b/examples/sni/server.py
new file mode 100644
index 0000000..8738416
--- /dev/null
+++ b/examples/sni/server.py
@@ -0,0 +1,64 @@
+# Copyright (C) Jean-Paul Calderone
+# See LICENSE for details.
+
+if __name__ == '__main__':
+    import server
+    raise SystemExit(server.main())
+
+from sys import stdout
+from socket import SOL_SOCKET, SO_REUSEADDR, socket
+
+from OpenSSL.crypto import FILETYPE_PEM, load_privatekey, load_certificate
+from OpenSSL.SSL import TLSv1_METHOD, Context, Connection
+
+def load(domain):
+    crt = open(domain + ".crt")
+    key = open(domain + ".key")
+    result = (
+        load_privatekey(FILETYPE_PEM, key.read()),
+        load_certificate(FILETYPE_PEM, crt.read()))
+    crt.close()
+    key.close()
+    return result
+
+
+def main():
+    """
+    Run an SNI-enabled server which selects between a few certificates in a
+    C{dict} based on the handshake request it receives from a client.
+    """
+    port = socket()
+    port.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)
+    port.bind(('', 8443))
+    port.listen(3)
+
+    print 'Accepting...',
+    stdout.flush()
+    server, addr = port.accept()
+    print 'accepted', addr
+
+    server_context = Context(TLSv1_METHOD)
+    server_context.set_tlsext_servername_callback(pick_certificate)
+
+    server_ssl = Connection(server_context, server)
+    server_ssl.set_accept_state()
+    server_ssl.do_handshake()
+    server.close()
+
+
+certificates = {
+    "example.invalid": load("example.invalid"),
+    "another.invalid": load("another.invalid"),
+    }
+
+
+def pick_certificate(connection):
+    try:
+        key, cert = certificates[connection.get_servername()]
+    except KeyError:
+        pass
+    else:
+        new_context = Context(TLSv1_METHOD)
+        new_context.use_privatekey(key)
+        new_context.use_certificate(cert)
+        connection.set_context(new_context)