picohttp/siduck.c
int siduck_callback(picoquic_cnx_t* cnx,
    uint64_t stream_id, uint8_t* bytes, size_t length,
    picoquic_call_back_event_t fin_or_event, void* callback_ctx, void* v_stream_ctx)
{
    int ret = 0;
    siduck_ctx_t * ctx = (siduck_ctx_t*)callback_ctx;

    if (ctx == NULL) {
        ctx = siduck_create_ctx(NULL);
        if (ctx != NULL) {
            ctx->is_auto_alloc = 1;
        }
        picoquic_set_callback(cnx, siduck_callback, ctx);
    }
    else {
        ret = 0;
    }

    if (ret == 0) {
        switch (fin_or_event) {
        case picoquic_callback_stream_data:
        case picoquic_callback_stream_fin:
        case picoquic_callback_stream_reset: /* Client reset stream #x */
        case picoquic_callback_stop_sending: /* Client asks server to reset stream #x */
        case picoquic_callback_stream_gap:
        case picoquic_callback_prepare_to_send:
            DBG_PRINTF("Unexpected callback, code %d, length = %zu", fin_or_event, length);
            if (ctx != NULL) {
                if (ctx->is_auto_alloc) {
                    free(ctx);
                    ctx = NULL;
                }
                else {
                    ctx->nb_other_errors++;
                }
            }
            picoquic_set_callback(cnx, NULL, NULL);
            ret = picoquic_close(cnx, SIDUCK_ONLY_QUACKS_ECHO);
            break;
        case picoquic_callback_stateless_reset:
        case picoquic_callback_close: /* Received connection close */
        case picoquic_callback_application_close: /* Received application close */
            if (ctx != NULL && ctx->is_auto_alloc) {
                free(ctx);
                ctx = NULL;
            }
            picoquic_set_callback(cnx, NULL, NULL);
            break;
        case picoquic_callback_version_negotiation:
            break;
        case picoquic_callback_almost_ready:
            break;
        case picoquic_callback_ready:
            /* Check that the transport parameters are what Siduck expects */
            if (cnx->remote_parameters.max_datagram_frame_size < sizeof(quack)) {
                if (ctx != NULL) {
                    ctx->nb_other_errors++;
                }
                picoquic_set_callback(cnx, NULL, NULL);
                ret = picoquic_close(cnx, SIDUCK_ONLY_QUACKS_ECHO);
            }
            else {
                if (cnx->client_mode) {
                    if (ctx != NULL) {
                        ctx->nb_quack_sent++;
                    }

                    if (ctx != NULL && ctx->F != NULL) {
                        fprintf(ctx->F, "Sent: quack\n");
                    }
                    ret = do_quack(cnx);
                }
            }
            break;
        case picoquic_callback_datagram:
            /* Process the datagram, which contains an address and a QUIC packet */
            if (cnx->client_mode) {
                if ((ret = check_quack_ack(bytes, length)) == 0) {
                    if (ctx != NULL && ctx->F != NULL) {
                        fprintf(ctx->F, "Received: quack-ack\n");
                    }
                    picoquic_set_callback(cnx, NULL, NULL);
                    if (ctx != NULL) {
                        if (ctx->is_auto_alloc) {
                            free(ctx);
                            ctx = NULL;
                        }
                        else {
                            ctx->nb_quack_ack_received++;
                        }
                    }
                    ret = picoquic_close(cnx, 0);
                }
                else {
                    if (ctx != NULL && ctx->F != NULL) {
                        fprintf(ctx->F, "Received: datagram, but not a quack-ack\n");
                    }
                    else {
                        DBG_PRINTF("Received a datagram, but not a quack ack, length = %zu", length);
                    }

                    if (ctx != NULL) {
                        if (ctx->is_auto_alloc) {
                            free(ctx);
                            ctx = NULL;
                        }
                        else {
                            ctx->nb_bad_quacks++;
                        }
                    }

                    picoquic_set_callback(cnx, NULL, NULL);
                    ret = picoquic_close(cnx, SIDUCK_ONLY_QUACKS_ECHO);
                }
            } else {
                if ((ret = check_quack(bytes, length)) == 0) {
                    if (ctx != NULL) {
                        ctx->nb_quack_ack_sent++;
                    }
                    ret = do_quack_ack(cnx);
                }
                else {
                    DBG_PRINTF("Received a datagram, but not a quack, length = %zu", length);

                    if (ctx != NULL) {
                        if (ctx->is_auto_alloc) {
                            free(ctx);
                            ctx = NULL;
                        }
                        else {
                            ctx->nb_bad_quacks++;
                        }
                    }

                    picoquic_set_callback(cnx, NULL, NULL);
                    ret = picoquic_close(cnx, SIDUCK_ONLY_QUACKS_ECHO);
                }
            }
            break;
        default:
            /* unexpected */
            break;
        }
    }

    return ret;
}
/*
 * SIDUCK datagram demo call back.
 */
SIDUCK datagram demo call back.
SIDUCK datagram demo call back .
int siduck_callback(picoquic_cnx_t* cnx,
    uint64_t stream_id, uint8_t* bytes, size_t length,
    picoquic_call_back_event_t fin_or_event, void* callback_ctx, void* v_stream_ctx)
{
    int ret = 0;
    siduck_ctx_t * ctx = (siduck_ctx_t*)callback_ctx;
    if (ctx == NULL) {
        ctx = siduck_create_ctx(NULL);
        if (ctx != NULL) {
            ctx->is_auto_alloc = 1;
        }
        picoquic_set_callback(cnx, siduck_callback, ctx);
    }
    else {
        ret = 0;
    }
    if (ret == 0) {
        switch (fin_or_event) {
        case picoquic_callback_stream_data:
        case picoquic_callback_stream_fin:
        case picoquic_callback_stream_reset: 
        case picoquic_callback_stop_sending: 
        case picoquic_callback_stream_gap:
        case picoquic_callback_prepare_to_send:
            DBG_PRINTF("Unexpected callback, code %d, length = %zu", fin_or_event, length);
            if (ctx != NULL) {
                if (ctx->is_auto_alloc) {
                    free(ctx);
                    ctx = NULL;
                }
                else {
                    ctx->nb_other_errors++;
                }
            }
            picoquic_set_callback(cnx, NULL, NULL);
            ret = picoquic_close(cnx, SIDUCK_ONLY_QUACKS_ECHO);
            break;
        case picoquic_callback_stateless_reset:
        case picoquic_callback_close: 
        case picoquic_callback_application_close: 
            if (ctx != NULL && ctx->is_auto_alloc) {
                free(ctx);
                ctx = NULL;
            }
            picoquic_set_callback(cnx, NULL, NULL);
            break;
        case picoquic_callback_version_negotiation:
            break;
        case picoquic_callback_almost_ready:
            break;
        case picoquic_callback_ready:
            if (cnx->remote_parameters.max_datagram_frame_size < sizeof(quack)) {
                if (ctx != NULL) {
                    ctx->nb_other_errors++;
                }
                picoquic_set_callback(cnx, NULL, NULL);
                ret = picoquic_close(cnx, SIDUCK_ONLY_QUACKS_ECHO);
            }
            else {
                if (cnx->client_mode) {
                    if (ctx != NULL) {
                        ctx->nb_quack_sent++;
                    }
                    if (ctx != NULL && ctx->F != NULL) {
                        fprintf(ctx->F, "Sent: quack\n");
                    }
                    ret = do_quack(cnx);
                }
            }
            break;
        case picoquic_callback_datagram:
            if (cnx->client_mode) {
                if ((ret = check_quack_ack(bytes, length)) == 0) {
                    if (ctx != NULL && ctx->F != NULL) {
                        fprintf(ctx->F, "Received: quack-ack\n");
                    }
                    picoquic_set_callback(cnx, NULL, NULL);
                    if (ctx != NULL) {
                        if (ctx->is_auto_alloc) {
                            free(ctx);
                            ctx = NULL;
                        }
                        else {
                            ctx->nb_quack_ack_received++;
                        }
                    }
                    ret = picoquic_close(cnx, 0);
                }
                else {
                    if (ctx != NULL && ctx->F != NULL) {
                        fprintf(ctx->F, "Received: datagram, but not a quack-ack\n");
                    }
                    else {
                        DBG_PRINTF("Received a datagram, but not a quack ack, length = %zu", length);
                    }
                    if (ctx != NULL) {
                        if (ctx->is_auto_alloc) {
                            free(ctx);
                            ctx = NULL;
                        }
                        else {
                            ctx->nb_bad_quacks++;
                        }
                    }
                    picoquic_set_callback(cnx, NULL, NULL);
                    ret = picoquic_close(cnx, SIDUCK_ONLY_QUACKS_ECHO);
                }
            } else {
                if ((ret = check_quack(bytes, length)) == 0) {
                    if (ctx != NULL) {
                        ctx->nb_quack_ack_sent++;
                    }
                    ret = do_quack_ack(cnx);
                }
                else {
                    DBG_PRINTF("Received a datagram, but not a quack, length = %zu", length);
                    if (ctx != NULL) {
                        if (ctx->is_auto_alloc) {
                            free(ctx);
                            ctx = NULL;
                        }
                        else {
                            ctx->nb_bad_quacks++;
                        }
                    }
                    picoquic_set_callback(cnx, NULL, NULL);
                    ret = picoquic_close(cnx, SIDUCK_ONLY_QUACKS_ECHO);
                }
            }
            break;
        default:
            break;
        }
    }
    return ret;
}
int siduck_callback ( picoquic_cnx_t * cnx , uint64_t stream_id , uint8_t * bytes , size_t length , picoquic_call_back_event_t fin_or_event , void * callback_ctx , void * v_stream_ctx ) { int ret = 0 ; siduck_ctx_t * ctx = ( siduck_ctx_t * ) callback_ctx ; if ( ctx == NULL ) { ctx = siduck_create_ctx ( NULL ) ; if ( ctx != NULL ) { ctx -> is_auto_alloc = 1 ; } picoquic_set_callback ( cnx , siduck_callback , ctx ) ; } else { ret = 0 ; } if ( ret == 0 ) { switch ( fin_or_event ) { case picoquic_callback_stream_data : case picoquic_callback_stream_fin : case picoquic_callback_stream_reset : case picoquic_callback_stop_sending : case picoquic_callback_stream_gap : case picoquic_callback_prepare_to_send : DBG_PRINTF ( " " , fin_or_event , length ) ; if ( ctx != NULL ) { if ( ctx -> is_auto_alloc ) { free ( ctx ) ; ctx = NULL ; } else { ctx -> nb_other_errors ++ ; } } picoquic_set_callback ( cnx , NULL , NULL ) ; ret = picoquic_close ( cnx , SIDUCK_ONLY_QUACKS_ECHO ) ; break ; case picoquic_callback_stateless_reset : case picoquic_callback_close : case picoquic_callback_application_close : if ( ctx != NULL && ctx -> is_auto_alloc ) { free ( ctx ) ; ctx = NULL ; } picoquic_set_callback ( cnx , NULL , NULL ) ; break ; case picoquic_callback_version_negotiation : break ; case picoquic_callback_almost_ready : break ; case picoquic_callback_ready : if ( cnx -> remote_parameters . max_datagram_frame_size < sizeof ( quack ) ) { if ( ctx != NULL ) { ctx -> nb_other_errors ++ ; } picoquic_set_callback ( cnx , NULL , NULL ) ; ret = picoquic_close ( cnx , SIDUCK_ONLY_QUACKS_ECHO ) ; } else { if ( cnx -> client_mode ) { if ( ctx != NULL ) { ctx -> nb_quack_sent ++ ; } if ( ctx != NULL && ctx -> F != NULL ) { fprintf ( ctx -> F , " \n " ) ; } ret = do_quack ( cnx ) ; } } break ; case picoquic_callback_datagram : if ( cnx -> client_mode ) { if ( ( ret = check_quack_ack ( bytes , length ) ) == 0 ) { if ( ctx != NULL && ctx -> F != NULL ) { fprintf ( ctx -> F , " \n " ) ; } picoquic_set_callback ( cnx , NULL , NULL ) ; if ( ctx != NULL ) { if ( ctx -> is_auto_alloc ) { free ( ctx ) ; ctx = NULL ; } else { ctx -> nb_quack_ack_received ++ ; } } ret = picoquic_close ( cnx , 0 ) ; } else { if ( ctx != NULL && ctx -> F != NULL ) { fprintf ( ctx -> F , " \n " ) ; } else { DBG_PRINTF ( " " , length ) ; } if ( ctx != NULL ) { if ( ctx -> is_auto_alloc ) { free ( ctx ) ; ctx = NULL ; } else { ctx -> nb_bad_quacks ++ ; } } picoquic_set_callback ( cnx , NULL , NULL ) ; ret = picoquic_close ( cnx , SIDUCK_ONLY_QUACKS_ECHO ) ; } } else { if ( ( ret = check_quack ( bytes , length ) ) == 0 ) { if ( ctx != NULL ) { ctx -> nb_quack_ack_sent ++ ; } ret = do_quack_ack ( cnx ) ; } else { DBG_PRINTF ( " " , length ) ; if ( ctx != NULL ) { if ( ctx -> is_auto_alloc ) { free ( ctx ) ; ctx = NULL ; } else { ctx -> nb_bad_quacks ++ ; } } picoquic_set_callback ( cnx , NULL , NULL ) ; ret = picoquic_close ( cnx , SIDUCK_ONLY_QUACKS_ECHO ) ; } } break ; default : break ; } } return ret ; }
SIDUCK datagram demo call back.
SIDUCK datagram demo call back .
/* Client reset stream #x */ /* Client asks server to reset stream #x */ /* Received connection close */ /* Received application close */ /* Check that the transport parameters are what Siduck expects */ /* Process the datagram, which contains an address and a QUIC packet */ /* unexpected */