/** * 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); } }
/** * 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); } }