diff --git a/ssl/s3_clnt.c b/ssl/s3_clnt.c
index 018a9f5..1faf168 100644
--- a/ssl/s3_clnt.c
+++ b/ssl/s3_clnt.c
@@ -476,14 +476,22 @@ int ssl3_connect(SSL *s)
 				SSL3_ST_CW_CHANGE_A,SSL3_ST_CW_CHANGE_B);
 			if (ret <= 0) goto end;
 
-#if defined(OPENSSL_NO_TLSEXT) || defined(OPENSSL_NO_NEXTPROTONEG)
+#if defined(OPENSSL_NO_TLSEXT) || (defined(OPENSSL_NO_NEXTPROTONEG) && defined(OPENSSL_NO_ALPN))
 			s->state=SSL3_ST_CW_FINISHED_A;
 #else
+#if !defined(OPENSSL_NO_NEXTPROTONEG)
 			if (s->s3->next_proto_neg_seen)
 				s->state=SSL3_ST_CW_NEXT_PROTO_A;
 			else
 				s->state=SSL3_ST_CW_FINISHED_A;
 #endif
+#if !defined(OPENSSL_NO_ALPN)
+			if (s->s3->alpn_seen)
+				s->state=SSL3_ST_CW_ALPN_A;
+			else
+				s->state=SSL3_ST_CW_FINISHED_A;
+#endif
+#endif
 			s->init_num=0;
 
 			s->session->cipher=s->s3->tmp.new_cipher;
@@ -519,6 +527,15 @@ int ssl3_connect(SSL *s)
 			s->state=SSL3_ST_CW_FINISHED_A;
 			break;
 #endif
+#if !defined(OPENSSL_NO_TLSEXT) && !defined(OPENSSL_NO_ALPN)
+		case SSL3_ST_CW_ALPN_A:
+		case SSL3_ST_CW_ALPN_B:
+			ret=ssl3_send_alpn(s);
+			if (ret <= 0) goto end;
+			s->state=SSL3_ST_CW_FINISHED_A;
+			break;
+#endif
+
 
 		case SSL3_ST_CW_FINISHED_A:
 		case SSL3_ST_CW_FINISHED_B:
@@ -3527,6 +3544,33 @@ err:
 	return(0);
 	}
 
+#if !defined(OPENSSL_NO_TLSEXT) && !defined(OPENSSL_NO_ALPN)
+int ssl3_send_alpn(SSL *s)
+	{
+	unsigned int len, padding_len;
+	unsigned char *d;
+
+	if (s->state == SSL3_ST_CW_ALPN_A)
+		{
+		len = s->alpn_negotiated_len;
+		padding_len = 32 - ((len + 2) % 32);
+		d = (unsigned char *)s->init_buf->data;
+		d[4] = len;
+		memcpy(d + 5, s->alpn_negotiated, len);
+		d[5 + len] = padding_len;
+		memset(d + 6 + len, 0, padding_len);
+		*(d++)=SSL3_MT_ALPN;
+		l2n3(2 + len + padding_len, d);
+		s->state = SSL3_ST_CW_ALPN_B;
+		s->init_num = 4 + 2 + len + padding_len;
+		s->init_off = 0;
+		}
+
+	return ssl3_do_write(s, SSL3_RT_HANDSHAKE);
+}
+#endif  /* !OPENSSL_NO_TLSEXT && !OPENSSL_NO_ALPN */
+
+
 /* Check to see if handshake is full or resumed. Usually this is just a
  * case of checking to see if a cache hit has occurred. In the case of
  * session tickets we have to check the next message to be sure.
diff --git a/ssl/s3_lib.c b/ssl/s3_lib.c
index 67eb920..2ef92e0 100644
--- a/ssl/s3_lib.c
+++ b/ssl/s3_lib.c
@@ -3122,6 +3122,14 @@ void ssl3_clear(SSL *s)
 		s->next_proto_negotiated_len = 0;
 		}
 #endif
+#if !defined(OPENSSL_NO_TLSEXT) && !defined(OPENSSL_NO_ALPN)
+	if (s->alpn_negotiated)
+		{
+		OPENSSL_free(s->alpn_negotiated);
+		s->alpn_negotiated = NULL;
+		s->alpn_negotiated_len = 0;
+		}
+#endif
 	}
 
 #ifndef OPENSSL_NO_SRP
diff --git a/ssl/s3_srvr.c b/ssl/s3_srvr.c
index ea4e132..8a8950e 100644
--- a/ssl/s3_srvr.c
+++ b/ssl/s3_srvr.c
@@ -630,14 +630,28 @@ int ssl3_accept(SSL *s)
 				 * the client uses its key from the certificate
 				 * for key exchange.
 				 */
-#if defined(OPENSSL_NO_TLSEXT) || defined(OPENSSL_NO_NEXTPROTONEG)
+#if defined(OPENSSL_NO_TLSEXT) 
 				s->state=SSL3_ST_SR_FINISHED_A;
 #else
+#if !defined(OPENSSL_NO_NEXTPROTONEG) && !defined(OPENSSL_NO_ALPN)
+#error "Cannot define both NPN and ALPN"
+#endif
+
+#if !defined(OPENSSL_NO_NEXTPROTONEG)
 				if (s->s3->next_proto_neg_seen)
 					s->state=SSL3_ST_SR_NEXT_PROTO_A;
 				else
 					s->state=SSL3_ST_SR_FINISHED_A;
-#endif
+#endif  /* defined(OPENSSL_NO_NEXTPROTONEG) */
+
+#if !defined(OPENSSL_NO_ALPN)
+				if (s->s3->alpn_seen)
+					s->state=SSL3_ST_SR_ALPN_A;
+				else
+					s->state=SSL3_ST_SR_FINISHED_A;
+#endif /* defined(OPENSSL_NO_ALPN) */
+
+#endif  /* defined(OPENSSL_NO_TLSEXT) */
 				s->init_num = 0;
 				}
 			else if (SSL_USE_SIGALGS(s))
@@ -698,14 +712,26 @@ int ssl3_accept(SSL *s)
 			ret=ssl3_get_cert_verify(s);
 			if (ret <= 0) goto end;
 
-#if defined(OPENSSL_NO_TLSEXT) || defined(OPENSSL_NO_NEXTPROTONEG)
+#if defined(OPENSSL_NO_TLSEXT)
 			s->state=SSL3_ST_SR_FINISHED_A;
 #else
+#if !defined(OPENSSL_NO_NEXTPROTONEG) && !defined(OPENSSL_NO_ALPN)
+#error "Cannot define both NPN and ALPN"
+#endif
+#if !defined(OPENSSL_NO_NEXTPROTONEG)
 			if (s->s3->next_proto_neg_seen)
 				s->state=SSL3_ST_SR_NEXT_PROTO_A;
 			else
 				s->state=SSL3_ST_SR_FINISHED_A;
-#endif
+#endif /* !defined(OPENSSL_NO_NEXTPROTONEG) */
+
+#if !defined(OPENSSL_NO_ALPN)
+			if (s->s3->alpn_seen)
+				s->state=SSL3_ST_SR_ALPN_A;
+			else
+				s->state=SSL3_ST_SR_FINISHED_A;
+#endif /* !defined(OPENSSL_NO_ALPN) */
+#endif /* defined(OPENSSL_NO_TLSEXT) */
 			s->init_num=0;
 			break;
 
@@ -719,6 +745,19 @@ int ssl3_accept(SSL *s)
 			break;
 #endif
 
+#if !defined(OPENSSL_NO_TLSEXT) && !defined(OPENSSL_NO_ALPN)
+		case SSL3_ST_SR_ALPN_A:
+		case SSL3_ST_SR_ALPN_B:
+            if (s->alpn_negotiated_len != 7)
+            {
+			    ret=ssl3_get_alpn(s);
+			    if (ret <= 0) goto end;
+			    s->init_num = 0;
+            }
+			s->state=SSL3_ST_SR_FINISHED_A;
+			break;
+#endif
+
 		case SSL3_ST_SR_FINISHED_A:
 		case SSL3_ST_SR_FINISHED_B:
 			ret=ssl3_get_finished(s,SSL3_ST_SR_FINISHED_A,
@@ -787,14 +826,27 @@ int ssl3_accept(SSL *s)
 			s->state=SSL3_ST_SW_FLUSH;
 			if (s->hit)
 				{
-#if defined(OPENSSL_NO_TLSEXT) || defined(OPENSSL_NO_NEXTPROTONEG)
+#if defined(OPENSSL_NO_TLSEXT)
 				s->s3->tmp.next_state=SSL3_ST_SR_FINISHED_A;
 #else
+#if !defined(OPENSSL_NO_NEXTPROTONEG) && !defined(OPENSSL_NO_ALPN)
+#error "Cannot define both NPN and ALPN"
+#endif
+#if !defined(OPENSSL_NO_NEXTPROTONEG)
 				if (s->s3->next_proto_neg_seen)
 					s->s3->tmp.next_state=SSL3_ST_SR_NEXT_PROTO_A;
 				else
 					s->s3->tmp.next_state=SSL3_ST_SR_FINISHED_A;
-#endif
+#endif /* !defined(OPENSSL_NO_NEXTPROTONEG) */
+
+#if !defined(OPENSSL_NO_ALPN)
+				if (s->s3->alpn_seen)
+					s->s3->tmp.next_state=SSL3_ST_SR_ALPN_A;
+				else
+					s->s3->tmp.next_state=SSL3_ST_SR_FINISHED_A;
+#endif /* !defined(OPENSSL_NO_ALPN) */
+
+#endif /* defined(OPENSSL_NO_TLSEXT) */
 				}
 			else
 				s->s3->tmp.next_state=SSL_ST_OK;
@@ -3642,6 +3694,203 @@ int ssl3_get_next_proto(SSL *s)
 	}
 # endif
 
+# ifndef OPENSSL_NO_ALPN
+/* ssl3_get_alpn reads a ALPN handshake message. It
+ * sets the alpn member in s if found */
+int ssl3_get_alpn(SSL *s)
+	{
+	int ok;
+	int proto_len, padding_len;
+	long n;
+	const unsigned char *p;
+
+	/* Clients cannot send a ALPN message if we didn't see the
+	 * extension in their ClientHello */
+	if (!s->s3->alpn_seen)
+		{
+		SSLerr(SSL_F_SSL3_GET_NEXT_PROTO,SSL_R_GOT_NEXT_PROTO_WITHOUT_EXTENSION);
+		return -1;
+		}
+
+	n=s->method->ssl_get_message(s,
+		SSL3_ST_SR_ALPN_A,
+		SSL3_ST_SR_ALPN_B,
+		SSL3_MT_ALPN,
+		514,  /* See the payload format below */
+		&ok);
+
+	if (!ok)
+		return((int)n);
+
+	/* s->state doesn't reflect whether ChangeCipherSpec has been received
+	 * in this handshake, but s->s3->change_cipher_spec does (will be reset
+	 * by ssl3_get_finished). */
+	if (!s->s3->change_cipher_spec)
+		{
+		SSLerr(SSL_F_SSL3_GET_NEXT_PROTO,SSL_R_GOT_NEXT_PROTO_BEFORE_A_CCS);
+		return -1;
+		}
+
+	if (n < 2)
+		return 0;  /* The body must be > 1 bytes long */
+
+	p=(unsigned char *)s->init_msg;
+
+	/* The payload looks like:
+	 *   uint8 proto_len;
+	 *   uint8 proto[proto_len];
+	 *   uint8 padding_len;
+	 *   uint8 padding[padding_len];
+	 */
+	proto_len = p[0];
+	if (proto_len + 2 > s->init_num)
+		return 0;
+	padding_len = p[proto_len + 1];
+	if (proto_len + padding_len + 2 != s->init_num)
+		return 0;
+
+	s->alpn_negotiated = OPENSSL_malloc(proto_len);
+	if (!s->alpn_negotiated)
+		{
+		SSLerr(SSL_F_SSL3_GET_NEXT_PROTO,ERR_R_MALLOC_FAILURE);
+		return 0;
+		}
+	memcpy(s->alpn_negotiated, p + 1, proto_len);
+	s->alpn_negotiated_len = proto_len;
+
+	return 1;
+	}
+
+
+/* ssl3_parse_clienthello_alpn reads a ALPN handshake message.
+   data points to start of protocol list
+   len is decoded size of protocol list
+ */
+int ssl3_parse_clienthello_alpn(SSL *s, unsigned char *data, int len)
+	{
+    int proto_len, total_len;
+	const unsigned char *p;
+
+	if ((len < 0) || (!data))
+		return 0;
+
+	p=(unsigned char *)data;
+    total_len = 0;
+
+	/* The payload looks like sequence of:
+     *   proto_len byte;
+     *   proto_name[proto_len];
+	 */
+    while(total_len < len)
+        {
+        proto_len = (int)(*p);
+        p = p + 1;
+        total_len = total_len + proto_len + 1;
+        if (total_len > len)
+            return 0;
+        p = p + proto_len;
+        }
+
+	s->alpn_negotiated = OPENSSL_malloc(total_len);
+	if (!s->alpn_negotiated)
+		{
+		SSLerr(SSL_F_SSL3_GET_NEXT_PROTO,ERR_R_MALLOC_FAILURE);
+		return 0;
+		}
+	memcpy(s->alpn_negotiated, data, total_len);
+	s->alpn_negotiated_len = total_len;
+
+	return 1;
+}
+
+
+/* ssl3_choose_proto_alpn compares client list 
+   and server list of protocols and chooses one
+   the chosen protocol is recorded in SSL instead
+   of current list of server protocols
+
+   client list consist of:
+    1 byte length
+    Protocol[length]
+
+   server list consist of:
+    1 byte length
+    Protocol[length]
+
+    Chosen protocol is recorded in format
+    1 byte length
+    Protocol[length]
+
+    Returns number of bytes copied
+
+ */
+int ssl3_choose_proto_alpn(SSL *ssl, const unsigned char *client_data, int client_len)
+{
+    int proto_len, total_len;
+    int server_length, server_total;
+	const unsigned char *p;
+    const unsigned char *s;
+    unsigned char *out;
+
+	if (client_len < 2)
+		return 0;  /* The client list must be at least 2 byte long */
+
+    if (!ssl->alpn_negotiated)
+        return 0; /* server does not have ALPN */
+
+	p=(unsigned char *)client_data;
+    total_len = 0;
+
+    while(total_len < client_len)
+    {
+        proto_len = (int)(*p);
+        p = p + 1;
+        total_len = total_len + proto_len + 1;
+        if (total_len > client_len) 
+            return 0; /* bad client length */
+
+        /*  search in server list */
+        s = ssl->alpn_negotiated;
+        server_total = 0;
+        while(server_total < ssl->alpn_negotiated_len)
+        {
+            server_length = (int)(*s);
+            s = s  + 1;
+            server_total = server_total + server_length + 1;
+            if (server_length > ssl->alpn_negotiated_len)
+                return 0; /*  well, how could I shoot myself in the foot? */
+
+            if (server_length != proto_len) continue;
+            if (memcmp(p, s, server_length) == 0) 
+            {
+                /* first match is good enough */
+                OPENSSL_free(ssl->alpn_negotiated);
+                ssl->alpn_negotiated_len = 0;
+                ssl->alpn_negotiated = OPENSSL_malloc(server_length + 1);
+	            if (!ssl->alpn_negotiated)
+		        {
+		            SSLerr(SSL_F_SSL3_GET_NEXT_PROTO,ERR_R_MALLOC_FAILURE);
+		            return 0;
+		        }
+                out = ssl->alpn_negotiated;
+                *out = (unsigned char)server_length;
+                out = out + 1;
+                memcpy(out, p, server_length);
+
+                ssl->alpn_negotiated_len = server_length + 1;
+                return ssl->alpn_negotiated_len;
+            }
+            /* move server pointer */
+            s = s + server_length;
+        }
+        /*  move client pointer */
+        p = p + proto_len;
+    }
+	return 0;
+}
+
+# endif /* OPENSSL_NO_ALPN */
+
 int tls1_send_server_supplemental_data(SSL *s)
 	{
 	size_t length = 0;
diff --git a/ssl/ssl.h b/ssl/ssl.h
index 67397cf..40703e7 100644
--- a/ssl/ssl.h
+++ b/ssl/ssl.h
@@ -143,6 +143,9 @@
 #ifndef HEADER_SSL_H 
 #define HEADER_SSL_H 
 
+/*#define OPENSSL_NO_NEXTPROTONEG 1*/
+#define OPENSSL_NO_ALPN 1
+
 #include <openssl/e_os2.h>
 
 #ifndef OPENSSL_NO_COMP
@@ -1099,6 +1102,25 @@ struct ssl_ctx_st
 				    void *arg);
 	void *next_proto_select_cb_arg;
 # endif
+# ifndef OPENSSL_NO_ALPN
+	/* ALPN information */
+	/* (for experimental ALPN extension). */
+
+	/* For a server, this contains a callback function by which the set of
+	 * advertised protocols can be provided. */
+	int (*alpn_advertised_cb)(SSL *s, const unsigned char **buf,
+			                 unsigned int *len, void *arg);
+	void *alpn_advertised_cb_arg;
+	/* For a client, this contains a callback function that selects the
+	 * next protocol from the list provided by the server. */
+	int (*alpn_select_cb)(SSL *s, unsigned char **out,
+				    unsigned char *outlen,
+				    const unsigned char *in,
+				    unsigned int inlen,
+				    void *arg);
+	void *alpn_select_cb_arg;
+# endif
+
         /* SRTP profiles we are willing to do from RFC 5764 */
 	STACK_OF(SRTP_PROTECTION_PROFILE) *srtp_profiles;  
 #endif
@@ -1201,6 +1223,33 @@ void SSL_get0_next_proto_negotiated(const SSL *s, const unsigned char **data,
 
 #endif
 
+#ifndef OPENSSL_NO_ALPN
+void SSL_CTX_set_alpn_advertised_cb(SSL_CTX *s,
+					   int (*cb) (SSL *ssl,
+						      const unsigned char **out,
+						      unsigned int *outlen,
+						      void *arg),
+					   void *arg);
+void SSL_CTX_set_alpn_select_cb(SSL_CTX *s,
+				      int (*cb) (SSL *ssl,
+						 unsigned char **out,
+						 unsigned char *outlen,
+						 const unsigned char *in,
+						 unsigned int inlen,
+						 void *arg),
+				      void *arg);
+
+int SSL_select_alpn(unsigned char **out, unsigned char *outlen,
+			  const unsigned char *in, unsigned int inlen,
+			  const unsigned char *client, unsigned int client_len);
+void SSL_get0_alpn_negotiated(const SSL *s,
+				    const unsigned char **data, unsigned *len);
+
+#define OPENSSL_ALPN_UNSUPPORTED	0
+#define OPENSSL_ALPN_NEGOTIATED	1
+#define OPENSSL_ALPN_NO_OVERLAP	2
+#endif
+
 #ifndef OPENSSL_NO_PSK
 /* the maximum length of the buffer given to callbacks containing the
  * resulting identity/psk */
@@ -1496,6 +1545,18 @@ struct ssl_st
 	unsigned char next_proto_negotiated_len;
 #endif
 
+#ifndef OPENSSL_NO_ALPN
+	/* ALPN. For the client, this is the protocol that
+	 * we sent in NextProtocol and is set when handling ServerHello
+	 * extensions.
+	 *
+	 * For a server, this is the client's selected_protocol from
+	 * NextProtocol and is set when handling the NextProtocol message,
+	 * before the Finished message. */
+	unsigned char *alpn_negotiated;
+	unsigned char alpn_negotiated_len;
+#endif
+
 #define session_ctx initial_ctx
 
 	STACK_OF(SRTP_PROTECTION_PROFILE) *srtp_profiles;  /* What we'll do */
diff --git a/ssl/ssl3.h b/ssl/ssl3.h
index 77747c4..f8963b6 100644
--- a/ssl/ssl3.h
+++ b/ssl/ssl3.h
@@ -587,6 +587,10 @@ typedef struct ssl3_state_st
 	unsigned short *tlsext_custom_types;
 	size_t tlsext_custom_types_count; /* how many tlsext_custom_types */
 #endif
+#ifndef OPENSSL_NO_ALPN
+	/* Set if we saw the ALPN extension from our peer. */
+	int alpn_seen;
+#endif
 	} SSL3_STATE;
 
 #endif
@@ -632,6 +636,10 @@ typedef struct ssl3_state_st
 #define SSL3_ST_CW_NEXT_PROTO_A		(0x200|SSL_ST_CONNECT)
 #define SSL3_ST_CW_NEXT_PROTO_B		(0x201|SSL_ST_CONNECT)
 #endif
+#ifndef OPENSSL_NO_ALPN
+#define SSL3_ST_CW_ALPN_A		(0x220|SSL_ST_CONNECT)
+#define SSL3_ST_CW_ALPN_B		(0x221|SSL_ST_CONNECT)
+#endif
 #define SSL3_ST_CW_FINISHED_A		(0x1B0|SSL_ST_CONNECT)
 #define SSL3_ST_CW_FINISHED_B		(0x1B1|SSL_ST_CONNECT)
 /* read from server */
@@ -685,6 +693,10 @@ typedef struct ssl3_state_st
 #define SSL3_ST_SR_NEXT_PROTO_A		(0x210|SSL_ST_ACCEPT)
 #define SSL3_ST_SR_NEXT_PROTO_B		(0x211|SSL_ST_ACCEPT)
 #endif
+#ifndef OPENSSL_NO_ALPN
+#define SSL3_ST_SR_ALPN_A		(0x230|SSL_ST_ACCEPT)
+#define SSL3_ST_SR_ALPN_B		(0x231|SSL_ST_ACCEPT)
+#endif
 #define SSL3_ST_SR_FINISHED_A		(0x1C0|SSL_ST_ACCEPT)
 #define SSL3_ST_SR_FINISHED_B		(0x1C1|SSL_ST_ACCEPT)
 /* write to client */
@@ -715,6 +727,9 @@ typedef struct ssl3_state_st
 #ifndef OPENSSL_NO_NEXTPROTONEG
 #define SSL3_MT_NEXT_PROTO			67
 #endif
+#ifndef OPENSSL_NO_ALPN
+#define SSL3_MT_ALPN				68
+#endif
 #define DTLS1_MT_HELLO_VERIFY_REQUEST    3
 
 
diff --git a/ssl/ssl_lib.c b/ssl/ssl_lib.c
index b08e826..8cae751 100644
--- a/ssl/ssl_lib.c
+++ b/ssl/ssl_lib.c
@@ -382,6 +382,9 @@ SSL *SSL_new(SSL_CTX *ctx)
 # ifndef OPENSSL_NO_NEXTPROTONEG
 	s->next_proto_negotiated = NULL;
 # endif
+# ifndef OPENSSL_NO_ALPN
+	s->alpn_negotiated = NULL;
+# endif
 #endif
 
 	s->verify_result=X509_V_OK;
@@ -624,6 +627,10 @@ void SSL_free(SSL *s)
 	if (s->next_proto_negotiated)
 		OPENSSL_free(s->next_proto_negotiated);
 #endif
+#if !defined(OPENSSL_NO_TLSEXT) && !defined(OPENSSL_NO_ALPN)
+	if (s->alpn_negotiated)
+		OPENSSL_free(s->alpn_negotiated);
+#endif
 
         if (s->srtp_profiles)
             sk_SRTP_PROTECTION_PROFILE_free(s->srtp_profiles);
@@ -1582,6 +1589,24 @@ int SSL_get_servername_type(const SSL *s)
 	}
 
 # ifndef OPENSSL_NO_NEXTPROTONEG
+
+int SSL_select_alpn(unsigned char **out, unsigned char *outlen, const unsigned char *server, unsigned int server_len, const unsigned char *client, unsigned int client_len)
+{
+    return OPENSSL_NPN_NO_OVERLAP;
+}
+
+void SSL_get0_alpn_negotiated(const SSL *s, const unsigned char **data, unsigned *len)
+{
+}
+
+void SSL_CTX_set_alpn_advertised_cb(SSL_CTX *ctx, int (*cb) (SSL *ssl, const unsigned char **out, unsigned int *outlen, void *arg), void *arg)
+{
+}
+
+void SSL_CTX_set_alpn_select_cb(SSL_CTX *ctx, int (*cb) (SSL *s, unsigned char **out, unsigned char *outlen, const unsigned char *in, unsigned int inlen, void *arg), void *arg)
+{
+}
+
 /* SSL_select_next_proto implements the standard protocol selection. It is
  * expected that this function is called from the callback set by
  * SSL_CTX_set_next_proto_select_cb.
@@ -1942,6 +1967,124 @@ SSL_CTX *SSL_CTX_new(const SSL_METHOD *meth)
 	ret->next_protos_advertised_cb = 0;
 	ret->next_proto_select_cb = 0;
 # endif
+
+# ifndef OPENSSL_NO_ALPN
+
+void SSL_CTX_set_next_proto_select_cb(SSL_CTX *ctx, int (*cb) (SSL *s, unsigned char **out, unsigned char *outlen, const unsigned char *in, unsigned int inlen, void *arg), void *arg)
+{
+}
+
+void SSL_CTX_set_next_protos_advertised_cb(SSL_CTX *ctx, int (*cb) (SSL *ssl, const unsigned char **out, unsigned int *outlen, void *arg), void *arg)
+{
+}
+
+void SSL_get0_next_proto_negotiated(const SSL *s, const unsigned char **data, unsigned *len)
+{
+}
+
+int SSL_select_next_proto(unsigned char **out, unsigned char *outlen, const unsigned char *server, unsigned int server_len, const unsigned char *client, unsigned int client_len)
+{
+    return OPENSSL_ALPN_NO_OVERLAP;
+}
+
+/* SSL_select_alpn implements the standard protocol selection. It is
+ * expected that this function is called from the callback set by
+ * SSL_CTX_set_alpn_select_cb.
+ *
+ * The protocol data is assumed to be a vector of 8-bit, length prefixed byte
+ * strings. The length byte itself is not included in the length. A byte
+ * string of length 0 is invalid. No byte string may be truncated.
+ *
+ * It returns either
+ * OPENSSL_ALPN_NEGOTIATED if a common protocol was found, or
+ * OPENSSL_ALPN_NO_OVERLAP if the fallback case was reached.
+ */
+int SSL_select_alpn(unsigned char **out, unsigned char *outlen, const unsigned char *server, unsigned int server_len, const unsigned char *client, unsigned int client_len)
+	{
+	unsigned int i, j;
+	const unsigned char *result;
+	int status = OPENSSL_ALPN_UNSUPPORTED;
+
+	/* For each protocol in server preference order, see if we support it. */
+	for (i = 0; i < server_len; )
+		{
+		for (j = 0; j < client_len; )
+			{
+			if (server[i] == client[j] &&
+			    memcmp(&server[i+1], &client[j+1], server[i]) == 0)
+				{
+				/* We found a match */
+				result = &server[i];
+				status = OPENSSL_ALPN_NEGOTIATED;
+				goto found;
+				}
+			j += client[j];
+			j++;
+			}
+		i += server[i];
+		i++;
+		}
+
+	/* There's no overlap between our protocols and the server's list. */
+	result = client;
+	status = OPENSSL_ALPN_NO_OVERLAP;
+
+	found:
+	*out = (unsigned char *) result + 1;
+	*outlen = result[0];
+	return status;
+	}
+
+/* SSL_get0_alpn_negotiated sets *data and *len to point to the client's
+ * requested protocol for this connection and returns 0. If the client didn't
+ * request any protocol, then *data is set to NULL.
+ *
+ * Note that the client can request any protocol it chooses. The value returned
+ * from this function need not be a member of the list of supported protocols
+ * provided by the callback.
+ */
+void SSL_get0_alpn_negotiated(const SSL *s, const unsigned char **data, unsigned *len)
+	{
+	*data = s->alpn_negotiated;
+	if (!*data) {
+		*len = 0;
+	} else {
+        (*data) = (*data) + 1; // name of ALPN is pefixed byte length
+		*len = s->alpn_negotiated_len;
+	}
+}
+
+/* SSL_CTX_set_alpn_advertised_cb sets a callback that is called when a
+ * TLS server needs a list of supported protocols for Next Protocol
+ * Negotiation. The returned list must be in wire format.  The list is returned
+ * by setting |out| to point to it and |outlen| to its length. This memory will
+ * not be modified, but one should assume that the SSL* keeps a reference to
+ * it.
+ *
+ * The callback should return SSL_TLSEXT_ERR_OK if it wishes to advertise. Otherwise, no
+ * such extension will be included in the ServerHello. */
+void SSL_CTX_set_alpn_advertised_cb(SSL_CTX *ctx, int (*cb) (SSL *ssl, const unsigned char **out, unsigned int *outlen, void *arg), void *arg)
+	{
+	ctx->alpn_advertised_cb = cb;
+	ctx->alpn_advertised_cb_arg = arg;
+	}
+
+/* SSL_CTX_set_alpn_select_cb sets a callback that is called when a
+ * client needs to select a protocol from the server's provided list. |out|
+ * must be set to point to the selected protocol (which may be within |in|).
+ * The length of the protocol name must be written into |outlen|. The server's
+ * advertised protocols are provided in |in| and |inlen|. The callback can
+ * assume that |in| is syntactically valid.
+ *
+ * The client must select a protocol. It is fatal to the connection if this
+ * callback returns a value other than SSL_TLSEXT_ERR_OK.
+ */
+void SSL_CTX_set_alpn_select_cb(SSL_CTX *ctx, int (*cb) (SSL *s, unsigned char **out, unsigned char *outlen, const unsigned char *in, unsigned int inlen, void *arg), void *arg)
+	{
+	ctx->alpn_select_cb = cb;
+	ctx->alpn_select_cb_arg = arg;
+	}
+# endif
 #endif
 #ifndef OPENSSL_NO_PSK
 	ret->psk_identity_hint=NULL;
diff --git a/ssl/ssl_locl.h b/ssl/ssl_locl.h
index 56f9b4b..02d98ab 100644
--- a/ssl/ssl_locl.h
+++ b/ssl/ssl_locl.h
@@ -1179,6 +1179,9 @@ int ssl3_check_finished(SSL *s);
 # ifndef OPENSSL_NO_NEXTPROTONEG
 int ssl3_send_next_proto(SSL *s);
 # endif
+# ifndef OPENSSL_NO_ALPN
+int ssl3_send_alpn(SSL *s);
+# endif
 #endif
 
 int dtls1_client_hello(SSL *s);
@@ -1197,6 +1200,11 @@ int ssl3_get_cert_verify(SSL *s);
 #ifndef OPENSSL_NO_NEXTPROTONEG
 int ssl3_get_next_proto(SSL *s);
 #endif
+#ifndef OPENSSL_NO_ALPN
+int ssl3_get_alpn(SSL *s);
+int ssl3_parse_clienthello_alpn(SSL *s, unsigned char *data, int len);
+int ssl3_choose_proto_alpn(SSL *s, const unsigned char *client_list, int client_len);
+#endif
 
 int ssl23_accept(SSL *s);
 int ssl23_connect(SSL *s);
diff --git a/ssl/ssltest.c b/ssl/ssltest.c
index f67c7ea..bf4d0bc 100644
--- a/ssl/ssltest.c
+++ b/ssl/ssltest.c
@@ -479,7 +479,7 @@ static void sv_usage(void)
 	               "                 (default is sect163r2).\n");
 #endif
 	fprintf(stderr," -test_cipherlist - verifies the order of the ssl cipher lists\n");
-#ifndef OPENSSL_NO_NPN
+#ifndef OPENSSL_NO_NEXTPROTONEG
 	fprintf(stderr," -npn_client - have client side offer NPN\n");
 	fprintf(stderr," -npn_server - have server side offer NPN\n");
 	fprintf(stderr," -npn_server_reject - have server reject NPN\n");
@@ -885,7 +885,7 @@ int main(int argc, char *argv[])
 			{
 			test_cipherlist = 1;
 			}
-#ifndef OPENSSL_NO_NPN
+#ifndef OPENSSL_NO_NEXTPROTONEG
 		else if (strcmp(*argv,"-npn_client") == 0)
 			{
 			npn_client = 1;
@@ -1217,7 +1217,7 @@ bad:
 		}
 #endif
 
-#ifndef OPENSSL_NO_NPN
+#ifndef OPENSSL_NO_NEXTPROTONEG
 	if (npn_client)
 		{
 		SSL_CTX_set_next_proto_select_cb(c_ctx, cb_client_npn, NULL);
@@ -1699,7 +1699,7 @@ int doit_biopair(SSL *s_ssl, SSL *c_ssl, long count,
 
 	if (verbose)
 		print_details(c_ssl, "DONE via BIO pair: ");
-#ifndef OPENSSL_NO_NPN
+#ifndef OPENSSL_NO_NEXTPROTONEG
 	if (verify_npn(c_ssl, s_ssl) < 0)
 		{
 		ret = 1;
@@ -2007,7 +2007,7 @@ int doit(SSL *s_ssl, SSL *c_ssl, long count)
 
 	if (verbose)
 		print_details(c_ssl, "DONE: ");
-#ifndef OPENSSL_NO_NPN
+#ifndef OPENSSL_NO_NEXTPROTONEG
 	if (verify_npn(c_ssl, s_ssl) < 0)
 		{
 		ret = 1;
diff --git a/ssl/t1_lib.c b/ssl/t1_lib.c
index 19769c5..a19e4dd 100644
--- a/ssl/t1_lib.c
+++ b/ssl/t1_lib.c
@@ -1404,6 +1404,27 @@ unsigned char *ssl_add_clienthello_tlsext(SSL *s, unsigned char *p, unsigned cha
 		}
 #endif
 
+#ifndef OPENSSL_NO_ALPN
+	if (s->ctx->alpn_select_cb && !s->s3->tmp.finish_md_len)
+		{
+		/* The client advertises an list of protocols for ALPN */
+		const unsigned char *npa;
+		unsigned int npalen;
+		int r;
+
+        r = s->ctx->alpn_advertised_cb(s, &npa, &npalen, s->ctx->alpn_advertised_cb_arg);
+		if (r == SSL_TLSEXT_ERR_OK)
+			{
+			if ((long)(limit - ret - 4 - npalen) < 0) return NULL;
+			s2n(TLSEXT_TYPE_alpn,ret);
+			s2n(npalen,ret);
+			memcpy(ret, npa, npalen);
+			ret += npalen;
+			}
+		}
+
+#endif /* OPENSSL_NO_ALPN */
+
         if(SSL_get_srtp_profiles(s))
                 {
                 int el;
@@ -1586,6 +1607,9 @@ unsigned char *ssl_add_serverhello_tlsext(SSL *s, unsigned char *p, unsigned cha
 		ret += sol;
 		}
 #endif
+#ifndef OPENSSL_NO_ALPN
+	int alpn_seen;
+#endif
 
         if(s->srtp_profile)
                 {
@@ -1768,6 +1792,32 @@ unsigned char *ssl_add_serverhello_tlsext(SSL *s, unsigned char *p, unsigned cha
 			}
 		}
 
+#ifndef OPENSSL_NO_ALPN
+	alpn_seen = s->s3->alpn_seen;
+	s->s3->alpn_seen = 0;
+	if (alpn_seen && s->ctx->alpn_advertised_cb)
+		{
+		const unsigned char *npa;
+		unsigned int npalen;
+		int r;
+
+		r = s->ctx->alpn_advertised_cb(s, &npa, &npalen, s->ctx->alpn_advertised_cb_arg);
+		if (r == SSL_TLSEXT_ERR_OK)
+			{
+			if ((long)(limit - ret - 4 - npalen) < 0) return NULL;
+            if(0 == ssl3_choose_proto_alpn(s, npa, npalen)) return NULL;
+
+			s2n(TLSEXT_TYPE_alpn,ret);
+            npalen = (unsigned int)s->alpn_negotiated_len;
+			s2n(npalen, ret);
+			memcpy(ret, s->alpn_negotiated, npalen);
+			ret += s->alpn_negotiated_len;
+			s->s3->alpn_seen = 1;
+			}
+		}
+#endif
+
+
 	if ((extdatalen = ret-p-2)== 0) 
 		return p;
 
@@ -1789,6 +1839,9 @@ static int ssl_scan_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char
 #ifndef OPENSSL_NO_NEXTPROTONEG
 	s->s3->next_proto_neg_seen = 0;
 #endif
+#ifndef OPENSSL_NO_ALPN
+	s->s3->alpn_seen = 0;
+#endif
 
 #ifndef OPENSSL_NO_HEARTBEATS
 	s->tlsext_heartbeat &= ~(SSL_TLSEXT_HB_ENABLED |
@@ -2265,6 +2318,16 @@ static int ssl_scan_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char
 			s->s3->next_proto_neg_seen = 1;
 			}
 #endif
+#ifndef OPENSSL_NO_ALPN
+		else if (type == TLSEXT_TYPE_alpn)
+			{
+            if (!ssl3_parse_clienthello_alpn(s, data, size))
+            {
+                return 0;
+            }
+		    s->s3->alpn_seen = 1;
+			}
+#endif /* OPENSSL_NO_ALPN */
 
 		/* session ticket processed earlier */
 		else if (type == TLSEXT_TYPE_use_srtp)
@@ -2442,6 +2505,26 @@ static char ssl_next_proto_validate(unsigned char *d, unsigned len)
 	}
 #endif
 
+#ifndef OPENSSL_NO_ALPN
+/* ssl_alpn_validate validates a ALPN block. No
+ * elements of zero length are allowed and the set of elements must exactly fill
+ * the length of the block. */
+static char ssl_alpn_validate(unsigned char *d, unsigned len)
+	{
+	unsigned int off = 0;
+
+	while (off < len)
+		{
+		if (d[off] == 0)
+			return 0;
+		off += d[off];
+		off++;
+		}
+
+	return off == len;
+	}
+#endif
+
 static int ssl_scan_serverhello_tlsext(SSL *s, unsigned char **p, unsigned char *d, int n, int *al)
 	{
 	unsigned short length;
@@ -2454,6 +2537,9 @@ static int ssl_scan_serverhello_tlsext(SSL *s, unsigned char **p, unsigned char
 #ifndef OPENSSL_NO_NEXTPROTONEG
 	s->s3->next_proto_neg_seen = 0;
 #endif
+#ifndef OPENSSL_NO_ALPN
+	s->s3->alpn_seen = 0;
+#endif
 
 #ifndef OPENSSL_NO_HEARTBEATS
 	s->tlsext_heartbeat &= ~(SSL_TLSEXT_HB_ENABLED |
@@ -2617,6 +2703,41 @@ static int ssl_scan_serverhello_tlsext(SSL *s, unsigned char **p, unsigned char
 			s->s3->next_proto_neg_seen = 1;
 			}
 #endif
+#ifndef OPENSSL_NO_ALPN
+		else if (type == TLSEXT_TYPE_alpn &&
+			 s->s3->tmp.finish_md_len == 0)
+			{
+			unsigned char *selected;
+			unsigned char selected_len;
+
+			/* We must have requested it. */
+			if ((s->ctx->alpn_select_cb == NULL))
+				{
+				*al = TLS1_AD_UNSUPPORTED_EXTENSION;
+				return 0;
+				}
+			/* The data must be valid */
+			if (!ssl_alpn_validate(data, size))
+				{
+				*al = TLS1_AD_DECODE_ERROR;
+				return 0;
+				}
+			if (s->ctx->alpn_select_cb(s, &selected, &selected_len, data, size, s->ctx->alpn_select_cb_arg) != SSL_TLSEXT_ERR_OK)
+				{
+				*al = TLS1_AD_INTERNAL_ERROR;
+				return 0;
+				}
+			s->alpn_negotiated = OPENSSL_malloc(selected_len);
+			if (!s->alpn_negotiated)
+				{
+				*al = TLS1_AD_INTERNAL_ERROR;
+				return 0;
+				}
+			memcpy(s->alpn_negotiated, selected, selected_len);
+			s->alpn_negotiated_len = selected_len;
+			s->s3->alpn_seen = 1;
+			}
+#endif
 		else if (type == TLSEXT_TYPE_renegotiate)
 			{
 			if(!ssl_parse_serverhello_renegotiate_ext(s, data, size, al))
diff --git a/ssl/tls1.h b/ssl/tls1.h
index c59a02f..d0aca21 100644
--- a/ssl/tls1.h
+++ b/ssl/tls1.h
@@ -248,6 +248,11 @@ extern "C" {
 #define TLSEXT_TYPE_next_proto_neg		13172
 #endif
 
+#ifndef OPENSSL_NO_ALPN
+/* This is not an IANA defined extension number */
+#define TLSEXT_TYPE_alpn		0xFFFF
+#endif
+
 /* NameType value from RFC 3546 */
 #define TLSEXT_NAMETYPE_host_name 0
 /* status request value from RFC 3546 */
