diff --git a/third_party/tlslite/tlslite/constants.py b/third_party/tlslite/tlslite/constants.py
index 715def9..e9743e4 100644
--- a/third_party/tlslite/tlslite/constants.py
+++ b/third_party/tlslite/tlslite/constants.py
@@ -54,6 +54,7 @@ class ExtensionType:    # RFC 6066 / 4366
     status_request = 5  # RFC 6066 / 4366
     srp = 12            # RFC 5054  
     cert_type = 9       # RFC 6091
+    alpn = 16           # RFC 7301
     signed_cert_timestamps = 18  # RFC 6962
     extended_master_secret = 23  # RFC 7627
     token_binding = 24           # draft-ietf-tokbind-negotiation
diff --git a/third_party/tlslite/tlslite/handshakesettings.py b/third_party/tlslite/tlslite/handshakesettings.py
index d7be5b3..69fc6f4 100644
--- a/third_party/tlslite/tlslite/handshakesettings.py
+++ b/third_party/tlslite/tlslite/handshakesettings.py
@@ -128,6 +128,12 @@ class HandshakeSettings(object):
     
     Note that TACK support is not standardized by IETF and uses a temporary
     TLS Extension number, so should NOT be used in production software.
+
+    @type alpnProtos: list of strings.
+    @param alpnProtos: A list of supported upper layer protocols to use in the
+    Application-Layer Protocol Negotiation Extension (RFC 7301).  For the
+    client, the order does not matter.  For the server, the list is in
+    decreasing order of preference.
     """
     def __init__(self):
         self.minKeySize = 1023
@@ -146,6 +152,7 @@ class HandshakeSettings(object):
         self.enableChannelID = True
         self.enableExtendedMasterSecret = True
         self.supportedTokenBindingParams = []
+        self.alpnProtos = None
 
     # Validates the min/max fields, and certificateTypes
     # Filters out unsupported cipherNames and cipherImplementations
@@ -166,6 +173,7 @@ class HandshakeSettings(object):
         other.enableChannelID = self.enableChannelID
         other.enableExtendedMasterSecret = self.enableExtendedMasterSecret
         other.supportedTokenBindingParams = self.supportedTokenBindingParams
+        other.alpnProtos = self.alpnProtos;
 
         if not cipherfactory.tripleDESPresent:
             other.cipherNames = [e for e in self.cipherNames if e != "3des"]
diff --git a/third_party/tlslite/tlslite/messages.py b/third_party/tlslite/tlslite/messages.py
index 5762ac6..1ce9320 100644
--- a/third_party/tlslite/tlslite/messages.py
+++ b/third_party/tlslite/tlslite/messages.py
@@ -18,6 +18,27 @@ from .x509 import X509
 from .x509certchain import X509CertChain
 from .utils.tackwrapper import *
 
+def parse_next_protos(b):
+    protos = []
+    while True:
+        if len(b) == 0:
+            break
+        l = b[0]
+        b = b[1:]
+        if len(b) < l:
+            raise BadNextProtos(len(b))
+        protos.append(b[:l])
+        b = b[l:]
+    return protos
+
+def next_protos_encoded(protocol_list):
+    b = bytearray()
+    for e in protocol_list:
+        if len(e) > 255 or len(e) == 0:
+            raise BadNextProtos(len(e))
+        b += bytearray( [len(e)] ) + bytearray(e)
+    return b
+
 class RecordHeader3(object):
     def __init__(self):
         self.type = 0
@@ -111,6 +132,7 @@ class ClientHello(HandshakeMsg):
         self.compression_methods = []   # a list of 8-bit values
         self.srp_username = None        # a string
         self.tack = False
+        self.alpn_protos_advertised = None
         self.supports_npn = False
         self.server_name = bytearray(0)
         self.channel_id = False
@@ -121,7 +143,8 @@ class ClientHello(HandshakeMsg):
 
     def create(self, version, random, session_id, cipher_suites,
                certificate_types=None, srpUsername=None,
-               tack=False, supports_npn=False, serverName=None):
+               tack=False, alpn_protos_advertised=None,
+               supports_npn=False, serverName=None):
         self.client_version = version
         self.random = random
         self.session_id = session_id
@@ -131,6 +154,7 @@ class ClientHello(HandshakeMsg):
         if srpUsername:
             self.srp_username = bytearray(srpUsername, "utf-8")
         self.tack = tack
+        self.alpn_protos_advertised = alpn_protos_advertised
         self.supports_npn = supports_npn
         if serverName:
             self.server_name = bytearray(serverName, "utf-8")
@@ -171,6 +195,11 @@ class ClientHello(HandshakeMsg):
                         self.certificate_types = p.getVarList(1, 1)
                     elif extType == ExtensionType.tack:
                         self.tack = True
+                    elif extType == ExtensionType.alpn:
+                        structLength = p.get(2)
+                        if structLength + 2 != extLength:
+                            raise SyntaxError()
+                        self.alpn_protos_advertised = parse_next_protos(p.getFixBytes(structLength))
                     elif extType == ExtensionType.supports_npn:
                         self.supports_npn = True
                     elif extType == ExtensionType.server_name:
@@ -243,6 +272,12 @@ class ClientHello(HandshakeMsg):
             w2.add(ExtensionType.srp, 2)
             w2.add(len(self.srp_username)+1, 2)
             w2.addVarSeq(self.srp_username, 1, 1)
+        if self.alpn_protos_advertised is not None:
+            encoded_alpn_protos_advertised = next_protos_encoded(self.alpn_protos_advertised)
+            w2.add(ExtensionType.alpn, 2)
+            w2.add(len(encoded_alpn_protos_advertised) + 2, 2)
+            w2.add(len(encoded_alpn_protos_advertised), 2)
+            w2.addFixSeq(encoded_alpn_protos_advertised, 1)
         if self.supports_npn:
             w2.add(ExtensionType.supports_npn, 2)
             w2.add(0, 2)
@@ -267,6 +302,13 @@ class BadNextProtos(Exception):
     def __str__(self):
         return 'Cannot encode a list of next protocols because it contains an element with invalid length %d. Element lengths must be 0 < x < 256' % self.length
 
+class InvalidALPNResponse(Exception):
+    def __init__(self, l):
+        self.length = l
+
+    def __str__(self):
+        return 'ALPN server response protocol list has invalid length %d.  It must be of length one.' % self.length
+
 class ServerHello(HandshakeMsg):
     def __init__(self):
         HandshakeMsg.__init__(self, HandshakeType.server_hello)
@@ -277,6 +319,7 @@ class ServerHello(HandshakeMsg):
         self.certificate_type = CertificateType.x509
         self.compression_method = 0
         self.tackExt = None
+        self.alpn_proto_selected = None
         self.next_protos_advertised = None
         self.next_protos = None
         self.channel_id = False
@@ -286,7 +329,8 @@ class ServerHello(HandshakeMsg):
         self.status_request = False
 
     def create(self, version, random, session_id, cipher_suite,
-               certificate_type, tackExt, next_protos_advertised):
+               certificate_type, tackExt, alpn_proto_selected,
+               next_protos_advertised):
         self.server_version = version
         self.random = random
         self.session_id = session_id
@@ -294,6 +338,7 @@ class ServerHello(HandshakeMsg):
         self.certificate_type = certificate_type
         self.compression_method = 0
         self.tackExt = tackExt
+        self.alpn_proto_selected = alpn_proto_selected
         self.next_protos_advertised = next_protos_advertised
         return self
 
@@ -316,35 +361,22 @@ class ServerHello(HandshakeMsg):
                     self.certificate_type = p.get(1)
                 elif extType == ExtensionType.tack and tackpyLoaded:
                     self.tackExt = TackExtension(p.getFixBytes(extLength))
+                elif extType == ExtensionType.alpn:
+                    structLength = p.get(2)
+                    if structLength + 2 != extLength:
+                        raise SyntaxError()
+                    alpn_protos = parse_next_protos(p.getFixBytes(structLength))
+                    if len(alpn_protos) != 1:
+                        raise InvalidALPNResponse(len(alpn_protos));
+                    self.alpn_proto_selected = alpn_protos[0]
                 elif extType == ExtensionType.supports_npn:
-                    self.next_protos = self.__parse_next_protos(p.getFixBytes(extLength))
+                    self.next_protos = parse_next_protos(p.getFixBytes(extLength))
                 else:
                     p.getFixBytes(extLength)
                 soFar += 4 + extLength
         p.stopLengthCheck()
         return self
 
-    def __parse_next_protos(self, b):
-        protos = []
-        while True:
-            if len(b) == 0:
-                break
-            l = b[0]
-            b = b[1:]
-            if len(b) < l:
-                raise BadNextProtos(len(b))
-            protos.append(b[:l])
-            b = b[l:]
-        return protos
-
-    def __next_protos_encoded(self):
-        b = bytearray()
-        for e in self.next_protos_advertised:
-            if len(e) > 255 or len(e) == 0:
-                raise BadNextProtos(len(e))
-            b += bytearray( [len(e)] ) + bytearray(e)
-        return b
-
     def write(self):
         w = Writer()
         w.add(self.server_version[0], 1)
@@ -365,8 +397,15 @@ class ServerHello(HandshakeMsg):
             w2.add(ExtensionType.tack, 2)
             w2.add(len(b), 2)
             w2.bytes += b
+        if self.alpn_proto_selected is not None:
+            alpn_protos_single_element_list = [self.alpn_proto_selected]
+            encoded_alpn_protos_advertised = next_protos_encoded(alpn_protos_single_element_list)
+            w2.add(ExtensionType.alpn, 2)
+            w2.add(len(encoded_alpn_protos_advertised) + 2, 2)
+            w2.add(len(encoded_alpn_protos_advertised), 2)
+            w2.addFixSeq(encoded_alpn_protos_advertised, 1)
         if self.next_protos_advertised is not None:
-            encoded_next_protos_advertised = self.__next_protos_encoded()
+            encoded_next_protos_advertised = next_protos_encoded(self.next_protos_advertised)
             w2.add(ExtensionType.supports_npn, 2)
             w2.add(len(encoded_next_protos_advertised), 2)
             w2.addFixSeq(encoded_next_protos_advertised, 1)
diff --git a/third_party/tlslite/tlslite/tlsconnection.py b/third_party/tlslite/tlslite/tlsconnection.py
index 41aab85..de5d580 100644
--- a/third_party/tlslite/tlslite/tlsconnection.py
+++ b/third_party/tlslite/tlslite/tlsconnection.py
@@ -495,6 +495,10 @@ class TLSConnection(TLSRecordLayer):
             settings = HandshakeSettings()
         settings = settings._filter()
 
+        if settings.alpnProtos is not None:
+            if len(settings.alpnProtos) == 0:
+                raise ValueError("Caller passed no alpnProtos")
+
         if clientCertChain:
             if not isinstance(clientCertChain, X509CertChain):
                 raise ValueError("Unrecognized certificate type")
@@ -651,7 +655,8 @@ class TLSConnection(TLSRecordLayer):
                                    session.sessionID, cipherSuites,
                                    certificateTypes, 
                                    session.srpUsername,
-                                   reqTack, nextProtos is not None,
+                                   reqTack, settings.alpnProtos,
+                                   nextProtos is not None,
                                    session.serverName)
 
         #Or send ClientHello (without)
@@ -661,7 +666,8 @@ class TLSConnection(TLSRecordLayer):
                                bytearray(0), cipherSuites,
                                certificateTypes, 
                                srpUsername,
-                               reqTack, nextProtos is not None, 
+                               reqTack, settings.alpnProtos,
+                               nextProtos is not None,
                                serverName)
         for result in self._sendMsg(clientHello):
             yield result
@@ -714,6 +720,16 @@ class TLSConnection(TLSRecordLayer):
                     AlertDescription.illegal_parameter,
                     "Server responded with unrequested Tack Extension"):
                     yield result
+        if serverHello.alpn_proto_selected and not clientHello.alpn_protos_advertised:
+            for result in self._sendError(\
+                AlertDescription.illegal_parameter,
+                "Server responded with unrequested ALPN Extension"):
+                yield result
+        if serverHello.alpn_proto_selected and serverHello.next_protos:
+            for result in self._sendError(\
+                AlertDescription.illegal_parameter,
+                "Server responded with both ALPN and NPN extension"):
+                yield result
         if serverHello.next_protos and not clientHello.supports_npn:
             for result in self._sendError(\
                 AlertDescription.illegal_parameter,
@@ -1315,6 +1331,15 @@ class TLSConnection(TLSRecordLayer):
         else:
             sessionID = bytearray(0)
         
+        alpn_proto_selected = None
+        if (clientHello.alpn_protos_advertised is not None
+                and settings.alpnProtos is not None):
+            for proto in settings.alpnProtos:
+                if proto in clientHello.alpn_protos_advertised:
+                    alpn_proto_selected = proto
+                    nextProtos = None
+                    break;
+
         if not clientHello.supports_npn:
             nextProtos = None
 
@@ -1330,6 +1355,7 @@ class TLSConnection(TLSRecordLayer):
         serverHello = ServerHello()
         serverHello.create(self.version, getRandomBytes(32), sessionID, \
                             cipherSuite, CertificateType.x509, tackExt,
+                            alpn_proto_selected,
                             nextProtos)
         serverHello.channel_id = \
             clientHello.channel_id and settings.enableChannelID
@@ -1500,6 +1526,14 @@ class TLSConnection(TLSRecordLayer):
         else:
             assert(False)
 
+        alpn_proto_selected = None
+        if (clientHello.alpn_protos_advertised is not None
+                and settings.alpnProtos is not None):
+            for proto in settings.alpnProtos:
+                if proto in clientHello.alpn_protos_advertised:
+                    alpn_proto_selected = proto
+                    break;
+
         #If resumption was requested and we have a session cache...
         if clientHello.session_id and sessionCache:
             session = None
@@ -1540,7 +1574,8 @@ class TLSConnection(TLSRecordLayer):
                 serverHello = ServerHello()
                 serverHello.create(self.version, getRandomBytes(32),
                                    session.sessionID, session.cipherSuite,
-                                   CertificateType.x509, None, None)
+                                   CertificateType.x509, None,
+                                   alpn_proto_selected, None)
                 serverHello.extended_master_secret = \
                     clientHello.extended_master_secret and \
                     settings.enableExtendedMasterSecret
