+ SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+ SSL_F_TLS_HANDLE_STATUS_REQUEST,
+ SSL_R_CLIENTHELLO_TLSEXT);
+ return 0;
+ }
+ }
+ }
+
+ return 1;
+}
+
+/*
+ * Call the alpn_select callback if needed. Upon success, returns 1.
+ * Upon failure, returns 0.
+ */
+int tls_handle_alpn(SSL *s)
+{
+ const unsigned char *selected = NULL;
+ unsigned char selected_len = 0;
+
+ if (s->ctx->ext.alpn_select_cb != NULL && s->s3->alpn_proposed != NULL) {
+ int r = s->ctx->ext.alpn_select_cb(s, &selected, &selected_len,
+ s->s3->alpn_proposed,
+ (unsigned int)s->s3->alpn_proposed_len,
+ s->ctx->ext.alpn_select_cb_arg);
+
+ if (r == SSL_TLSEXT_ERR_OK) {
+ OPENSSL_free(s->s3->alpn_selected);
+ s->s3->alpn_selected = OPENSSL_memdup(selected, selected_len);
+ if (s->s3->alpn_selected == NULL) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_HANDLE_ALPN,
+ ERR_R_INTERNAL_ERROR);