Ejemplo n.º 1
0
/**
 * Process data from ATS.
 *
 * Process data from one of the ATS events.
 *
 * @param[in,out] contp - the continuation
 * @param[in,out] ibd - the filter descriptor
 */
static void process_data(TSCont contp, ibd_ctx *ibd)
{
    int64_t ntodo;
    int64_t navail;
    TSIOBufferReader input_reader, output_reader;
    TSIOBufferBlock block;
    const char *buf;
    int64_t nbytes;
    ib_status_t rc;

    tsib_filter_ctx *fctx = ibd->data;

    tsib_txn_ctx *txndata = TSContDataGet(contp);
    TSVIO  input_vio = TSVConnWriteVIOGet(contp);
    TSIOBuffer in_buf = TSVIOBufferGet(input_vio);

    /* Test whether we're going into an errordoc */
    if (HTTP_CODE(txndata->status)) {  /* We're going to an error document,
                                        * so we discard all this data
                                        */
        ib_log_debug2_tx(txndata->tx, "Status is %d, discarding", txndata->status);
        ibd->data->buffering = IOBUF_DISCARD;
    }

    /* Test for EOS */
    if (in_buf == NULL) {
        if (fctx->output_buffer != NULL) {
            /* flush anything we have buffered.  This is final! */
            rc = flush_data(fctx, -1, 1);
            switch(rc) {
              case IB_OK:
                break;
              case IB_EBADVAL:
                ib_log_error_tx(txndata->tx, "Bad/Inconsistent stream edit(s) ignored.");
                break;
              default:  /* Can't happen unless a new status is introduced */
                ib_log_error_tx(txndata->tx, "Unhandled return value %d", rc);
                break;
            }
        }
        else {
            /* I guess NULL input may mean something other than EOS.
             * This appears to be possible when
             * processing an HTTP error from the backend.
             */
            ib_log_debug2_tx(txndata->tx, "Filter input was null.  No filtering.");
            /* RNS-1268: seems we may have to go through all the motions
             * of creating and enabling an output_vio with no data.
             */
            fctx->output_buffer = TSIOBufferCreate();
            ib_mm_register_cleanup(txndata->tx->mm,
                                   (ib_mm_cleanup_fn_t) TSIOBufferDestroy,
                                   (void*) fctx->output_buffer);
            output_reader = TSIOBufferReaderAlloc(fctx->output_buffer);
            fctx->output_vio = TSVConnWrite(TSTransformOutputVConnGet(contp), contp, output_reader, 0);
            TSVIOReenable(fctx->output_vio);
        }
        return;
    }

    /* Test for first time, and initialise.  */
    if (!fctx->output_buffer) {
        // FIXME - What to choose here and why?
        int64_t output_vio_sz = TSVIONBytesGet(input_vio);
        // NOTE: Using INT64_MAX asserts on 4.2.2: InkAPI.cc:6261: failed assert `sdk_sanity_check_iocore_structure(connp) == TS_SUCCESS`
        //int64_t output_vio_sz = INT64_MAX;
        // NOTE: Does it matter that this is only INT32_MAX as in the examples?
        // int64_t output_vio_sz = INT32_MAX;
        //int64_t output_vio_sz = fctx->have_edits
        //                        ? INT64_MAX
        //                        : TSVIONBytesGet(input_vio);
        fctx->output_buffer = TSIOBufferCreate();
        ib_mm_register_cleanup(txndata->tx->mm,
                               (ib_mm_cleanup_fn_t) TSIOBufferDestroy,
                               (void*) fctx->output_buffer);
        // FIXME - Where is TSIOBufferReaderFree()?
        output_reader = TSIOBufferReaderAlloc(fctx->output_buffer);
        fctx->output_vio = TSVConnWrite(TSTransformOutputVConnGet(contp), contp, output_reader, output_vio_sz);

        fctx->buffer = TSIOBufferCreate();
        ib_mm_register_cleanup(txndata->tx->mm,
                               (ib_mm_cleanup_fn_t) TSIOBufferDestroy,
                               (void*) fctx->buffer);
        // FIXME - Where is TSIOBufferReaderFree()?
        fctx->reader = TSIOBufferReaderAlloc(fctx->buffer);

        /* Get the buffering config */
        if (!HTTP_CODE(txndata->status)) {
            buffer_init(ibd, txndata->tx);
        }
    }

    /* Get any unprocessed bytes. */
    ntodo = TSVIONTodoGet(input_vio);

    /* Test for EOS */
    if (ntodo == 0) {
        ib_log_debug2_tx(txndata->tx, "ntodo zero before consuming data");

        flush_data(fctx, -1, 1);

        /* Call back the input VIO continuation to let it know that we
         * have completed the write operation.
         */
        TSContCall(TSVIOContGet(input_vio), TS_EVENT_VCONN_WRITE_COMPLETE, input_vio);
        return;
    }

    /* OK, there's some input awaiting our attention */
    input_reader = TSVIOReaderGet(input_vio);
    while (navail = TSIOBufferReaderAvail(input_reader), navail > 0) {
        block = TSIOBufferReaderStart(input_reader);
        buf = TSIOBufferBlockReadStart(block, input_reader, &nbytes);
        rc = (*ibd->ibd->ib_notify_body)(txndata->tx->ib, txndata->tx, buf, nbytes);
        if (rc != IB_OK) {
            ib_log_error_tx(txndata->tx, "Error %d notifying body data.", rc);
        }
        rc = buffer_data_chunk(fctx, input_reader, nbytes);
        switch (rc) {
          case IB_EAGAIN:
          case IB_OK:
            break;
          case IB_EBADVAL:
            ib_log_error_tx(txndata->tx, "Bad/Inconsistent stream edit(s) ignored.");
            break;
          default:  /* Can't happen unless a new status is introduced */
            ib_log_error_tx(txndata->tx, "Unhandled return value %d", rc);
            break;
        }
        TSIOBufferReaderConsume(input_reader, nbytes);
        TSVIONDoneSet(input_vio, TSVIONDoneGet(input_vio) + nbytes);
    }

    ntodo = TSVIONTodoGet(input_vio);
    if (ntodo == 0) {
        ib_log_debug2_tx(txndata->tx, "ntodo zero after consuming data");

        flush_data(fctx, -1, 1);

        /* Call back the input VIO continuation to let it know that we
         * have completed the write operation.
         */
        TSContCall(TSVIOContGet(input_vio), TS_EVENT_VCONN_WRITE_COMPLETE, input_vio);
    }
    else {
        /* Call back the input VIO continuation to let it know that we
         * are ready for more data.
         */
        TSContCall(TSVIOContGet(input_vio), TS_EVENT_VCONN_WRITE_READY, input_vio);
    }
}
Ejemplo n.º 2
0
/**
 * Process data from ATS.
 *
 * Process data from one of the ATS events.
 *
 * @param[in,out] contp - the continuation
 * @param[in,out] ibd - the filter descriptor
 */
static void process_data(TSCont contp, ibd_ctx *ibd)
{
    int64_t ntodo;
    int64_t navail;
    TSIOBufferReader input_reader, output_reader;
    TSIOBufferBlock block;
    const char *buf;
    int64_t nbytes;
    ib_status_t rc;

    ib_filter_ctx *fctx = ibd->data;

    ib_txn_ctx *data = TSContDataGet(contp);
    TSVIO  input_vio = TSVConnWriteVIOGet(contp);
    TSIOBuffer in_buf = TSVIOBufferGet(input_vio);

    /* Test whether we're going into an errordoc */
    if (IB_HTTP_CODE(data->status)) {  /* We're going to an error document,
                                        * so we discard all this data
                                        */
        TSDebug("ironbee", "Status is %d, discarding", data->status);
        ibd->data->buffering = IOBUF_DISCARD;
    }

    /* Test for EOS */
    if (in_buf == NULL) {
        /* flush anything we have buffered.  This is final! */
        flush_data(fctx, -1, 1);
        return;
    }

    ntodo = TSVIONTodoGet(input_vio);

    /* Test for first time, and initialise.  */
    if (!fctx->output_buffer) {
        fctx->output_buffer = TSIOBufferCreate();
        ib_mm_register_cleanup(data->tx->mm,
                               (ib_mm_cleanup_fn_t) TSIOBufferDestroy,
                               (void*) fctx->output_buffer);
        output_reader = TSIOBufferReaderAlloc(fctx->output_buffer);
        fctx->output_vio = TSVConnWrite(TSTransformOutputVConnGet(contp), contp, output_reader, TSVIONBytesGet(input_vio));

        fctx->buffer = TSIOBufferCreate();
        ib_mm_register_cleanup(data->tx->mm,
                               (ib_mm_cleanup_fn_t) TSIOBufferDestroy,
                               (void*) fctx->buffer);
        fctx->reader = TSIOBufferReaderAlloc(fctx->buffer);

        /* Get the buffering config */
        if (!IB_HTTP_CODE(data->status)) {
            buffer_init(ibd, data->tx);
        }

/* Do we still have to delay feeding the first data to Ironbee
 * to keep the IB events in their proper order?
 *
 * Appears maybe not, so let's do nothing until it shows signs of breakage.
 */
#if BUFFER_FIRST
        /* First time through we can only buffer data until headers are sent. */
        fctx->first_time = 1;
        input_reader = TSVIOReaderGet(input_vio);
        fctx->buffered = TSIOBufferCopy(fctx->buffer, TSVIOReaderGet(input_vio),
                                        ntodo, 0);
        TSIOBufferReaderConsume(input_reader, fctx->buffered);

        /* Do we need to request more input or just continue? */
        TSVIONDoneSet(input_vio, fctx->buffu`ered + fctx->bytes_done);

        TSContCall(TSVIOContGet(input_vio), TS_EVENT_VCONN_WRITE_READY, input_vio);
        return;
#endif
    }

    /* second time through we have to feed already-buffered data through
     * ironbee while retaining it in buffer.  Regardless of what else happens.
     */
#if BUFFER_FIRST
    if (fctx->first_time) {
        fctx->first_time = 0;
        for (block = TSIOBufferStart(fctx->buffer);
	     block != NULL;
             block = TSIOBufferBlockNext(block)) {

            //nbytes = TSIOBufferBlockDataSizeGet(block);
            /* FIXME - do this without a reader ? */
            buf = TSIOBufferBlockReadStart(block, fctx->reader, &nbytes);
            //rc = examine_data_chunk(ibd->ibd, data->tx, buf, nbytes);
            rc = (*ibd->ibd->ib_notify_body)(data->tx->ib, data->tx, buf, nbytes);
            if (rc != IB_OK) {
                // FIXME ???
            }
        }
    }
#endif

    /* Test for EOS */
    if (ntodo == 0) {
        TSDebug("[ironbee]", "ntodo zero before consuming data");
        /* Call back the input VIO continuation to let it know that we
         * have completed the write operation.
         */
        TSContCall(TSVIOContGet(input_vio), TS_EVENT_VCONN_WRITE_COMPLETE, input_vio);
        return;
    }

    /* OK, there's some input awaiting our attention */
    input_reader = TSVIOReaderGet(input_vio);
    while (navail = TSIOBufferReaderAvail(input_reader), navail > 0) {
        block = TSIOBufferReaderStart(input_reader);
        buf = TSIOBufferBlockReadStart(block, input_reader, &nbytes);
        rc = (*ibd->ibd->ib_notify_body)(data->tx->ib, data->tx, buf, nbytes);
        if (rc != IB_OK) {
            // FIXME ???
        }
        rc = buffer_data_chunk(fctx, input_reader, nbytes);
        if (rc != IB_OK) {
            // FIXME ???
        }
        TSIOBufferReaderConsume(input_reader, nbytes);
        TSVIONDoneSet(input_vio, TSVIONDoneGet(input_vio) + nbytes);
    }

    ntodo = TSVIONTodoGet(input_vio);
    if (ntodo == 0) {
        TSDebug("[ironbee]", "ntodo zero after consuming data");
        /* Call back the input VIO continuation to let it know that we
         * have completed the write operation.
         */
        TSContCall(TSVIOContGet(input_vio), TS_EVENT_VCONN_WRITE_COMPLETE, input_vio);
    }
    else {
        /* Call back the input VIO continuation to let it know that we
         * are ready for more data.
         */
        TSContCall(TSVIOContGet(input_vio), TS_EVENT_VCONN_WRITE_READY, input_vio);
    }
}