示例#1
0
文件: sink.c 项目: Chunjie/hilti
static void __unlink_state(binpac_sink* sink, __parser_state* state, hlt_execution_context* ctx)
{
    __parser_state* prev = 0;
    __parser_state* s = sink->head;

    while ( s ) {
        if ( s == state )
            break;

        prev = s;
        s = s->next;
    }

    assert(s);

    if ( prev )
        prev->next = state->next;

    else
        sink->head = state->next;

    GC_CLEAR(state->data, hlt_bytes, ctx);
    GC_CLEAR(state->resume, hlt_exception, ctx);
    GC_DTOR_GENERIC(&state->pobj, state->parser->type_info, ctx);
    state->pobj = 0;
    GC_CLEAR(state->parser, hlt_BinPACHilti_Parser, ctx);
    hlt_free(state);
}
示例#2
0
文件: sink.c 项目: Chunjie/hilti
static void __finish_parser(binpac_sink* sink, __parser_state* state, hlt_exception** excpt, hlt_execution_context* ctx)
{
    if ( state->data && state->resume ) {
        hlt_bytes_freeze(state->data, 1, excpt, ctx);

        // TODO: Not sure if we need this wrapping with fiber/excpt here
        // (neither in main write function).
        hlt_fiber* saved_fiber = ctx->fiber;
        ctx->fiber = 0;
        hlt_exception* sink_excpt = 0;

        // We may trigger a safepoint so make sure we refcount our locoal.
        GC_CCTOR(sink, binpac_sink, ctx);
        __cctor_state(state, ctx);

        (state->parser->resume_func_sink)(state->resume, &sink_excpt, ctx);

        GC_DTOR(sink, binpac_sink, ctx);
        __dtor_state(state, ctx);

        GC_CLEAR(state->resume, hlt_exception, ctx);
        __hlt_context_clear_exception(ctx);
        ctx->fiber = saved_fiber;

        // TODO: Not quite sure why the yield exception can occur here, but
        // we ignore it.
        //
        // Update: Actually I think I do: when two separate filters (like
        // first for a sink and then for the unit connected to it) filter the
        // same data, the frozen flags doesn't get propagated.
        //
        // We forbid that for now and hope it won't be used ...
        //
        // sink-unit-filter.pac2 tests for this but is currently disabled ...
        if ( sink_excpt && sink_excpt->type == &hlt_exception_yield ) {
            assert(false);
        }

        else if ( sink_excpt && sink_excpt->type == &binpac_exception_parserdisabled ) {
            // Disabled, nothing to do.
            DBG_LOG("binpac-sinks", "- final writing to sink %p disabled for parser %p", sink, state->pobj);
            GC_DTOR(sink_excpt, hlt_exception, ctx);
        }

        else
            *excpt = sink_excpt;
    }

    __unlink_state(sink, state, ctx);
}
示例#3
0
文件: sink.c 项目: Chunjie/hilti
void binpac_sink_dtor(hlt_type_info* ti, binpac_sink* sink, hlt_execution_context* ctx)
{
    // TODO: This is not consistnely called because HILTI is actually using
    // its own type info for the dummy struct type. We should unify that, but
    // it's not clear how .. For now, we can't rely on this running.
#if 0
    while ( sink->head )
        __unlink_state(sink, sink->head);

    GC_CLEAR(sink->filter, binpac_filter, ctx);

    __trim(sink, UINT64_MAX, user, excpt, ctx);
    assert(! sink->first_chunk);
    assert(! sink->last_chunk);
#endif
}
示例#4
0
文件: filter.c 项目: Chunjie/hilti
void binpachilti_filter_close(binpac_filter* head, hlt_exception** excpt, hlt_execution_context* ctx)
{
    if ( ! head )
        return;

    binpac_filter* prev = 0;

    binpac_filter* n = 0;
    for ( binpac_filter* f = head; f; f = n ) {
        n = f->next;
        (*f->def->close)(f, excpt, ctx);
        (*f->def->dtor)(0, f, ctx);

        if ( f != head )
            // The reference to the first filter is owned by the struct.
            GC_CLEAR(f, binpac_filter, ctx);
    }
}
示例#5
0
文件: sink.c 项目: Chunjie/hilti
void binpachilti_sink_close(binpac_sink* sink, void* user, hlt_exception** excpt, hlt_execution_context* ctx)
{
    DBG_LOG("binpac-sinks", "closing sink %p", sink);

    if ( sink->filter ) {
        binpachilti_filter_close(sink->filter, excpt, ctx);
        GC_CLEAR(sink->filter, binpac_filter, ctx);
    }

    while( sink->head )
        __finish_parser(sink, sink->head, excpt, ctx);

    __trim(sink, UINT64_MAX, user, excpt, ctx);
    assert(! sink->first_chunk);
    assert(! sink->last_chunk);

    sink->cur_rseq = 0;
    sink->last_reassem_rseq = 0;
    sink->trim_rseq = 0;

    DBG_LOG("binpac-sinks", "closed sink %p, disconnected all parsers", sink);
}
示例#6
0
文件: sink.c 项目: Chunjie/hilti
static int8_t __deliver_chunk(binpac_sink* sink, hlt_bytes* data, uint64_t rseq, uint64_t rupper, void* user, hlt_exception** excpt, hlt_execution_context* ctx)
{
    if ( ! data ) {
        // A gap.
        DBG_LOG("binpac-sinks", "hit gap with sink %p at rseq %" PRIu64, sink, rseq);

        if ( sink->cur_rseq != rupper ) {
            __report_gap(sink, rseq, (rupper - rseq), user, excpt, ctx);
            sink->cur_rseq = rupper;

            if ( sink->auto_trim )
                // We trim just up to the gap here, excluding the gap itself. This
                // will prevent future data beyond the gap from being delivered until
                // we explicitly skip over it.
                __trim(sink, rseq, user, excpt, ctx);
        }

        return 0;
    }

    DBG_LOG("binpac-sinks", "starting to deliver to sink %p at rseq %" PRIu64, sink, rseq);

    // If the HILTI function that we'll call suspends, it will change the
    // yield/resume fields. We need to reset them when we leave this
    // function.

    hlt_fiber* saved_fiber = ctx->fiber;
    __hlt_thread_mgr_blockable* saved_blockable = ctx->blockable;

    ctx->fiber = 0;
    ctx->blockable = 0;

    binpac_dbg_deliver(sink, data, 0, excpt, ctx);

    if ( sink->filter ) {
        hlt_bytes* decoded = binpachilti_filter_decode(sink->filter, data, excpt, ctx); // &noref!

        if ( ! decoded )
            goto exit;

        data = decoded;
    }

    sink->size += hlt_bytes_len(data, excpt, ctx);

    if ( *excpt )
        goto exit;

    if ( ! sink->head ) {
        DBG_LOG("binpac-sinks", "done delivering to sink %p, no parser connected", sink);
        goto exit;
    }

    // data at +1 here.

    __parser_state* s = sink->head;

    // Now pass it onto parsers.
    while ( s ) {

        if ( s->disconnected )
            continue;

        hlt_exception* sink_excpt = 0;

        if ( ! s->data ) {
            // First chunk.
            DBG_LOG("binpac-sinks", "- start delivering to sink %p for parser %p", sink, s->pobj);
            s->data = hlt_bytes_copy(data, excpt, ctx);
            GC_CCTOR(s->data, hlt_bytes, ctx);

            if ( hlt_bytes_is_frozen(data, excpt, ctx) )
                hlt_bytes_freeze(s->data, 1, excpt, ctx);

            // We may trigger a safepoint so make sure we refcount our locoal.
            GC_CCTOR(sink, binpac_sink, ctx);
            GC_CCTOR(data, hlt_bytes, ctx);
            __cctor_state(s, ctx);

            (s->parser->parse_func_sink)(s->pobj, s->data, user, &sink_excpt, ctx);

            GC_DTOR(sink, binpac_sink, ctx);
            GC_DTOR(data, hlt_bytes, ctx);
            __dtor_state(s, ctx);
        }

        else {
            if ( ! s->resume ) {
                // Parsing has already finished for this parser. We ignore this here,
                // as otherwise we'd have to throw an exception and thus abort the
                // other parsers as well.
                s = s->next;
                continue;
            }

            DBG_LOG("binpac-sinks", "- resuming delivering to sink %p for parser %p", sink, s->pobj);

            // Subsequent chunk, resume.
            hlt_bytes_append(s->data, data, excpt, ctx);

            if ( hlt_bytes_is_frozen(data, excpt, ctx) )
                hlt_bytes_freeze(s->data, 1, excpt, ctx);

            // We may trigger a safepoint so make sure we refcount our locoal.
            GC_CCTOR(sink, binpac_sink, ctx);
            GC_CCTOR(data, hlt_bytes, ctx);
            __cctor_state(s, ctx);

            (s->parser->resume_func_sink)(s->resume, &sink_excpt, ctx);

            GC_DTOR(sink, binpac_sink, ctx);
            GC_DTOR(data, hlt_bytes, ctx);
            __dtor_state(s, ctx);

            GC_CLEAR(s->resume, hlt_exception, ctx);
        }

        // Clear any left-over exceptions.
        __hlt_context_clear_exception(ctx);

        if ( sink_excpt && sink_excpt->type == &hlt_exception_yield ) {
            // Suspended.
            DBG_LOG("binpac-sinks", "- delivering to sink %p suspended for parser %p", sink, s->pobj);
            GC_CCTOR(sink_excpt, hlt_exception, ctx);
            s->resume = sink_excpt;
            s = s->next;
            sink_excpt = 0;
        }

        else if ( sink_excpt && sink_excpt->type == &binpac_exception_parserdisabled ) {
            // Disabled
            DBG_LOG("binpac-sinks", "- writing to sink %p disabled for parser %p", sink, s->pobj);
            GC_DTOR(sink_excpt, hlt_exception, ctx);
            sink_excpt = 0;
            __parser_state* next = s->next;
            // This guy is finished, remove.
            __unlink_state(sink, s, ctx);
            s = next;
        }

        else {
            DBG_LOG("binpac-sinks", "- delivering to sink %p finished for parser %p", sink, s->pobj);
            __parser_state* next = s->next;
            // This guy is finished, remove.
            __unlink_state(sink, s, ctx);
            s = next;
        }

        if ( sink_excpt ) {
            // Error, abort.
            *excpt = sink_excpt;
            goto exit;
        }
    }

    // Savely delete disconnected parsers.

    int done = 0;

    while ( ! done ) {
        done = 1;
        for ( __parser_state* s = sink->head; s; s = s->next ) {
            if ( s->disconnected ) {
                // We ignore parse error triggered by the disconnect.
                hlt_exception* ignore_excpt = 0;
                __finish_parser(sink, s, &ignore_excpt, ctx);

                if ( ignore_excpt )
                    GC_DTOR(ignore_excpt, hlt_exception, ctx);

                done = 0;
                break;
            }
        }
    }

exit:
    ctx->fiber = saved_fiber;
    ctx->blockable = saved_blockable;

    sink->cur_rseq = rupper;
    sink->last_reassem_rseq = rupper;

    if ( sink->auto_trim )
        __trim(sink, rupper, user, excpt, ctx);

    DBG_LOG("binpac-sinks", "done delivering to sink %p", sink);

    return 1;
}
示例#7
0
文件: mime.c 项目: Chunjie/hilti
void __mime_parser_dtor(hlt_type_info* ti, __mime_parser* mime_parser, hlt_execution_context* ctx)
{
    GC_CLEAR(mime_parser->parser, hlt_BinPACHilti_Parser, ctx);
    GC_CLEAR(mime_parser->next, __mime_parser, ctx);
}
示例#8
0
文件: context.c 项目: rsmmr/hilti
void __hlt_context_clear_exception(hlt_execution_context* ctx)
{
    GC_CLEAR(ctx->excpt, hlt_exception, ctx);
}