in buckets/ssl_buckets.c [1904:1967]
apr_status_t serf_ssl_negotiate_protocol(serf_ssl_context_t *context,
const char *protocols,
serf_ssl_protocol_result_cb_t callback,
void *callback_data)
{
apr_pool_t *subpool;
unsigned char *raw_header;
unsigned char *at;
const char *next;
apr_size_t raw_len = strlen(protocols)+1;
apr_size_t len;
if (raw_len >= 65536)
return APR_EINVAL;
/* The OpenSSL api wants the value in network format.
A length byte followed by the value for all items. */
apr_pool_create(&subpool, context->pool);
at = raw_header = apr_palloc(subpool, raw_len);
while ((next = strchr(protocols, ','))) {
len = (next - protocols);
if (len > 255) {
apr_pool_destroy(subpool);
return APR_EINVAL;
}
*at = (unsigned char)len;
at++;
memcpy(at, protocols, len);
at += len;
protocols = next + 1;
}
len = strlen(protocols);
if (len > 255) {
apr_pool_destroy(subpool);
return APR_EINVAL;
}
*at = (unsigned char)len;
at++;
memcpy(at, protocols, len);
at += len;
#ifdef SERF_HAVE_OPENSSL_ALPN
if (SSL_set_alpn_protos(context->ssl, raw_header, raw_len)) {
ERR_clear_error();
}
apr_pool_destroy(subpool);
context->protocol_callback = callback;
context->protocol_userdata = callback_data;
context->selected_protocol = NULL;
return APR_SUCCESS;
#else
apr_pool_destroy(subpool);
return APR_ENOTIMPL;
#endif
}