summaryrefslogtreecommitdiff
path: root/lib/ext/alpn.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/ext/alpn.c')
-rw-r--r--lib/ext/alpn.c32
1 files changed, 24 insertions, 8 deletions
diff --git a/lib/ext/alpn.c b/lib/ext/alpn.c
index de53060853..f3fab465e2 100644
--- a/lib/ext/alpn.c
+++ b/lib/ext/alpn.c
@@ -60,6 +60,7 @@ _gnutls_alpn_recv_params(gnutls_session_t session,
ssize_t data_size = _data_size;
alpn_ext_st *priv;
extension_priv_data_t epriv;
+ int selected_protocol_index;
ret =
_gnutls_ext_get_session_data(session, GNUTLS_EXTENSION_ALPN,
@@ -78,23 +79,37 @@ _gnutls_alpn_recv_params(gnutls_session_t session,
gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET_LENGTH);
if (session->security_parameters.entity == GNUTLS_SERVER) {
+ selected_protocol_index = MAX_ALPN_PROTOCOLS+1;
+
while (data_size > 0) {
DECR_LENGTH_RET(data_size, 1, 0);
len1 = *p;
p += 1;
DECR_LENGTH_RET(data_size, len1, 0);
- for (i = 0; i < priv->size; i++)
+ for (i = 0; i < priv->size; i++) {
if (priv->protocol_size[i] == len1
&& memcmp(p, priv->protocols[i],
len1) == 0) {
- priv->selected_protocol =
- priv->protocols[i];
- priv->selected_protocol_size =
- priv->protocol_size[i];
- return 0;
+ if (priv->flags & GNUTLS_ALPN_SERVER_PRECEDENCE) {
+ if (selected_protocol_index > i) {
+ selected_protocol_index = i;
+ priv->selected_protocol =
+ priv->protocols[i];
+ priv->selected_protocol_size =
+ priv->protocol_size[i];
+ break;
+ }
+ } else {
+ priv->selected_protocol =
+ priv->protocols[i];
+ priv->selected_protocol_size =
+ priv->protocol_size[i];
+ return 0;
+ }
}
+ }
p += len1;
}
} else {
@@ -103,7 +118,7 @@ _gnutls_alpn_recv_params(gnutls_session_t session,
p += 1;
DECR_LENGTH_RET(data_size, len1, 0);
- for (i = 0; i < priv->size; i++)
+ for (i = 0; i < priv->size; i++) {
if (priv->protocol_size[i] == len1
&& memcmp(p, priv->protocols[i], len1) == 0) {
priv->selected_protocol =
@@ -112,6 +127,7 @@ _gnutls_alpn_recv_params(gnutls_session_t session,
priv->protocol_size[i];
break;
}
+ }
p += len1;
}
@@ -246,7 +262,7 @@ gnutls_alpn_get_selected_protocol(gnutls_session_t session,
* @session: is a #gnutls_session_t type.
* @protocols: is the protocol names to add.
* @protocols_size: the number of protocols to add.
- * @flags: zero or %GNUTLS_ALPN_*
+ * @flags: zero or a sequence of %gnutls_alpn_flags_t
*
* This function is to be used by both clients and servers, to declare
* the supported ALPN protocols, which are used during negotiation with peer.