picoquic/tls_api.c
int picoquic_client_hello_call_back(ptls_on_client_hello_t* on_hello_cb_ctx,
    ptls_t* tls, ptls_on_client_hello_parameters_t *params)
{
    const uint8_t * alpn_found = 0;
    size_t alpn_found_length = 0;
    int ret = 0;
    picoquic_quic_t** ppquic = (picoquic_quic_t**)(((char*)on_hello_cb_ctx) + sizeof(ptls_on_client_hello_t));
    picoquic_quic_t* quic = *ppquic;

    /* Save the server name */
    ptls_set_server_name(tls, (const char *)params->server_name.base, params->server_name.len);

#ifdef PTLS_ESNI_NONCE_SIZE
    if (params->esni && quic->cnx_in_progress != NULL) {
        /* Find the ESNI secret if any, and copy key values to picoquic tls context */
        picoquic_tls_ctx_t* tls_ctx = (picoquic_tls_ctx_t*)quic->cnx_in_progress->tls_ctx;
        struct st_ptls_esni_secret_t * esni = ptls_get_esni_secret(tls_ctx->tls);
        if (esni != NULL) {
            tls_ctx->esni_version = esni->version;
            memcpy(tls_ctx->esni_nonce, esni->nonce, PTLS_ESNI_NONCE_SIZE);
        }
    }
#endif

    if (quic->F_log != NULL && quic->cnx_in_progress != NULL) {
        picoquic_log_negotiated_alpn(quic->F_log, quic->cnx_in_progress, 1, 1, params->negotiated_protocols.list, params->negotiated_protocols.count);
    }

    /* Check if the client is proposing the expected ALPN */
    if (quic->default_alpn != NULL) {
        size_t len = strlen(quic->default_alpn);

        for (size_t i = 0; i < params->negotiated_protocols.count; i++) {
            if (params->negotiated_protocols.list[i].len == len && memcmp(params->negotiated_protocols.list[i].base, quic->default_alpn, len) == 0) {
                if (quic->cnx_in_progress != NULL) {
                    picoquic_log_app_message(quic->cnx_in_progress, "ALPN[%d] matches default alpn (%s)", (int)i, quic->default_alpn);
                }
                alpn_found = (const uint8_t *)quic->default_alpn;
                alpn_found_length = len;
                ptls_set_negotiated_protocol(tls, quic->default_alpn, len);
                break;
            }
        }
    }
    else if (quic->alpn_select_fn != NULL) {
        size_t selected = quic->alpn_select_fn(quic, params->negotiated_protocols.list, params->negotiated_protocols.count);
        if (quic->cnx_in_progress != NULL) {
            picoquic_log_app_message(quic->cnx_in_progress, "ALPN Selection call back selects %d (out of %d)", (int)selected, (int)params->negotiated_protocols.count);
        }
        if (selected < params->negotiated_protocols.count) {
            alpn_found = params->negotiated_protocols.list[selected].base;
            alpn_found_length = params->negotiated_protocols.list[selected].len;
            ptls_set_negotiated_protocol(tls, (const char *)params->negotiated_protocols.list[selected].base, params->negotiated_protocols.list[selected].len);
        }
    }

    if (quic->cnx_in_progress != NULL && quic->cnx_in_progress->f_binlog != NULL) {
        binlog_transport_extension(quic->cnx_in_progress, 
            0, params->server_name.base, params->server_name.len, alpn_found, alpn_found_length, 
            params->negotiated_protocols.list, params->negotiated_protocols.count,
            0, NULL);
    }

    /* ALPN is mandatory in Quic. Return an error if no match found. */
    if (alpn_found == NULL) {
        ret = PTLS_ALERT_NO_APPLICATION_PROTOCOL;
    }

    if (ret != 0 && quic->cnx_in_progress != NULL) {
        picoquic_log_app_message(quic->cnx_in_progress, "Client Hello call back returns %d (0x%x)", ret, ret);
    }

    return ret;
}
/*
 * The Hello Call Back is called on the server side upon reception of the 
 * Client Hello. The picotls code will parse the client hello and retrieve
 * parameters such as SNI and proposed ALPN.
 * TODO: check the SNI in case several are supported.
 * TODO: check the ALPN in case several are supported.
 */
The Hello Call Back is called on the server side upon reception of the
Client Hello. The picotls code will parse the client hello and retrieve
parameters such as SNI and proposed ALPN.
TODO: check the SNI in case several are supported.
TODO: check the ALPN in case several are supported.
The Hello Call Back is called on the server side upon reception of the Client Hello . The picotls code will parse the client hello and retrieve parameters such as SNI and proposed ALPN . TODO : check the SNI in case several are supported . TODO : check the ALPN in case several are supported .
int picoquic_client_hello_call_back(ptls_on_client_hello_t* on_hello_cb_ctx,
    ptls_t* tls, ptls_on_client_hello_parameters_t *params)
{
    const uint8_t * alpn_found = 0;
    size_t alpn_found_length = 0;
    int ret = 0;
    picoquic_quic_t** ppquic = (picoquic_quic_t**)(((char*)on_hello_cb_ctx) + sizeof(ptls_on_client_hello_t));
    picoquic_quic_t* quic = *ppquic;
    ptls_set_server_name(tls, (const char *)params->server_name.base, params->server_name.len);
#ifdef PTLS_ESNI_NONCE_SIZE
    if (params->esni && quic->cnx_in_progress != NULL) {
        picoquic_tls_ctx_t* tls_ctx = (picoquic_tls_ctx_t*)quic->cnx_in_progress->tls_ctx;
        struct st_ptls_esni_secret_t * esni = ptls_get_esni_secret(tls_ctx->tls);
        if (esni != NULL) {
            tls_ctx->esni_version = esni->version;
            memcpy(tls_ctx->esni_nonce, esni->nonce, PTLS_ESNI_NONCE_SIZE);
        }
    }
#endif
    if (quic->F_log != NULL && quic->cnx_in_progress != NULL) {
        picoquic_log_negotiated_alpn(quic->F_log, quic->cnx_in_progress, 1, 1, params->negotiated_protocols.list, params->negotiated_protocols.count);
    }
    if (quic->default_alpn != NULL) {
        size_t len = strlen(quic->default_alpn);
        for (size_t i = 0; i < params->negotiated_protocols.count; i++) {
            if (params->negotiated_protocols.list[i].len == len && memcmp(params->negotiated_protocols.list[i].base, quic->default_alpn, len) == 0) {
                if (quic->cnx_in_progress != NULL) {
                    picoquic_log_app_message(quic->cnx_in_progress, "ALPN[%d] matches default alpn (%s)", (int)i, quic->default_alpn);
                }
                alpn_found = (const uint8_t *)quic->default_alpn;
                alpn_found_length = len;
                ptls_set_negotiated_protocol(tls, quic->default_alpn, len);
                break;
            }
        }
    }
    else if (quic->alpn_select_fn != NULL) {
        size_t selected = quic->alpn_select_fn(quic, params->negotiated_protocols.list, params->negotiated_protocols.count);
        if (quic->cnx_in_progress != NULL) {
            picoquic_log_app_message(quic->cnx_in_progress, "ALPN Selection call back selects %d (out of %d)", (int)selected, (int)params->negotiated_protocols.count);
        }
        if (selected < params->negotiated_protocols.count) {
            alpn_found = params->negotiated_protocols.list[selected].base;
            alpn_found_length = params->negotiated_protocols.list[selected].len;
            ptls_set_negotiated_protocol(tls, (const char *)params->negotiated_protocols.list[selected].base, params->negotiated_protocols.list[selected].len);
        }
    }
    if (quic->cnx_in_progress != NULL && quic->cnx_in_progress->f_binlog != NULL) {
        binlog_transport_extension(quic->cnx_in_progress, 
            0, params->server_name.base, params->server_name.len, alpn_found, alpn_found_length, 
            params->negotiated_protocols.list, params->negotiated_protocols.count,
            0, NULL);
    }
    if (alpn_found == NULL) {
        ret = PTLS_ALERT_NO_APPLICATION_PROTOCOL;
    }
    if (ret != 0 && quic->cnx_in_progress != NULL) {
        picoquic_log_app_message(quic->cnx_in_progress, "Client Hello call back returns %d (0x%x)", ret, ret);
    }
    return ret;
}
int picoquic_client_hello_call_back ( ptls_on_client_hello_t * on_hello_cb_ctx , ptls_t * tls , ptls_on_client_hello_parameters_t * params ) { const uint8_t * alpn_found = 0 ; size_t alpn_found_length = 0 ; int ret = 0 ; picoquic_quic_t * * ppquic = ( picoquic_quic_t * * ) ( ( ( char * ) on_hello_cb_ctx ) + sizeof ( ptls_on_client_hello_t ) ) ; picoquic_quic_t * quic = * ppquic ; ptls_set_server_name ( tls , ( const char * ) params -> server_name . base , params -> server_name . len ) ; #ifdef PTLS_ESNI_NONCE_SIZE if ( params -> esni && quic -> cnx_in_progress != NULL ) { picoquic_tls_ctx_t * tls_ctx = ( picoquic_tls_ctx_t * ) quic -> cnx_in_progress -> tls_ctx ; struct st_ptls_esni_secret_t * esni = ptls_get_esni_secret ( tls_ctx -> tls ) ; if ( esni != NULL ) { tls_ctx -> esni_version = esni -> version ; memcpy ( tls_ctx -> esni_nonce , esni -> nonce , PTLS_ESNI_NONCE_SIZE ) ; } } #endif if ( quic -> F_log != NULL && quic -> cnx_in_progress != NULL ) { picoquic_log_negotiated_alpn ( quic -> F_log , quic -> cnx_in_progress , 1 , 1 , params -> negotiated_protocols . list , params -> negotiated_protocols . count ) ; } if ( quic -> default_alpn != NULL ) { size_t len = strlen ( quic -> default_alpn ) ; for ( size_t i = 0 ; i < params -> negotiated_protocols . count ; i ++ ) { if ( params -> negotiated_protocols . list [ i ] . len == len && memcmp ( params -> negotiated_protocols . list [ i ] . base , quic -> default_alpn , len ) == 0 ) { if ( quic -> cnx_in_progress != NULL ) { picoquic_log_app_message ( quic -> cnx_in_progress , " " , ( int ) i , quic -> default_alpn ) ; } alpn_found = ( const uint8_t * ) quic -> default_alpn ; alpn_found_length = len ; ptls_set_negotiated_protocol ( tls , quic -> default_alpn , len ) ; break ; } } } else if ( quic -> alpn_select_fn != NULL ) { size_t selected = quic -> alpn_select_fn ( quic , params -> negotiated_protocols . list , params -> negotiated_protocols . count ) ; if ( quic -> cnx_in_progress != NULL ) { picoquic_log_app_message ( quic -> cnx_in_progress , " " , ( int ) selected , ( int ) params -> negotiated_protocols . count ) ; } if ( selected < params -> negotiated_protocols . count ) { alpn_found = params -> negotiated_protocols . list [ selected ] . base ; alpn_found_length = params -> negotiated_protocols . list [ selected ] . len ; ptls_set_negotiated_protocol ( tls , ( const char * ) params -> negotiated_protocols . list [ selected ] . base , params -> negotiated_protocols . list [ selected ] . len ) ; } } if ( quic -> cnx_in_progress != NULL && quic -> cnx_in_progress -> f_binlog != NULL ) { binlog_transport_extension ( quic -> cnx_in_progress , 0 , params -> server_name . base , params -> server_name . len , alpn_found , alpn_found_length , params -> negotiated_protocols . list , params -> negotiated_protocols . count , 0 , NULL ) ; } if ( alpn_found == NULL ) { ret = PTLS_ALERT_NO_APPLICATION_PROTOCOL ; } if ( ret != 0 && quic -> cnx_in_progress != NULL ) { picoquic_log_app_message ( quic -> cnx_in_progress , " " , ret , ret ) ; } return ret ; }
The Hello Call Back is called on the server side upon reception of the
 Client Hello.
The Hello Call Back is called on the server side upon reception of the Client Hello .
/* Save the server name */ /* Find the ESNI secret if any, and copy key values to picoquic tls context */ /* Check if the client is proposing the expected ALPN */ /* ALPN is mandatory in Quic. Return an error if no match found. */