You are viewing a plain text version of this content. The canonical link for it is here.
Posted to github@trafficserver.apache.org by "shukitchan (via GitHub)" <gi...@apache.org> on 2023/07/12 18:37:40 UTC

[GitHub] [trafficserver] shukitchan opened a new pull request, #10004: Add support for request/response transform

shukitchan opened a new pull request, #10004:
URL: https://github.com/apache/trafficserver/pull/10004

   (no comment)


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@trafficserver.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


[GitHub] [trafficserver] shukitchan commented on a diff in pull request #10004: Add support for request/response transform for Wasm plugin

Posted by "shukitchan (via GitHub)" <gi...@apache.org>.
shukitchan commented on code in PR #10004:
URL: https://github.com/apache/trafficserver/pull/10004#discussion_r1276989473


##########
plugins/experimental/wasm/wasm_main.cc:
##########
@@ -46,6 +46,249 @@ struct WasmInstanceConfig {
 
 static std::unique_ptr<WasmInstanceConfig> wasm_config = nullptr;
 
+// handler for transform event
+static int
+transform_handler(TSCont contp, ats_wasm::TransformInfo *ti, TSEvent event)

Review Comment:
   let me remove this



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@trafficserver.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


[GitHub] [trafficserver] shukitchan commented on a diff in pull request #10004: Add support for request/response transform for Wasm plugin

Posted by "shukitchan (via GitHub)" <gi...@apache.org>.
shukitchan commented on code in PR #10004:
URL: https://github.com/apache/trafficserver/pull/10004#discussion_r1274170955


##########
plugins/experimental/wasm/wasm_main.cc:
##########
@@ -46,6 +46,250 @@ struct WasmInstanceConfig {
 
 static std::unique_ptr<WasmInstanceConfig> wasm_config = nullptr;
 
+// handler for transform event
+static int
+transform_handler(TSCont contp, ats_wasm::TransformInfo *ti, TSEvent event)
+{
+  TSVConn output_conn;
+  TSVIO input_vio;
+  TSIOBufferReader input_reader;
+  TSIOBufferBlock blk;
+  int64_t toread, towrite, blk_len, upstream_done, input_avail;
+  const char *start;
+  const char *res;
+  size_t res_len;
+  int eos, write_down, empty_input;
+
+  ats_wasm::Context *c;
+
+  TSDebug(WASM_DEBUG_TAG, "[%s] transform handler begins", __FUNCTION__);
+  c = ti->context;
+
+  output_conn = TSTransformOutputVConnGet(contp);
+  input_vio   = TSVConnWriteVIOGet(contp);
+
+  empty_input = 0;
+
+  TSDebug(WASM_DEBUG_TAG, "[%s] cheking input VIO", __FUNCTION__);
+  if (!TSVIOBufferGet(input_vio)) {
+    if (ti->output_vio) {
+      TSDebug(WASM_DEBUG_TAG, "[%s] reenabling output VIO after input VIO does not exist", __FUNCTION__);
+      TSVIONBytesSet(ti->output_vio, ti->total);
+      TSVIOReenable(ti->output_vio);
+      return 0;
+    } else {
+      TSDebug(WASM_DEBUG_TAG, "[%s] no input VIO and output VIO", __FUNCTION__);
+      empty_input = 1;
+    }
+  }
+
+  if (empty_input == 0) {
+    input_reader = TSVIOReaderGet(input_vio);
+  }
+
+  TSDebug(WASM_DEBUG_TAG, "[%s] creating buffer and reader", __FUNCTION__);
+  if (!ti->output_buffer) {
+    ti->output_buffer = TSIOBufferCreate();
+    ti->output_reader = TSIOBufferReaderAlloc(ti->output_buffer);
+
+    ti->reserved_buffer = TSIOBufferCreate();
+    ti->reserved_reader = TSIOBufferReaderAlloc(ti->reserved_buffer);
+
+    if (empty_input == 0) {
+      ti->upstream_bytes = TSVIONBytesGet(input_vio);
+    } else {
+      ti->upstream_bytes = 0;
+    }
+
+    ti->downstream_bytes = INT64_MAX;
+  }
+
+  TSDebug(WASM_DEBUG_TAG, "[%s] init variables inside handler", __FUNCTION__);
+  if (empty_input == 0) {
+    input_avail   = TSIOBufferReaderAvail(input_reader);
+    upstream_done = TSVIONDoneGet(input_vio);
+    toread        = TSVIONTodoGet(input_vio);
+
+    if (toread <= input_avail) { // upstream finished
+      eos = 1;
+    } else {
+      eos = 0;
+    }
+  } else {
+    input_avail   = 0;
+    upstream_done = 0;
+    toread        = 0;
+    eos           = 1;
+  }
+
+  if (input_avail > 0) {
+    // move to the reserved.buffer
+    TSIOBufferCopy(ti->reserved_buffer, input_reader, input_avail, 0);
+
+    // reset input
+    TSIOBufferReaderConsume(input_reader, input_avail);
+    TSVIONDoneSet(input_vio, upstream_done + input_avail);
+  }
+
+  write_down = 0;
+  if (empty_input == 0) {
+    towrite = TSIOBufferReaderAvail(ti->reserved_reader);
+  } else {
+    towrite = 0;
+  }
+
+  do {
+    TSDebug(WASM_DEBUG_TAG, "[%s] inside transform handler loop", __FUNCTION__);
+    proxy_wasm::FilterDataStatus status = proxy_wasm::FilterDataStatus::Continue;
+
+    if (towrite == 0 && empty_input == 0) {
+      break;
+    }
+
+    TSDebug(WASM_DEBUG_TAG, "[%s] retrieving text and calling the wasm handler function", __FUNCTION__);
+    if (empty_input == 0) {
+      blk   = TSIOBufferReaderStart(ti->reserved_reader);
+      start = TSIOBufferBlockReadStart(blk, ti->reserved_reader, &blk_len);
+
+      int size = 0;
+      if (towrite > blk_len) {
+        c->setTransformResult(start, blk_len);
+        towrite -= blk_len;
+        TSIOBufferReaderConsume(ti->reserved_reader, blk_len);
+        size = blk_len;
+      } else {
+        c->setTransformResult(start, towrite);
+        TSIOBufferReaderConsume(ti->reserved_reader, towrite);
+        size    = towrite;
+        towrite = 0;
+      }
+
+      if (!towrite && eos) {
+        if (ti->request) {
+          status = c->onRequestBody(size, true);
+        } else {
+          status = c->onResponseBody(size, true);
+        }
+      } else {
+        if (ti->request) {
+          status = c->onRequestBody(size, false);
+        } else {
+          status = c->onResponseBody(size, false);
+        }
+      }
+    } else {
+      c->setTransformResult(nullptr, 0);
+      if (ti->request) {
+        status = c->onRequestBody(0, true);
+      } else {
+        status = c->onResponseBody(0, true);
+      }
+    }
+
+    TSDebug(WASM_DEBUG_TAG, "[%s] retrieving returns from wasm handler function and pass back to ATS", __FUNCTION__);
+    if ((status == proxy_wasm::FilterDataStatus::Continue) ||
+        ((status == proxy_wasm::FilterDataStatus::StopIterationAndBuffer ||
+          status == proxy_wasm::FilterDataStatus::StopIterationAndWatermark) &&
+         eos && !towrite)) {
+      res = c->getTransformResult(&res_len);
+
+      if (res && res_len > 0) {
+        if (!ti->output_vio) {
+          if (eos && !towrite) {
+            ti->output_vio = TSVConnWrite(output_conn, contp, ti->output_reader, res_len); // HttpSM go on
+          } else {
+            ti->output_vio = TSVConnWrite(output_conn, contp, ti->output_reader, ti->downstream_bytes); // HttpSM go on
+          }
+        }
+
+        TSIOBufferWrite(ti->output_buffer, res, res_len);
+        ti->total  += res_len;
+        write_down  = 1;
+      }
+
+      c->clearTransformResult();
+    }
+
+    if (status == proxy_wasm::FilterDataStatus::StopIterationNoBuffer) {
+      c->clearTransformResult();
+    }
+
+    if (eos && !towrite) { // EOS
+      eos = 1;

Review Comment:
   that's right



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@trafficserver.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


[GitHub] [trafficserver] shukitchan commented on a diff in pull request #10004: Add support for request/response transform for Wasm plugin

Posted by "shukitchan (via GitHub)" <gi...@apache.org>.
shukitchan commented on code in PR #10004:
URL: https://github.com/apache/trafficserver/pull/10004#discussion_r1274179901


##########
plugins/experimental/wasm/wasm_main.cc:
##########
@@ -46,6 +46,250 @@ struct WasmInstanceConfig {
 
 static std::unique_ptr<WasmInstanceConfig> wasm_config = nullptr;
 
+// handler for transform event
+static int
+transform_handler(TSCont contp, ats_wasm::TransformInfo *ti, TSEvent event)
+{
+  TSVConn output_conn;
+  TSVIO input_vio;
+  TSIOBufferReader input_reader;
+  TSIOBufferBlock blk;
+  int64_t toread, towrite, blk_len, upstream_done, input_avail;
+  const char *start;
+  const char *res;
+  size_t res_len;
+  int eos, write_down, empty_input;
+
+  ats_wasm::Context *c;
+
+  TSDebug(WASM_DEBUG_TAG, "[%s] transform handler begins", __FUNCTION__);
+  c = ti->context;
+
+  output_conn = TSTransformOutputVConnGet(contp);
+  input_vio   = TSVConnWriteVIOGet(contp);
+
+  empty_input = 0;
+
+  TSDebug(WASM_DEBUG_TAG, "[%s] cheking input VIO", __FUNCTION__);
+  if (!TSVIOBufferGet(input_vio)) {
+    if (ti->output_vio) {
+      TSDebug(WASM_DEBUG_TAG, "[%s] reenabling output VIO after input VIO does not exist", __FUNCTION__);
+      TSVIONBytesSet(ti->output_vio, ti->total);
+      TSVIOReenable(ti->output_vio);
+      return 0;
+    } else {
+      TSDebug(WASM_DEBUG_TAG, "[%s] no input VIO and output VIO", __FUNCTION__);
+      empty_input = 1;
+    }
+  }
+
+  if (empty_input == 0) {
+    input_reader = TSVIOReaderGet(input_vio);
+  }
+
+  TSDebug(WASM_DEBUG_TAG, "[%s] creating buffer and reader", __FUNCTION__);
+  if (!ti->output_buffer) {
+    ti->output_buffer = TSIOBufferCreate();
+    ti->output_reader = TSIOBufferReaderAlloc(ti->output_buffer);
+
+    ti->reserved_buffer = TSIOBufferCreate();
+    ti->reserved_reader = TSIOBufferReaderAlloc(ti->reserved_buffer);
+
+    if (empty_input == 0) {
+      ti->upstream_bytes = TSVIONBytesGet(input_vio);
+    } else {
+      ti->upstream_bytes = 0;
+    }
+
+    ti->downstream_bytes = INT64_MAX;
+  }
+
+  TSDebug(WASM_DEBUG_TAG, "[%s] init variables inside handler", __FUNCTION__);
+  if (empty_input == 0) {
+    input_avail   = TSIOBufferReaderAvail(input_reader);
+    upstream_done = TSVIONDoneGet(input_vio);
+    toread        = TSVIONTodoGet(input_vio);
+
+    if (toread <= input_avail) { // upstream finished
+      eos = 1;
+    } else {
+      eos = 0;
+    }
+  } else {
+    input_avail   = 0;
+    upstream_done = 0;
+    toread        = 0;
+    eos           = 1;
+  }
+
+  if (input_avail > 0) {
+    // move to the reserved.buffer
+    TSIOBufferCopy(ti->reserved_buffer, input_reader, input_avail, 0);

Review Comment:
   "reserved" is for temporarily storing the current block. That block will be passed to the wasm module for the provided function to process. And "output" is for actually taking the processed result out to pass it back to ATS



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@trafficserver.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


[GitHub] [trafficserver] serrislew commented on a diff in pull request #10004: Add support for request/response transform for Wasm plugin

Posted by "serrislew (via GitHub)" <gi...@apache.org>.
serrislew commented on code in PR #10004:
URL: https://github.com/apache/trafficserver/pull/10004#discussion_r1276683359


##########
plugins/experimental/wasm/wasm_main.cc:
##########
@@ -46,6 +46,249 @@ struct WasmInstanceConfig {
 
 static std::unique_ptr<WasmInstanceConfig> wasm_config = nullptr;
 
+// handler for transform event
+static int
+transform_handler(TSCont contp, ats_wasm::TransformInfo *ti, TSEvent event)
+{
+  TSVConn output_conn;
+  TSVIO input_vio;
+  TSIOBufferReader input_reader;
+  TSIOBufferBlock blk;
+  int64_t toread, towrite, blk_len, upstream_done, input_avail;
+  const char *start;
+  const char *res;
+  size_t res_len;
+  bool eos, write_down, empty_input;
+
+  ats_wasm::Context *c;
+
+  TSDebug(WASM_DEBUG_TAG, "[%s] transform handler begins", __FUNCTION__);
+  c = ti->context;
+
+  output_conn = TSTransformOutputVConnGet(contp);
+  input_vio   = TSVConnWriteVIOGet(contp);
+
+  empty_input = false;
+
+  TSDebug(WASM_DEBUG_TAG, "[%s] cheking input VIO", __FUNCTION__);
+  if (!TSVIOBufferGet(input_vio)) {
+    if (ti->output_vio) {
+      TSDebug(WASM_DEBUG_TAG, "[%s] reenabling output VIO after input VIO does not exist", __FUNCTION__);
+      TSVIONBytesSet(ti->output_vio, ti->total);
+      TSVIOReenable(ti->output_vio);
+      return 0;
+    } else {
+      TSDebug(WASM_DEBUG_TAG, "[%s] no input VIO and output VIO", __FUNCTION__);
+      empty_input = true;
+    }
+  }
+
+  if (!empty_input) {
+    input_reader = TSVIOReaderGet(input_vio);
+  }
+
+  TSDebug(WASM_DEBUG_TAG, "[%s] creating buffer and reader", __FUNCTION__);
+  if (!ti->output_buffer) {
+    ti->output_buffer = TSIOBufferCreate();
+    ti->output_reader = TSIOBufferReaderAlloc(ti->output_buffer);
+
+    ti->reserved_buffer = TSIOBufferCreate();
+    ti->reserved_reader = TSIOBufferReaderAlloc(ti->reserved_buffer);
+
+    if (!empty_input) {
+      ti->upstream_bytes = TSVIONBytesGet(input_vio);
+    } else {
+      ti->upstream_bytes = 0;
+    }
+
+    ti->downstream_bytes = INT64_MAX;
+  }
+
+  TSDebug(WASM_DEBUG_TAG, "[%s] init variables inside handler", __FUNCTION__);
+  if (!empty_input) {
+    input_avail   = TSIOBufferReaderAvail(input_reader);
+    upstream_done = TSVIONDoneGet(input_vio);
+    toread        = TSVIONTodoGet(input_vio);
+
+    if (toread <= input_avail) { // upstream finished
+      eos = true;
+    } else {
+      eos = false;
+    }
+  } else {
+    input_avail   = 0;
+    upstream_done = 0;
+    toread        = 0;
+    eos           = true;
+  }
+
+  if (input_avail > 0) {

Review Comment:
   if `toread` < `input_avail`, would we only want to copy `toread` bytes? or does it not matter if we copy more than needed? 



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@trafficserver.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


[GitHub] [trafficserver] shukitchan commented on a diff in pull request #10004: Add support for request/response transform for Wasm plugin

Posted by "shukitchan (via GitHub)" <gi...@apache.org>.
shukitchan commented on code in PR #10004:
URL: https://github.com/apache/trafficserver/pull/10004#discussion_r1274175435


##########
plugins/experimental/wasm/wasm_main.cc:
##########
@@ -46,6 +46,250 @@ struct WasmInstanceConfig {
 
 static std::unique_ptr<WasmInstanceConfig> wasm_config = nullptr;
 
+// handler for transform event
+static int
+transform_handler(TSCont contp, ats_wasm::TransformInfo *ti, TSEvent event)
+{
+  TSVConn output_conn;
+  TSVIO input_vio;
+  TSIOBufferReader input_reader;
+  TSIOBufferBlock blk;
+  int64_t toread, towrite, blk_len, upstream_done, input_avail;
+  const char *start;
+  const char *res;
+  size_t res_len;
+  int eos, write_down, empty_input;
+
+  ats_wasm::Context *c;
+
+  TSDebug(WASM_DEBUG_TAG, "[%s] transform handler begins", __FUNCTION__);
+  c = ti->context;
+
+  output_conn = TSTransformOutputVConnGet(contp);
+  input_vio   = TSVConnWriteVIOGet(contp);
+
+  empty_input = 0;
+
+  TSDebug(WASM_DEBUG_TAG, "[%s] cheking input VIO", __FUNCTION__);
+  if (!TSVIOBufferGet(input_vio)) {
+    if (ti->output_vio) {
+      TSDebug(WASM_DEBUG_TAG, "[%s] reenabling output VIO after input VIO does not exist", __FUNCTION__);
+      TSVIONBytesSet(ti->output_vio, ti->total);
+      TSVIOReenable(ti->output_vio);
+      return 0;
+    } else {
+      TSDebug(WASM_DEBUG_TAG, "[%s] no input VIO and output VIO", __FUNCTION__);
+      empty_input = 1;
+    }
+  }
+
+  if (empty_input == 0) {
+    input_reader = TSVIOReaderGet(input_vio);
+  }
+
+  TSDebug(WASM_DEBUG_TAG, "[%s] creating buffer and reader", __FUNCTION__);
+  if (!ti->output_buffer) {
+    ti->output_buffer = TSIOBufferCreate();
+    ti->output_reader = TSIOBufferReaderAlloc(ti->output_buffer);
+
+    ti->reserved_buffer = TSIOBufferCreate();
+    ti->reserved_reader = TSIOBufferReaderAlloc(ti->reserved_buffer);
+
+    if (empty_input == 0) {
+      ti->upstream_bytes = TSVIONBytesGet(input_vio);
+    } else {
+      ti->upstream_bytes = 0;
+    }
+
+    ti->downstream_bytes = INT64_MAX;
+  }
+
+  TSDebug(WASM_DEBUG_TAG, "[%s] init variables inside handler", __FUNCTION__);
+  if (empty_input == 0) {
+    input_avail   = TSIOBufferReaderAvail(input_reader);
+    upstream_done = TSVIONDoneGet(input_vio);
+    toread        = TSVIONTodoGet(input_vio);
+
+    if (toread <= input_avail) { // upstream finished
+      eos = 1;
+    } else {
+      eos = 0;
+    }
+  } else {
+    input_avail   = 0;
+    upstream_done = 0;
+    toread        = 0;
+    eos           = 1;
+  }
+
+  if (input_avail > 0) {
+    // move to the reserved.buffer
+    TSIOBufferCopy(ti->reserved_buffer, input_reader, input_avail, 0);
+
+    // reset input
+    TSIOBufferReaderConsume(input_reader, input_avail);
+    TSVIONDoneSet(input_vio, upstream_done + input_avail);
+  }
+
+  write_down = 0;
+  if (empty_input == 0) {
+    towrite = TSIOBufferReaderAvail(ti->reserved_reader);
+  } else {
+    towrite = 0;
+  }
+
+  do {
+    TSDebug(WASM_DEBUG_TAG, "[%s] inside transform handler loop", __FUNCTION__);
+    proxy_wasm::FilterDataStatus status = proxy_wasm::FilterDataStatus::Continue;
+
+    if (towrite == 0 && empty_input == 0) {
+      break;
+    }
+
+    TSDebug(WASM_DEBUG_TAG, "[%s] retrieving text and calling the wasm handler function", __FUNCTION__);
+    if (empty_input == 0) {
+      blk   = TSIOBufferReaderStart(ti->reserved_reader);
+      start = TSIOBufferBlockReadStart(blk, ti->reserved_reader, &blk_len);
+
+      int size = 0;
+      if (towrite > blk_len) {
+        c->setTransformResult(start, blk_len);
+        towrite -= blk_len;
+        TSIOBufferReaderConsume(ti->reserved_reader, blk_len);
+        size = blk_len;
+      } else {
+        c->setTransformResult(start, towrite);
+        TSIOBufferReaderConsume(ti->reserved_reader, towrite);
+        size    = towrite;
+        towrite = 0;
+      }
+
+      if (!towrite && eos) {
+        if (ti->request) {
+          status = c->onRequestBody(size, true);
+        } else {
+          status = c->onResponseBody(size, true);
+        }
+      } else {
+        if (ti->request) {
+          status = c->onRequestBody(size, false);
+        } else {
+          status = c->onResponseBody(size, false);
+        }
+      }
+    } else {
+      c->setTransformResult(nullptr, 0);
+      if (ti->request) {
+        status = c->onRequestBody(0, true);
+      } else {
+        status = c->onResponseBody(0, true);
+      }
+    }
+
+    TSDebug(WASM_DEBUG_TAG, "[%s] retrieving returns from wasm handler function and pass back to ATS", __FUNCTION__);
+    if ((status == proxy_wasm::FilterDataStatus::Continue) ||
+        ((status == proxy_wasm::FilterDataStatus::StopIterationAndBuffer ||
+          status == proxy_wasm::FilterDataStatus::StopIterationAndWatermark) &&
+         eos && !towrite)) {
+      res = c->getTransformResult(&res_len);
+
+      if (res && res_len > 0) {
+        if (!ti->output_vio) {
+          if (eos && !towrite) {
+            ti->output_vio = TSVConnWrite(output_conn, contp, ti->output_reader, res_len); // HttpSM go on
+          } else {
+            ti->output_vio = TSVConnWrite(output_conn, contp, ti->output_reader, ti->downstream_bytes); // HttpSM go on
+          }
+        }
+
+        TSIOBufferWrite(ti->output_buffer, res, res_len);
+        ti->total  += res_len;
+        write_down  = 1;
+      }
+
+      c->clearTransformResult();
+    }
+
+    if (status == proxy_wasm::FilterDataStatus::StopIterationNoBuffer) {
+      c->clearTransformResult();
+    }
+
+    if (eos && !towrite) { // EOS
+      eos = 1;
+      break;
+    }
+
+  } while (towrite > 0);
+
+  if (eos && !ti->output_vio) {
+    ti->output_vio = TSVConnWrite(output_conn, contp, ti->output_reader, 0);
+  }
+
+  if (write_down || eos) {
+    TSVIOReenable(ti->output_vio);
+  }
+
+  if (toread > input_avail) { // upstream not finished.
+    if (eos) {
+      TSVIONBytesSet(ti->output_vio, ti->total);
+      if (empty_input == 0) {
+        TSContCall(TSVIOContGet(input_vio), TS_EVENT_VCONN_EOS, input_vio);
+      }
+    } else {
+      if (empty_input == 0) {
+        TSContCall(TSVIOContGet(input_vio), TS_EVENT_VCONN_WRITE_READY, input_vio);
+      }
+    }
+  } else { // upstream is finished.
+    TSVIONBytesSet(ti->output_vio, ti->total);
+    if (empty_input == 0) {
+      TSContCall(TSVIOContGet(input_vio), TS_EVENT_VCONN_WRITE_COMPLETE, input_vio);
+    }
+  }
+
+  return 0;
+}
+
+static int
+transform_entry(TSCont contp, TSEvent ev, void *edata)
+{
+  int event;
+  TSVIO input_vio;
+  ats_wasm::TransformInfo *ti;
+
+  event = (int)ev;
+  ti    = (ats_wasm::TransformInfo *)TSContDataGet(contp);
+
+  TSDebug(WASM_DEBUG_TAG, "[%s] begin transform entry", __FUNCTION__);
+  if (TSVConnClosedGet(contp)) {
+    delete ti;
+    TSContDestroy(contp);
+    return 0;
+  }
+
+  TSDebug(WASM_DEBUG_TAG, "[%s] checking event inside transform entry", __FUNCTION__);
+  switch (event) {
+  case TS_EVENT_ERROR:
+    TSDebug(WASM_DEBUG_TAG, "[%s] event error", __FUNCTION__);
+    input_vio = TSVConnWriteVIOGet(contp);
+    TSContCall(TSVIOContGet(input_vio), TS_EVENT_ERROR, input_vio);
+    break;
+
+  case TS_EVENT_VCONN_WRITE_COMPLETE:
+    TSDebug(WASM_DEBUG_TAG, "[%s] event vconn write complete", __FUNCTION__);
+    TSVConnShutdown(TSTransformOutputVConnGet(contp), 0, 1);
+    break;
+
+  case TS_EVENT_VCONN_WRITE_READY:
+  default:

Review Comment:
   I think it will be TS_EVENT_VCONN_WRITE_COMPLETE eventually. 
   I am following the null transform example plugin on the event handling



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@trafficserver.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


[GitHub] [trafficserver] shukitchan commented on a diff in pull request #10004: Add support for request/response transform for Wasm plugin

Posted by "shukitchan (via GitHub)" <gi...@apache.org>.
shukitchan commented on code in PR #10004:
URL: https://github.com/apache/trafficserver/pull/10004#discussion_r1276990941


##########
plugins/experimental/wasm/wasm_main.cc:
##########
@@ -46,6 +46,249 @@ struct WasmInstanceConfig {
 
 static std::unique_ptr<WasmInstanceConfig> wasm_config = nullptr;
 
+// handler for transform event
+static int
+transform_handler(TSCont contp, ats_wasm::TransformInfo *ti, TSEvent event)
+{
+  TSVConn output_conn;
+  TSVIO input_vio;
+  TSIOBufferReader input_reader;
+  TSIOBufferBlock blk;
+  int64_t toread, towrite, blk_len, upstream_done, input_avail;
+  const char *start;
+  const char *res;
+  size_t res_len;
+  bool eos, write_down, empty_input;
+
+  ats_wasm::Context *c;
+
+  TSDebug(WASM_DEBUG_TAG, "[%s] transform handler begins", __FUNCTION__);
+  c = ti->context;
+
+  output_conn = TSTransformOutputVConnGet(contp);
+  input_vio   = TSVConnWriteVIOGet(contp);
+
+  empty_input = false;
+
+  TSDebug(WASM_DEBUG_TAG, "[%s] cheking input VIO", __FUNCTION__);
+  if (!TSVIOBufferGet(input_vio)) {
+    if (ti->output_vio) {
+      TSDebug(WASM_DEBUG_TAG, "[%s] reenabling output VIO after input VIO does not exist", __FUNCTION__);
+      TSVIONBytesSet(ti->output_vio, ti->total);
+      TSVIOReenable(ti->output_vio);
+      return 0;
+    } else {
+      TSDebug(WASM_DEBUG_TAG, "[%s] no input VIO and output VIO", __FUNCTION__);
+      empty_input = true;
+    }
+  }
+
+  if (!empty_input) {
+    input_reader = TSVIOReaderGet(input_vio);
+  }
+
+  TSDebug(WASM_DEBUG_TAG, "[%s] creating buffer and reader", __FUNCTION__);
+  if (!ti->output_buffer) {
+    ti->output_buffer = TSIOBufferCreate();
+    ti->output_reader = TSIOBufferReaderAlloc(ti->output_buffer);
+
+    ti->reserved_buffer = TSIOBufferCreate();
+    ti->reserved_reader = TSIOBufferReaderAlloc(ti->reserved_buffer);
+
+    if (!empty_input) {
+      ti->upstream_bytes = TSVIONBytesGet(input_vio);
+    } else {
+      ti->upstream_bytes = 0;
+    }
+
+    ti->downstream_bytes = INT64_MAX;
+  }
+
+  TSDebug(WASM_DEBUG_TAG, "[%s] init variables inside handler", __FUNCTION__);
+  if (!empty_input) {
+    input_avail   = TSIOBufferReaderAvail(input_reader);
+    upstream_done = TSVIONDoneGet(input_vio);
+    toread        = TSVIONTodoGet(input_vio);
+
+    if (toread <= input_avail) { // upstream finished
+      eos = true;
+    } else {
+      eos = false;
+    }
+  } else {
+    input_avail   = 0;
+    upstream_done = 0;
+    toread        = 0;
+    eos           = true;
+  }
+
+  if (input_avail > 0) {
+    // move to the reserved.buffer
+    TSIOBufferCopy(ti->reserved_buffer, input_reader, input_avail, 0);
+
+    // reset input
+    TSIOBufferReaderConsume(input_reader, input_avail);
+    TSVIONDoneSet(input_vio, upstream_done + input_avail);
+  }
+
+  write_down = false;
+  if (!empty_input) {
+    towrite = TSIOBufferReaderAvail(ti->reserved_reader);
+  } else {
+    towrite = 0;
+  }
+
+  do {
+    TSDebug(WASM_DEBUG_TAG, "[%s] inside transform handler loop", __FUNCTION__);
+    proxy_wasm::FilterDataStatus status = proxy_wasm::FilterDataStatus::Continue;
+
+    if (towrite == 0 && !empty_input) {
+      break;
+    }
+
+    TSDebug(WASM_DEBUG_TAG, "[%s] retrieving text and calling the wasm handler function", __FUNCTION__);
+    if (!empty_input) {
+      blk   = TSIOBufferReaderStart(ti->reserved_reader);
+      start = TSIOBufferBlockReadStart(blk, ti->reserved_reader, &blk_len);
+
+      int size = 0;
+      if (towrite > blk_len) {
+        c->setTransformResult(start, blk_len);
+        towrite -= blk_len;
+        TSIOBufferReaderConsume(ti->reserved_reader, blk_len);
+        size = blk_len;
+      } else {
+        c->setTransformResult(start, towrite);
+        TSIOBufferReaderConsume(ti->reserved_reader, towrite);
+        size    = towrite;
+        towrite = 0;
+      }
+
+      if (!towrite && eos) {
+        if (ti->request) {
+          status = c->onRequestBody(size, true);
+        } else {
+          status = c->onResponseBody(size, true);
+        }
+      } else {
+        if (ti->request) {
+          status = c->onRequestBody(size, false);
+        } else {
+          status = c->onResponseBody(size, false);
+        }
+      }
+    } else {
+      c->setTransformResult(nullptr, 0);
+      if (ti->request) {
+        status = c->onRequestBody(0, true);
+      } else {
+        status = c->onResponseBody(0, true);
+      }
+    }
+
+    TSDebug(WASM_DEBUG_TAG, "[%s] retrieving returns from wasm handler function and pass back to ATS", __FUNCTION__);
+    if ((status == proxy_wasm::FilterDataStatus::Continue) ||
+        ((status == proxy_wasm::FilterDataStatus::StopIterationAndBuffer ||
+          status == proxy_wasm::FilterDataStatus::StopIterationAndWatermark) &&
+         eos && !towrite)) {
+      res = c->getTransformResult(&res_len);
+
+      if (res && res_len > 0) {
+        if (!ti->output_vio) {
+          if (eos && !towrite) {
+            ti->output_vio = TSVConnWrite(output_conn, contp, ti->output_reader, res_len); // HttpSM go on
+          } else {
+            ti->output_vio = TSVConnWrite(output_conn, contp, ti->output_reader, ti->downstream_bytes); // HttpSM go on
+          }
+        }
+
+        TSIOBufferWrite(ti->output_buffer, res, res_len);
+        ti->total  += res_len;
+        write_down  = true;
+      }
+
+      c->clearTransformResult();
+    }
+
+    if (status == proxy_wasm::FilterDataStatus::StopIterationNoBuffer) {
+      c->clearTransformResult();
+    }
+
+    if (eos && !towrite) { // EOS
+      break;
+    }
+
+  } while (towrite > 0);
+
+  if (eos && !ti->output_vio) {
+    ti->output_vio = TSVConnWrite(output_conn, contp, ti->output_reader, 0);
+  }
+
+  if (write_down || eos) {
+    TSVIOReenable(ti->output_vio);
+  }
+
+  if (toread > input_avail) { // upstream not finished.
+    if (eos) {

Review Comment:
   it can be set true by the function in the wasm module. I forgot to retrieve that value and set eos . 
   
   Good find. So that's why you can still have the EOS event below. 



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@trafficserver.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


[GitHub] [trafficserver] shukitchan commented on a diff in pull request #10004: Add support for request/response transform for Wasm plugin

Posted by "shukitchan (via GitHub)" <gi...@apache.org>.
shukitchan commented on code in PR #10004:
URL: https://github.com/apache/trafficserver/pull/10004#discussion_r1275475331


##########
plugins/experimental/wasm/wasm_main.cc:
##########
@@ -46,6 +46,250 @@ struct WasmInstanceConfig {
 
 static std::unique_ptr<WasmInstanceConfig> wasm_config = nullptr;
 
+// handler for transform event
+static int
+transform_handler(TSCont contp, ats_wasm::TransformInfo *ti, TSEvent event)
+{
+  TSVConn output_conn;
+  TSVIO input_vio;
+  TSIOBufferReader input_reader;
+  TSIOBufferBlock blk;
+  int64_t toread, towrite, blk_len, upstream_done, input_avail;
+  const char *start;
+  const char *res;
+  size_t res_len;
+  int eos, write_down, empty_input;
+
+  ats_wasm::Context *c;
+
+  TSDebug(WASM_DEBUG_TAG, "[%s] transform handler begins", __FUNCTION__);
+  c = ti->context;
+
+  output_conn = TSTransformOutputVConnGet(contp);
+  input_vio   = TSVConnWriteVIOGet(contp);
+
+  empty_input = 0;
+
+  TSDebug(WASM_DEBUG_TAG, "[%s] cheking input VIO", __FUNCTION__);
+  if (!TSVIOBufferGet(input_vio)) {
+    if (ti->output_vio) {
+      TSDebug(WASM_DEBUG_TAG, "[%s] reenabling output VIO after input VIO does not exist", __FUNCTION__);
+      TSVIONBytesSet(ti->output_vio, ti->total);
+      TSVIOReenable(ti->output_vio);
+      return 0;
+    } else {
+      TSDebug(WASM_DEBUG_TAG, "[%s] no input VIO and output VIO", __FUNCTION__);
+      empty_input = 1;
+    }
+  }
+
+  if (empty_input == 0) {
+    input_reader = TSVIOReaderGet(input_vio);
+  }
+
+  TSDebug(WASM_DEBUG_TAG, "[%s] creating buffer and reader", __FUNCTION__);
+  if (!ti->output_buffer) {
+    ti->output_buffer = TSIOBufferCreate();
+    ti->output_reader = TSIOBufferReaderAlloc(ti->output_buffer);
+
+    ti->reserved_buffer = TSIOBufferCreate();
+    ti->reserved_reader = TSIOBufferReaderAlloc(ti->reserved_buffer);
+
+    if (empty_input == 0) {
+      ti->upstream_bytes = TSVIONBytesGet(input_vio);
+    } else {
+      ti->upstream_bytes = 0;
+    }
+
+    ti->downstream_bytes = INT64_MAX;
+  }
+
+  TSDebug(WASM_DEBUG_TAG, "[%s] init variables inside handler", __FUNCTION__);
+  if (empty_input == 0) {
+    input_avail   = TSIOBufferReaderAvail(input_reader);
+    upstream_done = TSVIONDoneGet(input_vio);
+    toread        = TSVIONTodoGet(input_vio);
+
+    if (toread <= input_avail) { // upstream finished
+      eos = 1;
+    } else {
+      eos = 0;
+    }
+  } else {
+    input_avail   = 0;
+    upstream_done = 0;
+    toread        = 0;
+    eos           = 1;
+  }
+
+  if (input_avail > 0) {
+    // move to the reserved.buffer
+    TSIOBufferCopy(ti->reserved_buffer, input_reader, input_avail, 0);
+
+    // reset input
+    TSIOBufferReaderConsume(input_reader, input_avail);
+    TSVIONDoneSet(input_vio, upstream_done + input_avail);
+  }
+
+  write_down = 0;
+  if (empty_input == 0) {
+    towrite = TSIOBufferReaderAvail(ti->reserved_reader);
+  } else {
+    towrite = 0;
+  }
+
+  do {
+    TSDebug(WASM_DEBUG_TAG, "[%s] inside transform handler loop", __FUNCTION__);
+    proxy_wasm::FilterDataStatus status = proxy_wasm::FilterDataStatus::Continue;
+
+    if (towrite == 0 && empty_input == 0) {
+      break;
+    }
+
+    TSDebug(WASM_DEBUG_TAG, "[%s] retrieving text and calling the wasm handler function", __FUNCTION__);
+    if (empty_input == 0) {
+      blk   = TSIOBufferReaderStart(ti->reserved_reader);
+      start = TSIOBufferBlockReadStart(blk, ti->reserved_reader, &blk_len);
+
+      int size = 0;
+      if (towrite > blk_len) {
+        c->setTransformResult(start, blk_len);
+        towrite -= blk_len;
+        TSIOBufferReaderConsume(ti->reserved_reader, blk_len);
+        size = blk_len;
+      } else {
+        c->setTransformResult(start, towrite);
+        TSIOBufferReaderConsume(ti->reserved_reader, towrite);
+        size    = towrite;
+        towrite = 0;
+      }
+
+      if (!towrite && eos) {
+        if (ti->request) {
+          status = c->onRequestBody(size, true);
+        } else {
+          status = c->onResponseBody(size, true);
+        }
+      } else {
+        if (ti->request) {
+          status = c->onRequestBody(size, false);
+        } else {
+          status = c->onResponseBody(size, false);
+        }
+      }
+    } else {
+      c->setTransformResult(nullptr, 0);
+      if (ti->request) {
+        status = c->onRequestBody(0, true);
+      } else {
+        status = c->onResponseBody(0, true);
+      }
+    }
+
+    TSDebug(WASM_DEBUG_TAG, "[%s] retrieving returns from wasm handler function and pass back to ATS", __FUNCTION__);
+    if ((status == proxy_wasm::FilterDataStatus::Continue) ||
+        ((status == proxy_wasm::FilterDataStatus::StopIterationAndBuffer ||
+          status == proxy_wasm::FilterDataStatus::StopIterationAndWatermark) &&
+         eos && !towrite)) {
+      res = c->getTransformResult(&res_len);
+
+      if (res && res_len > 0) {
+        if (!ti->output_vio) {
+          if (eos && !towrite) {
+            ti->output_vio = TSVConnWrite(output_conn, contp, ti->output_reader, res_len); // HttpSM go on
+          } else {
+            ti->output_vio = TSVConnWrite(output_conn, contp, ti->output_reader, ti->downstream_bytes); // HttpSM go on

Review Comment:
   Actually there is a check on line 197 for output_vio. 
   so for a long response that comes in multiple block, we will issue TSVConnWrite with INT64_MAX once. For a short response that comes in one single block, we will issue TSVConnWrite with the exact size. 
   That's what the code is trying to do. 



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@trafficserver.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


[GitHub] [trafficserver] shukitchan commented on a diff in pull request #10004: Add support for request/response transform for Wasm plugin

Posted by "shukitchan (via GitHub)" <gi...@apache.org>.
shukitchan commented on code in PR #10004:
URL: https://github.com/apache/trafficserver/pull/10004#discussion_r1276990941


##########
plugins/experimental/wasm/wasm_main.cc:
##########
@@ -46,6 +46,249 @@ struct WasmInstanceConfig {
 
 static std::unique_ptr<WasmInstanceConfig> wasm_config = nullptr;
 
+// handler for transform event
+static int
+transform_handler(TSCont contp, ats_wasm::TransformInfo *ti, TSEvent event)
+{
+  TSVConn output_conn;
+  TSVIO input_vio;
+  TSIOBufferReader input_reader;
+  TSIOBufferBlock blk;
+  int64_t toread, towrite, blk_len, upstream_done, input_avail;
+  const char *start;
+  const char *res;
+  size_t res_len;
+  bool eos, write_down, empty_input;
+
+  ats_wasm::Context *c;
+
+  TSDebug(WASM_DEBUG_TAG, "[%s] transform handler begins", __FUNCTION__);
+  c = ti->context;
+
+  output_conn = TSTransformOutputVConnGet(contp);
+  input_vio   = TSVConnWriteVIOGet(contp);
+
+  empty_input = false;
+
+  TSDebug(WASM_DEBUG_TAG, "[%s] cheking input VIO", __FUNCTION__);
+  if (!TSVIOBufferGet(input_vio)) {
+    if (ti->output_vio) {
+      TSDebug(WASM_DEBUG_TAG, "[%s] reenabling output VIO after input VIO does not exist", __FUNCTION__);
+      TSVIONBytesSet(ti->output_vio, ti->total);
+      TSVIOReenable(ti->output_vio);
+      return 0;
+    } else {
+      TSDebug(WASM_DEBUG_TAG, "[%s] no input VIO and output VIO", __FUNCTION__);
+      empty_input = true;
+    }
+  }
+
+  if (!empty_input) {
+    input_reader = TSVIOReaderGet(input_vio);
+  }
+
+  TSDebug(WASM_DEBUG_TAG, "[%s] creating buffer and reader", __FUNCTION__);
+  if (!ti->output_buffer) {
+    ti->output_buffer = TSIOBufferCreate();
+    ti->output_reader = TSIOBufferReaderAlloc(ti->output_buffer);
+
+    ti->reserved_buffer = TSIOBufferCreate();
+    ti->reserved_reader = TSIOBufferReaderAlloc(ti->reserved_buffer);
+
+    if (!empty_input) {
+      ti->upstream_bytes = TSVIONBytesGet(input_vio);
+    } else {
+      ti->upstream_bytes = 0;
+    }
+
+    ti->downstream_bytes = INT64_MAX;
+  }
+
+  TSDebug(WASM_DEBUG_TAG, "[%s] init variables inside handler", __FUNCTION__);
+  if (!empty_input) {
+    input_avail   = TSIOBufferReaderAvail(input_reader);
+    upstream_done = TSVIONDoneGet(input_vio);
+    toread        = TSVIONTodoGet(input_vio);
+
+    if (toread <= input_avail) { // upstream finished
+      eos = true;
+    } else {
+      eos = false;
+    }
+  } else {
+    input_avail   = 0;
+    upstream_done = 0;
+    toread        = 0;
+    eos           = true;
+  }
+
+  if (input_avail > 0) {
+    // move to the reserved.buffer
+    TSIOBufferCopy(ti->reserved_buffer, input_reader, input_avail, 0);
+
+    // reset input
+    TSIOBufferReaderConsume(input_reader, input_avail);
+    TSVIONDoneSet(input_vio, upstream_done + input_avail);
+  }
+
+  write_down = false;
+  if (!empty_input) {
+    towrite = TSIOBufferReaderAvail(ti->reserved_reader);
+  } else {
+    towrite = 0;
+  }
+
+  do {
+    TSDebug(WASM_DEBUG_TAG, "[%s] inside transform handler loop", __FUNCTION__);
+    proxy_wasm::FilterDataStatus status = proxy_wasm::FilterDataStatus::Continue;
+
+    if (towrite == 0 && !empty_input) {
+      break;
+    }
+
+    TSDebug(WASM_DEBUG_TAG, "[%s] retrieving text and calling the wasm handler function", __FUNCTION__);
+    if (!empty_input) {
+      blk   = TSIOBufferReaderStart(ti->reserved_reader);
+      start = TSIOBufferBlockReadStart(blk, ti->reserved_reader, &blk_len);
+
+      int size = 0;
+      if (towrite > blk_len) {
+        c->setTransformResult(start, blk_len);
+        towrite -= blk_len;
+        TSIOBufferReaderConsume(ti->reserved_reader, blk_len);
+        size = blk_len;
+      } else {
+        c->setTransformResult(start, towrite);
+        TSIOBufferReaderConsume(ti->reserved_reader, towrite);
+        size    = towrite;
+        towrite = 0;
+      }
+
+      if (!towrite && eos) {
+        if (ti->request) {
+          status = c->onRequestBody(size, true);
+        } else {
+          status = c->onResponseBody(size, true);
+        }
+      } else {
+        if (ti->request) {
+          status = c->onRequestBody(size, false);
+        } else {
+          status = c->onResponseBody(size, false);
+        }
+      }
+    } else {
+      c->setTransformResult(nullptr, 0);
+      if (ti->request) {
+        status = c->onRequestBody(0, true);
+      } else {
+        status = c->onResponseBody(0, true);
+      }
+    }
+
+    TSDebug(WASM_DEBUG_TAG, "[%s] retrieving returns from wasm handler function and pass back to ATS", __FUNCTION__);
+    if ((status == proxy_wasm::FilterDataStatus::Continue) ||
+        ((status == proxy_wasm::FilterDataStatus::StopIterationAndBuffer ||
+          status == proxy_wasm::FilterDataStatus::StopIterationAndWatermark) &&
+         eos && !towrite)) {
+      res = c->getTransformResult(&res_len);
+
+      if (res && res_len > 0) {
+        if (!ti->output_vio) {
+          if (eos && !towrite) {
+            ti->output_vio = TSVConnWrite(output_conn, contp, ti->output_reader, res_len); // HttpSM go on
+          } else {
+            ti->output_vio = TSVConnWrite(output_conn, contp, ti->output_reader, ti->downstream_bytes); // HttpSM go on
+          }
+        }
+
+        TSIOBufferWrite(ti->output_buffer, res, res_len);
+        ti->total  += res_len;
+        write_down  = true;
+      }
+
+      c->clearTransformResult();
+    }
+
+    if (status == proxy_wasm::FilterDataStatus::StopIterationNoBuffer) {
+      c->clearTransformResult();
+    }
+
+    if (eos && !towrite) { // EOS
+      break;
+    }
+
+  } while (towrite > 0);
+
+  if (eos && !ti->output_vio) {
+    ti->output_vio = TSVConnWrite(output_conn, contp, ti->output_reader, 0);
+  }
+
+  if (write_down || eos) {
+    TSVIOReenable(ti->output_vio);
+  }
+
+  if (toread > input_avail) { // upstream not finished.
+    if (eos) {

Review Comment:
   it can be true by the function in the wasm module. I forgot to retrieve that value and set eos . 
   
   Good find. So that's why you can still have the EOS event below. 



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@trafficserver.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


[GitHub] [trafficserver] serrislew commented on a diff in pull request #10004: Add support for request/response transform for Wasm plugin

Posted by "serrislew (via GitHub)" <gi...@apache.org>.
serrislew commented on code in PR #10004:
URL: https://github.com/apache/trafficserver/pull/10004#discussion_r1270109303


##########
plugins/experimental/wasm/wasm_main.cc:
##########
@@ -46,6 +46,250 @@ struct WasmInstanceConfig {
 
 static std::unique_ptr<WasmInstanceConfig> wasm_config = nullptr;
 
+// handler for transform event
+static int
+transform_handler(TSCont contp, ats_wasm::TransformInfo *ti, TSEvent event)
+{
+  TSVConn output_conn;
+  TSVIO input_vio;
+  TSIOBufferReader input_reader;
+  TSIOBufferBlock blk;
+  int64_t toread, towrite, blk_len, upstream_done, input_avail;
+  const char *start;
+  const char *res;
+  size_t res_len;
+  int eos, write_down, empty_input;
+
+  ats_wasm::Context *c;
+
+  TSDebug(WASM_DEBUG_TAG, "[%s] transform handler begins", __FUNCTION__);
+  c = ti->context;
+
+  output_conn = TSTransformOutputVConnGet(contp);
+  input_vio   = TSVConnWriteVIOGet(contp);
+
+  empty_input = 0;
+
+  TSDebug(WASM_DEBUG_TAG, "[%s] cheking input VIO", __FUNCTION__);
+  if (!TSVIOBufferGet(input_vio)) {
+    if (ti->output_vio) {
+      TSDebug(WASM_DEBUG_TAG, "[%s] reenabling output VIO after input VIO does not exist", __FUNCTION__);
+      TSVIONBytesSet(ti->output_vio, ti->total);
+      TSVIOReenable(ti->output_vio);
+      return 0;
+    } else {
+      TSDebug(WASM_DEBUG_TAG, "[%s] no input VIO and output VIO", __FUNCTION__);
+      empty_input = 1;
+    }
+  }
+
+  if (empty_input == 0) {
+    input_reader = TSVIOReaderGet(input_vio);
+  }
+
+  TSDebug(WASM_DEBUG_TAG, "[%s] creating buffer and reader", __FUNCTION__);
+  if (!ti->output_buffer) {
+    ti->output_buffer = TSIOBufferCreate();
+    ti->output_reader = TSIOBufferReaderAlloc(ti->output_buffer);
+
+    ti->reserved_buffer = TSIOBufferCreate();
+    ti->reserved_reader = TSIOBufferReaderAlloc(ti->reserved_buffer);
+
+    if (empty_input == 0) {
+      ti->upstream_bytes = TSVIONBytesGet(input_vio);
+    } else {
+      ti->upstream_bytes = 0;
+    }
+
+    ti->downstream_bytes = INT64_MAX;
+  }
+
+  TSDebug(WASM_DEBUG_TAG, "[%s] init variables inside handler", __FUNCTION__);
+  if (empty_input == 0) {
+    input_avail   = TSIOBufferReaderAvail(input_reader);
+    upstream_done = TSVIONDoneGet(input_vio);
+    toread        = TSVIONTodoGet(input_vio);
+
+    if (toread <= input_avail) { // upstream finished
+      eos = 1;
+    } else {
+      eos = 0;
+    }
+  } else {
+    input_avail   = 0;
+    upstream_done = 0;
+    toread        = 0;
+    eos           = 1;
+  }
+
+  if (input_avail > 0) {
+    // move to the reserved.buffer
+    TSIOBufferCopy(ti->reserved_buffer, input_reader, input_avail, 0);

Review Comment:
   why is there a reserved buffer and reserved reader? it seems like it's acting as an intermediate buffer



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@trafficserver.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


[GitHub] [trafficserver] serrislew commented on a diff in pull request #10004: Add support for request/response transform for Wasm plugin

Posted by "serrislew (via GitHub)" <gi...@apache.org>.
serrislew commented on code in PR #10004:
URL: https://github.com/apache/trafficserver/pull/10004#discussion_r1276682416


##########
plugins/experimental/wasm/wasm_main.cc:
##########
@@ -46,6 +46,249 @@ struct WasmInstanceConfig {
 
 static std::unique_ptr<WasmInstanceConfig> wasm_config = nullptr;
 
+// handler for transform event
+static int
+transform_handler(TSCont contp, ats_wasm::TransformInfo *ti, TSEvent event)

Review Comment:
   TSEvent event not needed in transform_handler



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@trafficserver.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


[GitHub] [trafficserver] serrislew commented on a diff in pull request #10004: Add support for request/response transform for Wasm plugin

Posted by "serrislew (via GitHub)" <gi...@apache.org>.
serrislew commented on code in PR #10004:
URL: https://github.com/apache/trafficserver/pull/10004#discussion_r1276660273


##########
plugins/experimental/wasm/wasm_main.cc:
##########
@@ -46,6 +46,250 @@ struct WasmInstanceConfig {
 
 static std::unique_ptr<WasmInstanceConfig> wasm_config = nullptr;
 
+// handler for transform event
+static int
+transform_handler(TSCont contp, ats_wasm::TransformInfo *ti, TSEvent event)
+{
+  TSVConn output_conn;
+  TSVIO input_vio;
+  TSIOBufferReader input_reader;
+  TSIOBufferBlock blk;
+  int64_t toread, towrite, blk_len, upstream_done, input_avail;
+  const char *start;
+  const char *res;
+  size_t res_len;
+  int eos, write_down, empty_input;
+
+  ats_wasm::Context *c;
+
+  TSDebug(WASM_DEBUG_TAG, "[%s] transform handler begins", __FUNCTION__);
+  c = ti->context;
+
+  output_conn = TSTransformOutputVConnGet(contp);
+  input_vio   = TSVConnWriteVIOGet(contp);
+
+  empty_input = 0;
+
+  TSDebug(WASM_DEBUG_TAG, "[%s] cheking input VIO", __FUNCTION__);
+  if (!TSVIOBufferGet(input_vio)) {
+    if (ti->output_vio) {
+      TSDebug(WASM_DEBUG_TAG, "[%s] reenabling output VIO after input VIO does not exist", __FUNCTION__);
+      TSVIONBytesSet(ti->output_vio, ti->total);
+      TSVIOReenable(ti->output_vio);
+      return 0;
+    } else {
+      TSDebug(WASM_DEBUG_TAG, "[%s] no input VIO and output VIO", __FUNCTION__);
+      empty_input = 1;
+    }
+  }
+
+  if (empty_input == 0) {
+    input_reader = TSVIOReaderGet(input_vio);
+  }
+
+  TSDebug(WASM_DEBUG_TAG, "[%s] creating buffer and reader", __FUNCTION__);
+  if (!ti->output_buffer) {
+    ti->output_buffer = TSIOBufferCreate();
+    ti->output_reader = TSIOBufferReaderAlloc(ti->output_buffer);
+
+    ti->reserved_buffer = TSIOBufferCreate();
+    ti->reserved_reader = TSIOBufferReaderAlloc(ti->reserved_buffer);
+
+    if (empty_input == 0) {
+      ti->upstream_bytes = TSVIONBytesGet(input_vio);
+    } else {
+      ti->upstream_bytes = 0;
+    }
+
+    ti->downstream_bytes = INT64_MAX;
+  }
+
+  TSDebug(WASM_DEBUG_TAG, "[%s] init variables inside handler", __FUNCTION__);
+  if (empty_input == 0) {
+    input_avail   = TSIOBufferReaderAvail(input_reader);
+    upstream_done = TSVIONDoneGet(input_vio);
+    toread        = TSVIONTodoGet(input_vio);
+
+    if (toread <= input_avail) { // upstream finished
+      eos = 1;
+    } else {
+      eos = 0;
+    }
+  } else {
+    input_avail   = 0;
+    upstream_done = 0;
+    toread        = 0;
+    eos           = 1;
+  }
+
+  if (input_avail > 0) {
+    // move to the reserved.buffer
+    TSIOBufferCopy(ti->reserved_buffer, input_reader, input_avail, 0);
+
+    // reset input
+    TSIOBufferReaderConsume(input_reader, input_avail);
+    TSVIONDoneSet(input_vio, upstream_done + input_avail);
+  }
+
+  write_down = 0;
+  if (empty_input == 0) {
+    towrite = TSIOBufferReaderAvail(ti->reserved_reader);
+  } else {
+    towrite = 0;
+  }
+
+  do {
+    TSDebug(WASM_DEBUG_TAG, "[%s] inside transform handler loop", __FUNCTION__);
+    proxy_wasm::FilterDataStatus status = proxy_wasm::FilterDataStatus::Continue;
+
+    if (towrite == 0 && empty_input == 0) {
+      break;
+    }
+
+    TSDebug(WASM_DEBUG_TAG, "[%s] retrieving text and calling the wasm handler function", __FUNCTION__);
+    if (empty_input == 0) {
+      blk   = TSIOBufferReaderStart(ti->reserved_reader);
+      start = TSIOBufferBlockReadStart(blk, ti->reserved_reader, &blk_len);
+
+      int size = 0;
+      if (towrite > blk_len) {
+        c->setTransformResult(start, blk_len);
+        towrite -= blk_len;
+        TSIOBufferReaderConsume(ti->reserved_reader, blk_len);
+        size = blk_len;
+      } else {
+        c->setTransformResult(start, towrite);
+        TSIOBufferReaderConsume(ti->reserved_reader, towrite);
+        size    = towrite;
+        towrite = 0;
+      }
+
+      if (!towrite && eos) {
+        if (ti->request) {
+          status = c->onRequestBody(size, true);
+        } else {
+          status = c->onResponseBody(size, true);
+        }
+      } else {
+        if (ti->request) {
+          status = c->onRequestBody(size, false);
+        } else {
+          status = c->onResponseBody(size, false);
+        }
+      }
+    } else {
+      c->setTransformResult(nullptr, 0);
+      if (ti->request) {
+        status = c->onRequestBody(0, true);
+      } else {
+        status = c->onResponseBody(0, true);
+      }
+    }
+
+    TSDebug(WASM_DEBUG_TAG, "[%s] retrieving returns from wasm handler function and pass back to ATS", __FUNCTION__);
+    if ((status == proxy_wasm::FilterDataStatus::Continue) ||
+        ((status == proxy_wasm::FilterDataStatus::StopIterationAndBuffer ||
+          status == proxy_wasm::FilterDataStatus::StopIterationAndWatermark) &&
+         eos && !towrite)) {
+      res = c->getTransformResult(&res_len);
+
+      if (res && res_len > 0) {
+        if (!ti->output_vio) {
+          if (eos && !towrite) {
+            ti->output_vio = TSVConnWrite(output_conn, contp, ti->output_reader, res_len); // HttpSM go on
+          } else {
+            ti->output_vio = TSVConnWrite(output_conn, contp, ti->output_reader, ti->downstream_bytes); // HttpSM go on

Review Comment:
   oh for a large response with multiple blocks, it will iterate and keep writing so you are only calling TSVConnWrite to initialize for all of the bytes. got it, thanks for clarifying 



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@trafficserver.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


[GitHub] [trafficserver] shukitchan commented on a diff in pull request #10004: Add support for request/response transform for Wasm plugin

Posted by "shukitchan (via GitHub)" <gi...@apache.org>.
shukitchan commented on code in PR #10004:
URL: https://github.com/apache/trafficserver/pull/10004#discussion_r1274462223


##########
plugins/experimental/wasm/wasm_main.cc:
##########
@@ -46,6 +46,250 @@ struct WasmInstanceConfig {
 
 static std::unique_ptr<WasmInstanceConfig> wasm_config = nullptr;
 
+// handler for transform event
+static int
+transform_handler(TSCont contp, ats_wasm::TransformInfo *ti, TSEvent event)
+{
+  TSVConn output_conn;
+  TSVIO input_vio;
+  TSIOBufferReader input_reader;
+  TSIOBufferBlock blk;
+  int64_t toread, towrite, blk_len, upstream_done, input_avail;
+  const char *start;
+  const char *res;
+  size_t res_len;
+  int eos, write_down, empty_input;
+
+  ats_wasm::Context *c;
+
+  TSDebug(WASM_DEBUG_TAG, "[%s] transform handler begins", __FUNCTION__);
+  c = ti->context;
+
+  output_conn = TSTransformOutputVConnGet(contp);
+  input_vio   = TSVConnWriteVIOGet(contp);
+
+  empty_input = 0;
+
+  TSDebug(WASM_DEBUG_TAG, "[%s] cheking input VIO", __FUNCTION__);
+  if (!TSVIOBufferGet(input_vio)) {
+    if (ti->output_vio) {
+      TSDebug(WASM_DEBUG_TAG, "[%s] reenabling output VIO after input VIO does not exist", __FUNCTION__);
+      TSVIONBytesSet(ti->output_vio, ti->total);
+      TSVIOReenable(ti->output_vio);
+      return 0;
+    } else {
+      TSDebug(WASM_DEBUG_TAG, "[%s] no input VIO and output VIO", __FUNCTION__);
+      empty_input = 1;
+    }
+  }
+
+  if (empty_input == 0) {
+    input_reader = TSVIOReaderGet(input_vio);
+  }
+
+  TSDebug(WASM_DEBUG_TAG, "[%s] creating buffer and reader", __FUNCTION__);
+  if (!ti->output_buffer) {
+    ti->output_buffer = TSIOBufferCreate();
+    ti->output_reader = TSIOBufferReaderAlloc(ti->output_buffer);
+
+    ti->reserved_buffer = TSIOBufferCreate();
+    ti->reserved_reader = TSIOBufferReaderAlloc(ti->reserved_buffer);
+
+    if (empty_input == 0) {
+      ti->upstream_bytes = TSVIONBytesGet(input_vio);
+    } else {
+      ti->upstream_bytes = 0;
+    }
+
+    ti->downstream_bytes = INT64_MAX;
+  }
+
+  TSDebug(WASM_DEBUG_TAG, "[%s] init variables inside handler", __FUNCTION__);
+  if (empty_input == 0) {
+    input_avail   = TSIOBufferReaderAvail(input_reader);
+    upstream_done = TSVIONDoneGet(input_vio);
+    toread        = TSVIONTodoGet(input_vio);
+
+    if (toread <= input_avail) { // upstream finished
+      eos = 1;
+    } else {
+      eos = 0;
+    }
+  } else {
+    input_avail   = 0;
+    upstream_done = 0;
+    toread        = 0;
+    eos           = 1;
+  }
+
+  if (input_avail > 0) {
+    // move to the reserved.buffer
+    TSIOBufferCopy(ti->reserved_buffer, input_reader, input_avail, 0);
+
+    // reset input
+    TSIOBufferReaderConsume(input_reader, input_avail);
+    TSVIONDoneSet(input_vio, upstream_done + input_avail);
+  }
+
+  write_down = 0;
+  if (empty_input == 0) {
+    towrite = TSIOBufferReaderAvail(ti->reserved_reader);
+  } else {
+    towrite = 0;
+  }
+
+  do {
+    TSDebug(WASM_DEBUG_TAG, "[%s] inside transform handler loop", __FUNCTION__);
+    proxy_wasm::FilterDataStatus status = proxy_wasm::FilterDataStatus::Continue;
+
+    if (towrite == 0 && empty_input == 0) {
+      break;
+    }
+
+    TSDebug(WASM_DEBUG_TAG, "[%s] retrieving text and calling the wasm handler function", __FUNCTION__);
+    if (empty_input == 0) {
+      blk   = TSIOBufferReaderStart(ti->reserved_reader);
+      start = TSIOBufferBlockReadStart(blk, ti->reserved_reader, &blk_len);
+
+      int size = 0;
+      if (towrite > blk_len) {
+        c->setTransformResult(start, blk_len);
+        towrite -= blk_len;
+        TSIOBufferReaderConsume(ti->reserved_reader, blk_len);
+        size = blk_len;
+      } else {
+        c->setTransformResult(start, towrite);
+        TSIOBufferReaderConsume(ti->reserved_reader, towrite);
+        size    = towrite;
+        towrite = 0;
+      }
+
+      if (!towrite && eos) {
+        if (ti->request) {
+          status = c->onRequestBody(size, true);
+        } else {
+          status = c->onResponseBody(size, true);
+        }
+      } else {
+        if (ti->request) {
+          status = c->onRequestBody(size, false);
+        } else {
+          status = c->onResponseBody(size, false);
+        }
+      }
+    } else {
+      c->setTransformResult(nullptr, 0);
+      if (ti->request) {
+        status = c->onRequestBody(0, true);
+      } else {
+        status = c->onResponseBody(0, true);
+      }
+    }
+
+    TSDebug(WASM_DEBUG_TAG, "[%s] retrieving returns from wasm handler function and pass back to ATS", __FUNCTION__);
+    if ((status == proxy_wasm::FilterDataStatus::Continue) ||
+        ((status == proxy_wasm::FilterDataStatus::StopIterationAndBuffer ||
+          status == proxy_wasm::FilterDataStatus::StopIterationAndWatermark) &&
+         eos && !towrite)) {
+      res = c->getTransformResult(&res_len);
+
+      if (res && res_len > 0) {
+        if (!ti->output_vio) {
+          if (eos && !towrite) {
+            ti->output_vio = TSVConnWrite(output_conn, contp, ti->output_reader, res_len); // HttpSM go on
+          } else {
+            ti->output_vio = TSVConnWrite(output_conn, contp, ti->output_reader, ti->downstream_bytes); // HttpSM go on

Review Comment:
   That is probably right. Will try this out. 



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@trafficserver.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


[GitHub] [trafficserver] serrislew commented on a diff in pull request #10004: Add support for request/response transform for Wasm plugin

Posted by "serrislew (via GitHub)" <gi...@apache.org>.
serrislew commented on code in PR #10004:
URL: https://github.com/apache/trafficserver/pull/10004#discussion_r1270104411


##########
plugins/experimental/wasm/wasm_main.cc:
##########
@@ -46,6 +46,250 @@ struct WasmInstanceConfig {
 
 static std::unique_ptr<WasmInstanceConfig> wasm_config = nullptr;
 
+// handler for transform event
+static int
+transform_handler(TSCont contp, ats_wasm::TransformInfo *ti, TSEvent event)
+{
+  TSVConn output_conn;
+  TSVIO input_vio;
+  TSIOBufferReader input_reader;
+  TSIOBufferBlock blk;
+  int64_t toread, towrite, blk_len, upstream_done, input_avail;
+  const char *start;
+  const char *res;
+  size_t res_len;
+  int eos, write_down, empty_input;
+
+  ats_wasm::Context *c;
+
+  TSDebug(WASM_DEBUG_TAG, "[%s] transform handler begins", __FUNCTION__);
+  c = ti->context;
+
+  output_conn = TSTransformOutputVConnGet(contp);
+  input_vio   = TSVConnWriteVIOGet(contp);
+
+  empty_input = 0;
+
+  TSDebug(WASM_DEBUG_TAG, "[%s] cheking input VIO", __FUNCTION__);
+  if (!TSVIOBufferGet(input_vio)) {
+    if (ti->output_vio) {
+      TSDebug(WASM_DEBUG_TAG, "[%s] reenabling output VIO after input VIO does not exist", __FUNCTION__);
+      TSVIONBytesSet(ti->output_vio, ti->total);
+      TSVIOReenable(ti->output_vio);
+      return 0;
+    } else {
+      TSDebug(WASM_DEBUG_TAG, "[%s] no input VIO and output VIO", __FUNCTION__);
+      empty_input = 1;
+    }
+  }
+
+  if (empty_input == 0) {
+    input_reader = TSVIOReaderGet(input_vio);
+  }
+
+  TSDebug(WASM_DEBUG_TAG, "[%s] creating buffer and reader", __FUNCTION__);
+  if (!ti->output_buffer) {
+    ti->output_buffer = TSIOBufferCreate();
+    ti->output_reader = TSIOBufferReaderAlloc(ti->output_buffer);
+
+    ti->reserved_buffer = TSIOBufferCreate();
+    ti->reserved_reader = TSIOBufferReaderAlloc(ti->reserved_buffer);
+
+    if (empty_input == 0) {
+      ti->upstream_bytes = TSVIONBytesGet(input_vio);
+    } else {
+      ti->upstream_bytes = 0;
+    }
+
+    ti->downstream_bytes = INT64_MAX;
+  }
+
+  TSDebug(WASM_DEBUG_TAG, "[%s] init variables inside handler", __FUNCTION__);
+  if (empty_input == 0) {
+    input_avail   = TSIOBufferReaderAvail(input_reader);
+    upstream_done = TSVIONDoneGet(input_vio);
+    toread        = TSVIONTodoGet(input_vio);
+
+    if (toread <= input_avail) { // upstream finished
+      eos = 1;
+    } else {
+      eos = 0;
+    }
+  } else {
+    input_avail   = 0;
+    upstream_done = 0;
+    toread        = 0;
+    eos           = 1;
+  }
+
+  if (input_avail > 0) {
+    // move to the reserved.buffer
+    TSIOBufferCopy(ti->reserved_buffer, input_reader, input_avail, 0);
+
+    // reset input
+    TSIOBufferReaderConsume(input_reader, input_avail);
+    TSVIONDoneSet(input_vio, upstream_done + input_avail);
+  }
+
+  write_down = 0;
+  if (empty_input == 0) {
+    towrite = TSIOBufferReaderAvail(ti->reserved_reader);
+  } else {
+    towrite = 0;
+  }
+
+  do {
+    TSDebug(WASM_DEBUG_TAG, "[%s] inside transform handler loop", __FUNCTION__);
+    proxy_wasm::FilterDataStatus status = proxy_wasm::FilterDataStatus::Continue;
+
+    if (towrite == 0 && empty_input == 0) {
+      break;
+    }
+
+    TSDebug(WASM_DEBUG_TAG, "[%s] retrieving text and calling the wasm handler function", __FUNCTION__);
+    if (empty_input == 0) {
+      blk   = TSIOBufferReaderStart(ti->reserved_reader);
+      start = TSIOBufferBlockReadStart(blk, ti->reserved_reader, &blk_len);
+
+      int size = 0;
+      if (towrite > blk_len) {
+        c->setTransformResult(start, blk_len);
+        towrite -= blk_len;
+        TSIOBufferReaderConsume(ti->reserved_reader, blk_len);
+        size = blk_len;
+      } else {
+        c->setTransformResult(start, towrite);
+        TSIOBufferReaderConsume(ti->reserved_reader, towrite);
+        size    = towrite;
+        towrite = 0;
+      }
+
+      if (!towrite && eos) {
+        if (ti->request) {
+          status = c->onRequestBody(size, true);
+        } else {
+          status = c->onResponseBody(size, true);
+        }
+      } else {
+        if (ti->request) {
+          status = c->onRequestBody(size, false);
+        } else {
+          status = c->onResponseBody(size, false);
+        }
+      }
+    } else {
+      c->setTransformResult(nullptr, 0);
+      if (ti->request) {
+        status = c->onRequestBody(0, true);
+      } else {
+        status = c->onResponseBody(0, true);
+      }
+    }
+
+    TSDebug(WASM_DEBUG_TAG, "[%s] retrieving returns from wasm handler function and pass back to ATS", __FUNCTION__);
+    if ((status == proxy_wasm::FilterDataStatus::Continue) ||
+        ((status == proxy_wasm::FilterDataStatus::StopIterationAndBuffer ||
+          status == proxy_wasm::FilterDataStatus::StopIterationAndWatermark) &&
+         eos && !towrite)) {
+      res = c->getTransformResult(&res_len);
+
+      if (res && res_len > 0) {
+        if (!ti->output_vio) {
+          if (eos && !towrite) {
+            ti->output_vio = TSVConnWrite(output_conn, contp, ti->output_reader, res_len); // HttpSM go on
+          } else {
+            ti->output_vio = TSVConnWrite(output_conn, contp, ti->output_reader, ti->downstream_bytes); // HttpSM go on
+          }
+        }
+
+        TSIOBufferWrite(ti->output_buffer, res, res_len);
+        ti->total  += res_len;
+        write_down  = 1;
+      }
+
+      c->clearTransformResult();
+    }
+
+    if (status == proxy_wasm::FilterDataStatus::StopIterationNoBuffer) {
+      c->clearTransformResult();
+    }
+
+    if (eos && !towrite) { // EOS
+      eos = 1;

Review Comment:
   I don't think this does anything 



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@trafficserver.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


[GitHub] [trafficserver] shukitchan commented on a diff in pull request #10004: Add support for request/response transform for Wasm plugin

Posted by "shukitchan (via GitHub)" <gi...@apache.org>.
shukitchan commented on code in PR #10004:
URL: https://github.com/apache/trafficserver/pull/10004#discussion_r1277126468


##########
plugins/experimental/wasm/wasm_main.cc:
##########
@@ -46,6 +46,249 @@ struct WasmInstanceConfig {
 
 static std::unique_ptr<WasmInstanceConfig> wasm_config = nullptr;
 
+// handler for transform event
+static int
+transform_handler(TSCont contp, ats_wasm::TransformInfo *ti, TSEvent event)
+{
+  TSVConn output_conn;
+  TSVIO input_vio;
+  TSIOBufferReader input_reader;
+  TSIOBufferBlock blk;
+  int64_t toread, towrite, blk_len, upstream_done, input_avail;
+  const char *start;
+  const char *res;
+  size_t res_len;
+  bool eos, write_down, empty_input;
+
+  ats_wasm::Context *c;
+
+  TSDebug(WASM_DEBUG_TAG, "[%s] transform handler begins", __FUNCTION__);
+  c = ti->context;
+
+  output_conn = TSTransformOutputVConnGet(contp);
+  input_vio   = TSVConnWriteVIOGet(contp);
+
+  empty_input = false;
+
+  TSDebug(WASM_DEBUG_TAG, "[%s] cheking input VIO", __FUNCTION__);
+  if (!TSVIOBufferGet(input_vio)) {
+    if (ti->output_vio) {
+      TSDebug(WASM_DEBUG_TAG, "[%s] reenabling output VIO after input VIO does not exist", __FUNCTION__);
+      TSVIONBytesSet(ti->output_vio, ti->total);
+      TSVIOReenable(ti->output_vio);
+      return 0;
+    } else {
+      TSDebug(WASM_DEBUG_TAG, "[%s] no input VIO and output VIO", __FUNCTION__);
+      empty_input = true;
+    }
+  }
+
+  if (!empty_input) {
+    input_reader = TSVIOReaderGet(input_vio);
+  }
+
+  TSDebug(WASM_DEBUG_TAG, "[%s] creating buffer and reader", __FUNCTION__);
+  if (!ti->output_buffer) {
+    ti->output_buffer = TSIOBufferCreate();
+    ti->output_reader = TSIOBufferReaderAlloc(ti->output_buffer);
+
+    ti->reserved_buffer = TSIOBufferCreate();
+    ti->reserved_reader = TSIOBufferReaderAlloc(ti->reserved_buffer);
+
+    if (!empty_input) {
+      ti->upstream_bytes = TSVIONBytesGet(input_vio);
+    } else {
+      ti->upstream_bytes = 0;
+    }
+
+    ti->downstream_bytes = INT64_MAX;
+  }
+
+  TSDebug(WASM_DEBUG_TAG, "[%s] init variables inside handler", __FUNCTION__);
+  if (!empty_input) {
+    input_avail   = TSIOBufferReaderAvail(input_reader);
+    upstream_done = TSVIONDoneGet(input_vio);
+    toread        = TSVIONTodoGet(input_vio);
+
+    if (toread <= input_avail) { // upstream finished
+      eos = true;
+    } else {
+      eos = false;
+    }
+  } else {
+    input_avail   = 0;
+    upstream_done = 0;
+    toread        = 0;
+    eos           = true;
+  }
+
+  if (input_avail > 0) {
+    // move to the reserved.buffer
+    TSIOBufferCopy(ti->reserved_buffer, input_reader, input_avail, 0);
+
+    // reset input
+    TSIOBufferReaderConsume(input_reader, input_avail);
+    TSVIONDoneSet(input_vio, upstream_done + input_avail);
+  }
+
+  write_down = false;
+  if (!empty_input) {
+    towrite = TSIOBufferReaderAvail(ti->reserved_reader);
+  } else {
+    towrite = 0;
+  }
+
+  do {
+    TSDebug(WASM_DEBUG_TAG, "[%s] inside transform handler loop", __FUNCTION__);
+    proxy_wasm::FilterDataStatus status = proxy_wasm::FilterDataStatus::Continue;
+
+    if (towrite == 0 && !empty_input) {
+      break;
+    }
+
+    TSDebug(WASM_DEBUG_TAG, "[%s] retrieving text and calling the wasm handler function", __FUNCTION__);
+    if (!empty_input) {
+      blk   = TSIOBufferReaderStart(ti->reserved_reader);
+      start = TSIOBufferBlockReadStart(blk, ti->reserved_reader, &blk_len);
+
+      int size = 0;
+      if (towrite > blk_len) {
+        c->setTransformResult(start, blk_len);
+        towrite -= blk_len;
+        TSIOBufferReaderConsume(ti->reserved_reader, blk_len);
+        size = blk_len;
+      } else {
+        c->setTransformResult(start, towrite);
+        TSIOBufferReaderConsume(ti->reserved_reader, towrite);
+        size    = towrite;
+        towrite = 0;
+      }
+
+      if (!towrite && eos) {
+        if (ti->request) {
+          status = c->onRequestBody(size, true);
+        } else {
+          status = c->onResponseBody(size, true);
+        }
+      } else {
+        if (ti->request) {
+          status = c->onRequestBody(size, false);
+        } else {
+          status = c->onResponseBody(size, false);
+        }
+      }
+    } else {
+      c->setTransformResult(nullptr, 0);
+      if (ti->request) {
+        status = c->onRequestBody(0, true);
+      } else {
+        status = c->onResponseBody(0, true);
+      }
+    }
+
+    TSDebug(WASM_DEBUG_TAG, "[%s] retrieving returns from wasm handler function and pass back to ATS", __FUNCTION__);
+    if ((status == proxy_wasm::FilterDataStatus::Continue) ||
+        ((status == proxy_wasm::FilterDataStatus::StopIterationAndBuffer ||
+          status == proxy_wasm::FilterDataStatus::StopIterationAndWatermark) &&
+         eos && !towrite)) {
+      res = c->getTransformResult(&res_len);
+
+      if (res && res_len > 0) {
+        if (!ti->output_vio) {
+          if (eos && !towrite) {
+            ti->output_vio = TSVConnWrite(output_conn, contp, ti->output_reader, res_len); // HttpSM go on
+          } else {
+            ti->output_vio = TSVConnWrite(output_conn, contp, ti->output_reader, ti->downstream_bytes); // HttpSM go on
+          }
+        }
+
+        TSIOBufferWrite(ti->output_buffer, res, res_len);
+        ti->total  += res_len;
+        write_down  = true;
+      }
+
+      c->clearTransformResult();
+    }
+
+    if (status == proxy_wasm::FilterDataStatus::StopIterationNoBuffer) {
+      c->clearTransformResult();
+    }
+
+    if (eos && !towrite) { // EOS
+      break;
+    }
+
+  } while (towrite > 0);
+
+  if (eos && !ti->output_vio) {
+    ti->output_vio = TSVConnWrite(output_conn, contp, ti->output_reader, 0);
+  }
+
+  if (write_down || eos) {
+    TSVIOReenable(ti->output_vio);
+  }
+
+  if (toread > input_avail) { // upstream not finished.
+    if (eos) {

Review Comment:
   I just double checked the proxy-wasm spec. It currently does not allow changing the eos. But I expect it be possible in the future. So I want to keep the code as if. But let me add a bunch of comments to explain the idea



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@trafficserver.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


[GitHub] [trafficserver] serrislew commented on a diff in pull request #10004: Add support for request/response transform for Wasm plugin

Posted by "serrislew (via GitHub)" <gi...@apache.org>.
serrislew commented on code in PR #10004:
URL: https://github.com/apache/trafficserver/pull/10004#discussion_r1270109918


##########
plugins/experimental/wasm/wasm_main.cc:
##########
@@ -46,6 +46,250 @@ struct WasmInstanceConfig {
 
 static std::unique_ptr<WasmInstanceConfig> wasm_config = nullptr;
 
+// handler for transform event
+static int
+transform_handler(TSCont contp, ats_wasm::TransformInfo *ti, TSEvent event)
+{
+  TSVConn output_conn;
+  TSVIO input_vio;
+  TSIOBufferReader input_reader;
+  TSIOBufferBlock blk;
+  int64_t toread, towrite, blk_len, upstream_done, input_avail;
+  const char *start;
+  const char *res;
+  size_t res_len;
+  int eos, write_down, empty_input;
+
+  ats_wasm::Context *c;
+
+  TSDebug(WASM_DEBUG_TAG, "[%s] transform handler begins", __FUNCTION__);
+  c = ti->context;
+
+  output_conn = TSTransformOutputVConnGet(contp);
+  input_vio   = TSVConnWriteVIOGet(contp);
+
+  empty_input = 0;
+
+  TSDebug(WASM_DEBUG_TAG, "[%s] cheking input VIO", __FUNCTION__);
+  if (!TSVIOBufferGet(input_vio)) {
+    if (ti->output_vio) {
+      TSDebug(WASM_DEBUG_TAG, "[%s] reenabling output VIO after input VIO does not exist", __FUNCTION__);
+      TSVIONBytesSet(ti->output_vio, ti->total);
+      TSVIOReenable(ti->output_vio);
+      return 0;
+    } else {
+      TSDebug(WASM_DEBUG_TAG, "[%s] no input VIO and output VIO", __FUNCTION__);
+      empty_input = 1;
+    }
+  }
+
+  if (empty_input == 0) {
+    input_reader = TSVIOReaderGet(input_vio);
+  }
+
+  TSDebug(WASM_DEBUG_TAG, "[%s] creating buffer and reader", __FUNCTION__);
+  if (!ti->output_buffer) {
+    ti->output_buffer = TSIOBufferCreate();
+    ti->output_reader = TSIOBufferReaderAlloc(ti->output_buffer);
+
+    ti->reserved_buffer = TSIOBufferCreate();
+    ti->reserved_reader = TSIOBufferReaderAlloc(ti->reserved_buffer);
+
+    if (empty_input == 0) {
+      ti->upstream_bytes = TSVIONBytesGet(input_vio);
+    } else {
+      ti->upstream_bytes = 0;
+    }
+
+    ti->downstream_bytes = INT64_MAX;
+  }
+
+  TSDebug(WASM_DEBUG_TAG, "[%s] init variables inside handler", __FUNCTION__);
+  if (empty_input == 0) {
+    input_avail   = TSIOBufferReaderAvail(input_reader);
+    upstream_done = TSVIONDoneGet(input_vio);
+    toread        = TSVIONTodoGet(input_vio);
+
+    if (toread <= input_avail) { // upstream finished
+      eos = 1;
+    } else {
+      eos = 0;
+    }
+  } else {
+    input_avail   = 0;
+    upstream_done = 0;
+    toread        = 0;
+    eos           = 1;
+  }
+
+  if (input_avail > 0) {
+    // move to the reserved.buffer
+    TSIOBufferCopy(ti->reserved_buffer, input_reader, input_avail, 0);
+
+    // reset input
+    TSIOBufferReaderConsume(input_reader, input_avail);
+    TSVIONDoneSet(input_vio, upstream_done + input_avail);
+  }
+
+  write_down = 0;
+  if (empty_input == 0) {
+    towrite = TSIOBufferReaderAvail(ti->reserved_reader);
+  } else {
+    towrite = 0;
+  }
+
+  do {
+    TSDebug(WASM_DEBUG_TAG, "[%s] inside transform handler loop", __FUNCTION__);
+    proxy_wasm::FilterDataStatus status = proxy_wasm::FilterDataStatus::Continue;
+
+    if (towrite == 0 && empty_input == 0) {
+      break;
+    }
+
+    TSDebug(WASM_DEBUG_TAG, "[%s] retrieving text and calling the wasm handler function", __FUNCTION__);
+    if (empty_input == 0) {

Review Comment:
   also this might be more nit-picky but it seems like this conditional is checked a lot and could be refactored to handle this case separately instead of having it checked every block of code



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@trafficserver.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


[GitHub] [trafficserver] shukitchan merged pull request #10004: Add support for request/response transform for Wasm plugin

Posted by "shukitchan (via GitHub)" <gi...@apache.org>.
shukitchan merged PR #10004:
URL: https://github.com/apache/trafficserver/pull/10004


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@trafficserver.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


[GitHub] [trafficserver] shukitchan commented on pull request #10004: Add support for request/response transform for Wasm plugin

Posted by "shukitchan (via GitHub)" <gi...@apache.org>.
shukitchan commented on PR #10004:
URL: https://github.com/apache/trafficserver/pull/10004#issuecomment-1652638743

   @serrislew would you pls review again? Thanks.


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@trafficserver.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


[GitHub] [trafficserver] serrislew commented on a diff in pull request #10004: Add support for request/response transform for Wasm plugin

Posted by "serrislew (via GitHub)" <gi...@apache.org>.
serrislew commented on code in PR #10004:
URL: https://github.com/apache/trafficserver/pull/10004#discussion_r1276671909


##########
plugins/experimental/wasm/wasm_main.cc:
##########
@@ -46,6 +46,249 @@ struct WasmInstanceConfig {
 
 static std::unique_ptr<WasmInstanceConfig> wasm_config = nullptr;
 
+// handler for transform event
+static int
+transform_handler(TSCont contp, ats_wasm::TransformInfo *ti, TSEvent event)
+{
+  TSVConn output_conn;
+  TSVIO input_vio;
+  TSIOBufferReader input_reader;
+  TSIOBufferBlock blk;
+  int64_t toread, towrite, blk_len, upstream_done, input_avail;
+  const char *start;
+  const char *res;
+  size_t res_len;
+  bool eos, write_down, empty_input;
+
+  ats_wasm::Context *c;
+
+  TSDebug(WASM_DEBUG_TAG, "[%s] transform handler begins", __FUNCTION__);
+  c = ti->context;
+
+  output_conn = TSTransformOutputVConnGet(contp);
+  input_vio   = TSVConnWriteVIOGet(contp);
+
+  empty_input = false;
+
+  TSDebug(WASM_DEBUG_TAG, "[%s] cheking input VIO", __FUNCTION__);
+  if (!TSVIOBufferGet(input_vio)) {
+    if (ti->output_vio) {
+      TSDebug(WASM_DEBUG_TAG, "[%s] reenabling output VIO after input VIO does not exist", __FUNCTION__);
+      TSVIONBytesSet(ti->output_vio, ti->total);
+      TSVIOReenable(ti->output_vio);
+      return 0;
+    } else {
+      TSDebug(WASM_DEBUG_TAG, "[%s] no input VIO and output VIO", __FUNCTION__);
+      empty_input = true;
+    }
+  }
+
+  if (!empty_input) {
+    input_reader = TSVIOReaderGet(input_vio);
+  }
+
+  TSDebug(WASM_DEBUG_TAG, "[%s] creating buffer and reader", __FUNCTION__);
+  if (!ti->output_buffer) {
+    ti->output_buffer = TSIOBufferCreate();
+    ti->output_reader = TSIOBufferReaderAlloc(ti->output_buffer);
+
+    ti->reserved_buffer = TSIOBufferCreate();
+    ti->reserved_reader = TSIOBufferReaderAlloc(ti->reserved_buffer);
+
+    if (!empty_input) {
+      ti->upstream_bytes = TSVIONBytesGet(input_vio);
+    } else {
+      ti->upstream_bytes = 0;
+    }
+
+    ti->downstream_bytes = INT64_MAX;
+  }
+
+  TSDebug(WASM_DEBUG_TAG, "[%s] init variables inside handler", __FUNCTION__);
+  if (!empty_input) {
+    input_avail   = TSIOBufferReaderAvail(input_reader);
+    upstream_done = TSVIONDoneGet(input_vio);
+    toread        = TSVIONTodoGet(input_vio);
+
+    if (toread <= input_avail) { // upstream finished
+      eos = true;
+    } else {
+      eos = false;
+    }
+  } else {
+    input_avail   = 0;
+    upstream_done = 0;
+    toread        = 0;
+    eos           = true;
+  }
+
+  if (input_avail > 0) {
+    // move to the reserved.buffer
+    TSIOBufferCopy(ti->reserved_buffer, input_reader, input_avail, 0);
+
+    // reset input
+    TSIOBufferReaderConsume(input_reader, input_avail);
+    TSVIONDoneSet(input_vio, upstream_done + input_avail);
+  }
+
+  write_down = false;
+  if (!empty_input) {
+    towrite = TSIOBufferReaderAvail(ti->reserved_reader);
+  } else {
+    towrite = 0;
+  }
+
+  do {
+    TSDebug(WASM_DEBUG_TAG, "[%s] inside transform handler loop", __FUNCTION__);
+    proxy_wasm::FilterDataStatus status = proxy_wasm::FilterDataStatus::Continue;
+
+    if (towrite == 0 && !empty_input) {
+      break;
+    }
+
+    TSDebug(WASM_DEBUG_TAG, "[%s] retrieving text and calling the wasm handler function", __FUNCTION__);
+    if (!empty_input) {
+      blk   = TSIOBufferReaderStart(ti->reserved_reader);
+      start = TSIOBufferBlockReadStart(blk, ti->reserved_reader, &blk_len);
+
+      int size = 0;
+      if (towrite > blk_len) {
+        c->setTransformResult(start, blk_len);
+        towrite -= blk_len;
+        TSIOBufferReaderConsume(ti->reserved_reader, blk_len);
+        size = blk_len;
+      } else {
+        c->setTransformResult(start, towrite);
+        TSIOBufferReaderConsume(ti->reserved_reader, towrite);
+        size    = towrite;
+        towrite = 0;
+      }
+
+      if (!towrite && eos) {
+        if (ti->request) {
+          status = c->onRequestBody(size, true);
+        } else {
+          status = c->onResponseBody(size, true);
+        }
+      } else {
+        if (ti->request) {
+          status = c->onRequestBody(size, false);
+        } else {
+          status = c->onResponseBody(size, false);
+        }
+      }
+    } else {
+      c->setTransformResult(nullptr, 0);
+      if (ti->request) {
+        status = c->onRequestBody(0, true);
+      } else {
+        status = c->onResponseBody(0, true);
+      }
+    }
+
+    TSDebug(WASM_DEBUG_TAG, "[%s] retrieving returns from wasm handler function and pass back to ATS", __FUNCTION__);
+    if ((status == proxy_wasm::FilterDataStatus::Continue) ||
+        ((status == proxy_wasm::FilterDataStatus::StopIterationAndBuffer ||
+          status == proxy_wasm::FilterDataStatus::StopIterationAndWatermark) &&
+         eos && !towrite)) {
+      res = c->getTransformResult(&res_len);
+
+      if (res && res_len > 0) {
+        if (!ti->output_vio) {
+          if (eos && !towrite) {
+            ti->output_vio = TSVConnWrite(output_conn, contp, ti->output_reader, res_len); // HttpSM go on
+          } else {
+            ti->output_vio = TSVConnWrite(output_conn, contp, ti->output_reader, ti->downstream_bytes); // HttpSM go on
+          }
+        }
+
+        TSIOBufferWrite(ti->output_buffer, res, res_len);
+        ti->total  += res_len;
+        write_down  = true;
+      }
+
+      c->clearTransformResult();
+    }
+
+    if (status == proxy_wasm::FilterDataStatus::StopIterationNoBuffer) {
+      c->clearTransformResult();
+    }
+
+    if (eos && !towrite) { // EOS
+      break;
+    }
+
+  } while (towrite > 0);
+
+  if (eos && !ti->output_vio) {
+    ti->output_vio = TSVConnWrite(output_conn, contp, ti->output_reader, 0);
+  }
+
+  if (write_down || eos) {
+    TSVIOReenable(ti->output_vio);
+  }
+
+  if (toread > input_avail) { // upstream not finished.
+    if (eos) {

Review Comment:
   is this even possible? if `toread > input_avail`, `eos` will always be false since there is more to read? also from how `eos` is set above? 



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@trafficserver.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


[GitHub] [trafficserver] serrislew commented on pull request #10004: Add support for request/response transform for Wasm plugin

Posted by "serrislew (via GitHub)" <gi...@apache.org>.
serrislew commented on PR #10004:
URL: https://github.com/apache/trafficserver/pull/10004#issuecomment-1656127933

   LGTM


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@trafficserver.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


[GitHub] [trafficserver] shukitchan commented on pull request #10004: Add support for request/response transform

Posted by "shukitchan (via GitHub)" <gi...@apache.org>.
shukitchan commented on PR #10004:
URL: https://github.com/apache/trafficserver/pull/10004#issuecomment-1633111175

   [approve ci autest]


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@trafficserver.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


[GitHub] [trafficserver] serrislew commented on a diff in pull request #10004: Add support for request/response transform for Wasm plugin

Posted by "serrislew (via GitHub)" <gi...@apache.org>.
serrislew commented on code in PR #10004:
URL: https://github.com/apache/trafficserver/pull/10004#discussion_r1270105582


##########
plugins/experimental/wasm/wasm_main.cc:
##########
@@ -46,6 +46,250 @@ struct WasmInstanceConfig {
 
 static std::unique_ptr<WasmInstanceConfig> wasm_config = nullptr;
 
+// handler for transform event
+static int
+transform_handler(TSCont contp, ats_wasm::TransformInfo *ti, TSEvent event)
+{
+  TSVConn output_conn;
+  TSVIO input_vio;
+  TSIOBufferReader input_reader;
+  TSIOBufferBlock blk;
+  int64_t toread, towrite, blk_len, upstream_done, input_avail;
+  const char *start;
+  const char *res;
+  size_t res_len;
+  int eos, write_down, empty_input;
+
+  ats_wasm::Context *c;
+
+  TSDebug(WASM_DEBUG_TAG, "[%s] transform handler begins", __FUNCTION__);
+  c = ti->context;
+
+  output_conn = TSTransformOutputVConnGet(contp);
+  input_vio   = TSVConnWriteVIOGet(contp);
+
+  empty_input = 0;
+
+  TSDebug(WASM_DEBUG_TAG, "[%s] cheking input VIO", __FUNCTION__);
+  if (!TSVIOBufferGet(input_vio)) {
+    if (ti->output_vio) {
+      TSDebug(WASM_DEBUG_TAG, "[%s] reenabling output VIO after input VIO does not exist", __FUNCTION__);
+      TSVIONBytesSet(ti->output_vio, ti->total);
+      TSVIOReenable(ti->output_vio);
+      return 0;
+    } else {
+      TSDebug(WASM_DEBUG_TAG, "[%s] no input VIO and output VIO", __FUNCTION__);
+      empty_input = 1;
+    }
+  }
+
+  if (empty_input == 0) {
+    input_reader = TSVIOReaderGet(input_vio);
+  }
+
+  TSDebug(WASM_DEBUG_TAG, "[%s] creating buffer and reader", __FUNCTION__);
+  if (!ti->output_buffer) {
+    ti->output_buffer = TSIOBufferCreate();
+    ti->output_reader = TSIOBufferReaderAlloc(ti->output_buffer);
+
+    ti->reserved_buffer = TSIOBufferCreate();
+    ti->reserved_reader = TSIOBufferReaderAlloc(ti->reserved_buffer);
+
+    if (empty_input == 0) {
+      ti->upstream_bytes = TSVIONBytesGet(input_vio);
+    } else {
+      ti->upstream_bytes = 0;
+    }
+
+    ti->downstream_bytes = INT64_MAX;
+  }
+
+  TSDebug(WASM_DEBUG_TAG, "[%s] init variables inside handler", __FUNCTION__);
+  if (empty_input == 0) {
+    input_avail   = TSIOBufferReaderAvail(input_reader);
+    upstream_done = TSVIONDoneGet(input_vio);
+    toread        = TSVIONTodoGet(input_vio);
+
+    if (toread <= input_avail) { // upstream finished
+      eos = 1;
+    } else {
+      eos = 0;
+    }
+  } else {
+    input_avail   = 0;
+    upstream_done = 0;
+    toread        = 0;
+    eos           = 1;
+  }
+
+  if (input_avail > 0) {
+    // move to the reserved.buffer
+    TSIOBufferCopy(ti->reserved_buffer, input_reader, input_avail, 0);
+
+    // reset input
+    TSIOBufferReaderConsume(input_reader, input_avail);
+    TSVIONDoneSet(input_vio, upstream_done + input_avail);
+  }
+
+  write_down = 0;
+  if (empty_input == 0) {
+    towrite = TSIOBufferReaderAvail(ti->reserved_reader);
+  } else {
+    towrite = 0;
+  }
+
+  do {
+    TSDebug(WASM_DEBUG_TAG, "[%s] inside transform handler loop", __FUNCTION__);
+    proxy_wasm::FilterDataStatus status = proxy_wasm::FilterDataStatus::Continue;
+
+    if (towrite == 0 && empty_input == 0) {
+      break;
+    }
+
+    TSDebug(WASM_DEBUG_TAG, "[%s] retrieving text and calling the wasm handler function", __FUNCTION__);
+    if (empty_input == 0) {
+      blk   = TSIOBufferReaderStart(ti->reserved_reader);
+      start = TSIOBufferBlockReadStart(blk, ti->reserved_reader, &blk_len);
+
+      int size = 0;
+      if (towrite > blk_len) {
+        c->setTransformResult(start, blk_len);
+        towrite -= blk_len;
+        TSIOBufferReaderConsume(ti->reserved_reader, blk_len);
+        size = blk_len;
+      } else {
+        c->setTransformResult(start, towrite);
+        TSIOBufferReaderConsume(ti->reserved_reader, towrite);
+        size    = towrite;
+        towrite = 0;
+      }
+
+      if (!towrite && eos) {
+        if (ti->request) {
+          status = c->onRequestBody(size, true);
+        } else {
+          status = c->onResponseBody(size, true);
+        }
+      } else {
+        if (ti->request) {
+          status = c->onRequestBody(size, false);
+        } else {
+          status = c->onResponseBody(size, false);
+        }
+      }
+    } else {
+      c->setTransformResult(nullptr, 0);
+      if (ti->request) {
+        status = c->onRequestBody(0, true);
+      } else {
+        status = c->onResponseBody(0, true);
+      }
+    }
+
+    TSDebug(WASM_DEBUG_TAG, "[%s] retrieving returns from wasm handler function and pass back to ATS", __FUNCTION__);
+    if ((status == proxy_wasm::FilterDataStatus::Continue) ||
+        ((status == proxy_wasm::FilterDataStatus::StopIterationAndBuffer ||
+          status == proxy_wasm::FilterDataStatus::StopIterationAndWatermark) &&
+         eos && !towrite)) {
+      res = c->getTransformResult(&res_len);
+
+      if (res && res_len > 0) {
+        if (!ti->output_vio) {
+          if (eos && !towrite) {
+            ti->output_vio = TSVConnWrite(output_conn, contp, ti->output_reader, res_len); // HttpSM go on
+          } else {
+            ti->output_vio = TSVConnWrite(output_conn, contp, ti->output_reader, ti->downstream_bytes); // HttpSM go on

Review Comment:
   why would this be different? only `transform_result_` gets written right so shouldn't the number of bytes written always be `res_len`? 



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@trafficserver.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


[GitHub] [trafficserver] shukitchan commented on a diff in pull request #10004: Add support for request/response transform for Wasm plugin

Posted by "shukitchan (via GitHub)" <gi...@apache.org>.
shukitchan commented on code in PR #10004:
URL: https://github.com/apache/trafficserver/pull/10004#discussion_r1276989269


##########
plugins/experimental/wasm/wasm_main.cc:
##########
@@ -46,6 +46,249 @@ struct WasmInstanceConfig {
 
 static std::unique_ptr<WasmInstanceConfig> wasm_config = nullptr;
 
+// handler for transform event
+static int
+transform_handler(TSCont contp, ats_wasm::TransformInfo *ti, TSEvent event)
+{
+  TSVConn output_conn;
+  TSVIO input_vio;
+  TSIOBufferReader input_reader;
+  TSIOBufferBlock blk;
+  int64_t toread, towrite, blk_len, upstream_done, input_avail;
+  const char *start;
+  const char *res;
+  size_t res_len;
+  bool eos, write_down, empty_input;
+
+  ats_wasm::Context *c;
+
+  TSDebug(WASM_DEBUG_TAG, "[%s] transform handler begins", __FUNCTION__);
+  c = ti->context;
+
+  output_conn = TSTransformOutputVConnGet(contp);
+  input_vio   = TSVConnWriteVIOGet(contp);
+
+  empty_input = false;
+
+  TSDebug(WASM_DEBUG_TAG, "[%s] cheking input VIO", __FUNCTION__);
+  if (!TSVIOBufferGet(input_vio)) {
+    if (ti->output_vio) {
+      TSDebug(WASM_DEBUG_TAG, "[%s] reenabling output VIO after input VIO does not exist", __FUNCTION__);
+      TSVIONBytesSet(ti->output_vio, ti->total);
+      TSVIOReenable(ti->output_vio);
+      return 0;
+    } else {
+      TSDebug(WASM_DEBUG_TAG, "[%s] no input VIO and output VIO", __FUNCTION__);
+      empty_input = true;
+    }
+  }
+
+  if (!empty_input) {
+    input_reader = TSVIOReaderGet(input_vio);
+  }
+
+  TSDebug(WASM_DEBUG_TAG, "[%s] creating buffer and reader", __FUNCTION__);
+  if (!ti->output_buffer) {
+    ti->output_buffer = TSIOBufferCreate();
+    ti->output_reader = TSIOBufferReaderAlloc(ti->output_buffer);
+
+    ti->reserved_buffer = TSIOBufferCreate();
+    ti->reserved_reader = TSIOBufferReaderAlloc(ti->reserved_buffer);
+
+    if (!empty_input) {
+      ti->upstream_bytes = TSVIONBytesGet(input_vio);
+    } else {
+      ti->upstream_bytes = 0;
+    }
+
+    ti->downstream_bytes = INT64_MAX;
+  }
+
+  TSDebug(WASM_DEBUG_TAG, "[%s] init variables inside handler", __FUNCTION__);
+  if (!empty_input) {
+    input_avail   = TSIOBufferReaderAvail(input_reader);
+    upstream_done = TSVIONDoneGet(input_vio);
+    toread        = TSVIONTodoGet(input_vio);
+
+    if (toread <= input_avail) { // upstream finished
+      eos = true;
+    } else {
+      eos = false;
+    }
+  } else {
+    input_avail   = 0;
+    upstream_done = 0;
+    toread        = 0;
+    eos           = true;
+  }
+
+  if (input_avail > 0) {

Review Comment:
   The input_avail is from the buffer. So we do the buffer copy with the number of bytes available in the buffer, not with the data left to be read. 
   
   I guess in reality you probably will not get toread < input_avail. 



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@trafficserver.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


[GitHub] [trafficserver] shukitchan commented on pull request #10004: Add support for request/response transform for Wasm plugin

Posted by "shukitchan (via GitHub)" <gi...@apache.org>.
shukitchan commented on PR #10004:
URL: https://github.com/apache/trafficserver/pull/10004#issuecomment-1655136811

   @serrislew ready for another review


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@trafficserver.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


[GitHub] [trafficserver] serrislew commented on a diff in pull request #10004: Add support for request/response transform for Wasm plugin

Posted by "serrislew (via GitHub)" <gi...@apache.org>.
serrislew commented on code in PR #10004:
URL: https://github.com/apache/trafficserver/pull/10004#discussion_r1276674333


##########
plugins/experimental/wasm/wasm_main.cc:
##########
@@ -46,6 +46,250 @@ struct WasmInstanceConfig {
 
 static std::unique_ptr<WasmInstanceConfig> wasm_config = nullptr;
 
+// handler for transform event
+static int
+transform_handler(TSCont contp, ats_wasm::TransformInfo *ti, TSEvent event)
+{
+  TSVConn output_conn;
+  TSVIO input_vio;
+  TSIOBufferReader input_reader;
+  TSIOBufferBlock blk;
+  int64_t toread, towrite, blk_len, upstream_done, input_avail;
+  const char *start;
+  const char *res;
+  size_t res_len;
+  int eos, write_down, empty_input;
+
+  ats_wasm::Context *c;
+
+  TSDebug(WASM_DEBUG_TAG, "[%s] transform handler begins", __FUNCTION__);
+  c = ti->context;
+
+  output_conn = TSTransformOutputVConnGet(contp);
+  input_vio   = TSVConnWriteVIOGet(contp);
+
+  empty_input = 0;
+
+  TSDebug(WASM_DEBUG_TAG, "[%s] cheking input VIO", __FUNCTION__);
+  if (!TSVIOBufferGet(input_vio)) {
+    if (ti->output_vio) {
+      TSDebug(WASM_DEBUG_TAG, "[%s] reenabling output VIO after input VIO does not exist", __FUNCTION__);
+      TSVIONBytesSet(ti->output_vio, ti->total);
+      TSVIOReenable(ti->output_vio);
+      return 0;
+    } else {
+      TSDebug(WASM_DEBUG_TAG, "[%s] no input VIO and output VIO", __FUNCTION__);
+      empty_input = 1;
+    }
+  }
+
+  if (empty_input == 0) {
+    input_reader = TSVIOReaderGet(input_vio);
+  }
+
+  TSDebug(WASM_DEBUG_TAG, "[%s] creating buffer and reader", __FUNCTION__);
+  if (!ti->output_buffer) {
+    ti->output_buffer = TSIOBufferCreate();
+    ti->output_reader = TSIOBufferReaderAlloc(ti->output_buffer);
+
+    ti->reserved_buffer = TSIOBufferCreate();
+    ti->reserved_reader = TSIOBufferReaderAlloc(ti->reserved_buffer);
+
+    if (empty_input == 0) {
+      ti->upstream_bytes = TSVIONBytesGet(input_vio);
+    } else {
+      ti->upstream_bytes = 0;
+    }
+
+    ti->downstream_bytes = INT64_MAX;
+  }
+
+  TSDebug(WASM_DEBUG_TAG, "[%s] init variables inside handler", __FUNCTION__);
+  if (empty_input == 0) {
+    input_avail   = TSIOBufferReaderAvail(input_reader);
+    upstream_done = TSVIONDoneGet(input_vio);
+    toread        = TSVIONTodoGet(input_vio);
+
+    if (toread <= input_avail) { // upstream finished
+      eos = 1;
+    } else {
+      eos = 0;
+    }
+  } else {
+    input_avail   = 0;
+    upstream_done = 0;
+    toread        = 0;
+    eos           = 1;
+  }
+
+  if (input_avail > 0) {
+    // move to the reserved.buffer
+    TSIOBufferCopy(ti->reserved_buffer, input_reader, input_avail, 0);
+
+    // reset input
+    TSIOBufferReaderConsume(input_reader, input_avail);
+    TSVIONDoneSet(input_vio, upstream_done + input_avail);
+  }
+
+  write_down = 0;
+  if (empty_input == 0) {
+    towrite = TSIOBufferReaderAvail(ti->reserved_reader);
+  } else {
+    towrite = 0;
+  }
+
+  do {
+    TSDebug(WASM_DEBUG_TAG, "[%s] inside transform handler loop", __FUNCTION__);
+    proxy_wasm::FilterDataStatus status = proxy_wasm::FilterDataStatus::Continue;
+
+    if (towrite == 0 && empty_input == 0) {
+      break;
+    }
+
+    TSDebug(WASM_DEBUG_TAG, "[%s] retrieving text and calling the wasm handler function", __FUNCTION__);
+    if (empty_input == 0) {
+      blk   = TSIOBufferReaderStart(ti->reserved_reader);
+      start = TSIOBufferBlockReadStart(blk, ti->reserved_reader, &blk_len);
+
+      int size = 0;
+      if (towrite > blk_len) {
+        c->setTransformResult(start, blk_len);
+        towrite -= blk_len;
+        TSIOBufferReaderConsume(ti->reserved_reader, blk_len);
+        size = blk_len;
+      } else {
+        c->setTransformResult(start, towrite);
+        TSIOBufferReaderConsume(ti->reserved_reader, towrite);
+        size    = towrite;
+        towrite = 0;
+      }
+
+      if (!towrite && eos) {
+        if (ti->request) {
+          status = c->onRequestBody(size, true);
+        } else {
+          status = c->onResponseBody(size, true);
+        }
+      } else {
+        if (ti->request) {
+          status = c->onRequestBody(size, false);
+        } else {
+          status = c->onResponseBody(size, false);
+        }
+      }
+    } else {
+      c->setTransformResult(nullptr, 0);
+      if (ti->request) {
+        status = c->onRequestBody(0, true);
+      } else {
+        status = c->onResponseBody(0, true);
+      }
+    }
+
+    TSDebug(WASM_DEBUG_TAG, "[%s] retrieving returns from wasm handler function and pass back to ATS", __FUNCTION__);
+    if ((status == proxy_wasm::FilterDataStatus::Continue) ||
+        ((status == proxy_wasm::FilterDataStatus::StopIterationAndBuffer ||
+          status == proxy_wasm::FilterDataStatus::StopIterationAndWatermark) &&
+         eos && !towrite)) {
+      res = c->getTransformResult(&res_len);
+
+      if (res && res_len > 0) {
+        if (!ti->output_vio) {
+          if (eos && !towrite) {
+            ti->output_vio = TSVConnWrite(output_conn, contp, ti->output_reader, res_len); // HttpSM go on
+          } else {
+            ti->output_vio = TSVConnWrite(output_conn, contp, ti->output_reader, ti->downstream_bytes); // HttpSM go on
+          }
+        }
+
+        TSIOBufferWrite(ti->output_buffer, res, res_len);
+        ti->total  += res_len;
+        write_down  = 1;
+      }
+
+      c->clearTransformResult();
+    }
+
+    if (status == proxy_wasm::FilterDataStatus::StopIterationNoBuffer) {
+      c->clearTransformResult();
+    }
+
+    if (eos && !towrite) { // EOS
+      eos = 1;
+      break;
+    }
+
+  } while (towrite > 0);
+
+  if (eos && !ti->output_vio) {
+    ti->output_vio = TSVConnWrite(output_conn, contp, ti->output_reader, 0);
+  }
+
+  if (write_down || eos) {
+    TSVIOReenable(ti->output_vio);
+  }
+
+  if (toread > input_avail) { // upstream not finished.
+    if (eos) {
+      TSVIONBytesSet(ti->output_vio, ti->total);
+      if (empty_input == 0) {
+        TSContCall(TSVIOContGet(input_vio), TS_EVENT_VCONN_EOS, input_vio);
+      }
+    } else {
+      if (empty_input == 0) {
+        TSContCall(TSVIOContGet(input_vio), TS_EVENT_VCONN_WRITE_READY, input_vio);
+      }
+    }
+  } else { // upstream is finished.
+    TSVIONBytesSet(ti->output_vio, ti->total);
+    if (empty_input == 0) {
+      TSContCall(TSVIOContGet(input_vio), TS_EVENT_VCONN_WRITE_COMPLETE, input_vio);
+    }
+  }
+
+  return 0;
+}
+
+static int
+transform_entry(TSCont contp, TSEvent ev, void *edata)
+{
+  int event;
+  TSVIO input_vio;
+  ats_wasm::TransformInfo *ti;
+
+  event = (int)ev;
+  ti    = (ats_wasm::TransformInfo *)TSContDataGet(contp);
+
+  TSDebug(WASM_DEBUG_TAG, "[%s] begin transform entry", __FUNCTION__);
+  if (TSVConnClosedGet(contp)) {
+    delete ti;
+    TSContDestroy(contp);
+    return 0;
+  }
+
+  TSDebug(WASM_DEBUG_TAG, "[%s] checking event inside transform entry", __FUNCTION__);
+  switch (event) {
+  case TS_EVENT_ERROR:
+    TSDebug(WASM_DEBUG_TAG, "[%s] event error", __FUNCTION__);
+    input_vio = TSVConnWriteVIOGet(contp);
+    TSContCall(TSVIOContGet(input_vio), TS_EVENT_ERROR, input_vio);
+    break;
+
+  case TS_EVENT_VCONN_WRITE_COMPLETE:
+    TSDebug(WASM_DEBUG_TAG, "[%s] event vconn write complete", __FUNCTION__);
+    TSVConnShutdown(TSTransformOutputVConnGet(contp), 0, 1);
+    break;
+
+  case TS_EVENT_VCONN_WRITE_READY:
+  default:

Review Comment:
   actually from `transform_handler` logic (in my previous comment), I don't think `TS_EVENT_VCONN_EOS` would even be called



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@trafficserver.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


[GitHub] [trafficserver] serrislew commented on a diff in pull request #10004: Add support for request/response transform for Wasm plugin

Posted by "serrislew (via GitHub)" <gi...@apache.org>.
serrislew commented on code in PR #10004:
URL: https://github.com/apache/trafficserver/pull/10004#discussion_r1270107593


##########
plugins/experimental/wasm/wasm_main.cc:
##########
@@ -46,6 +46,250 @@ struct WasmInstanceConfig {
 
 static std::unique_ptr<WasmInstanceConfig> wasm_config = nullptr;
 
+// handler for transform event
+static int
+transform_handler(TSCont contp, ats_wasm::TransformInfo *ti, TSEvent event)
+{
+  TSVConn output_conn;
+  TSVIO input_vio;
+  TSIOBufferReader input_reader;
+  TSIOBufferBlock blk;
+  int64_t toread, towrite, blk_len, upstream_done, input_avail;
+  const char *start;
+  const char *res;
+  size_t res_len;
+  int eos, write_down, empty_input;
+
+  ats_wasm::Context *c;
+
+  TSDebug(WASM_DEBUG_TAG, "[%s] transform handler begins", __FUNCTION__);
+  c = ti->context;
+
+  output_conn = TSTransformOutputVConnGet(contp);
+  input_vio   = TSVConnWriteVIOGet(contp);
+
+  empty_input = 0;
+
+  TSDebug(WASM_DEBUG_TAG, "[%s] cheking input VIO", __FUNCTION__);
+  if (!TSVIOBufferGet(input_vio)) {
+    if (ti->output_vio) {
+      TSDebug(WASM_DEBUG_TAG, "[%s] reenabling output VIO after input VIO does not exist", __FUNCTION__);
+      TSVIONBytesSet(ti->output_vio, ti->total);
+      TSVIOReenable(ti->output_vio);
+      return 0;
+    } else {
+      TSDebug(WASM_DEBUG_TAG, "[%s] no input VIO and output VIO", __FUNCTION__);
+      empty_input = 1;
+    }
+  }
+
+  if (empty_input == 0) {
+    input_reader = TSVIOReaderGet(input_vio);
+  }
+
+  TSDebug(WASM_DEBUG_TAG, "[%s] creating buffer and reader", __FUNCTION__);
+  if (!ti->output_buffer) {
+    ti->output_buffer = TSIOBufferCreate();
+    ti->output_reader = TSIOBufferReaderAlloc(ti->output_buffer);
+
+    ti->reserved_buffer = TSIOBufferCreate();
+    ti->reserved_reader = TSIOBufferReaderAlloc(ti->reserved_buffer);
+
+    if (empty_input == 0) {
+      ti->upstream_bytes = TSVIONBytesGet(input_vio);
+    } else {
+      ti->upstream_bytes = 0;
+    }
+
+    ti->downstream_bytes = INT64_MAX;
+  }
+
+  TSDebug(WASM_DEBUG_TAG, "[%s] init variables inside handler", __FUNCTION__);
+  if (empty_input == 0) {
+    input_avail   = TSIOBufferReaderAvail(input_reader);
+    upstream_done = TSVIONDoneGet(input_vio);
+    toread        = TSVIONTodoGet(input_vio);
+
+    if (toread <= input_avail) { // upstream finished
+      eos = 1;
+    } else {
+      eos = 0;
+    }
+  } else {
+    input_avail   = 0;
+    upstream_done = 0;
+    toread        = 0;
+    eos           = 1;
+  }
+
+  if (input_avail > 0) {
+    // move to the reserved.buffer
+    TSIOBufferCopy(ti->reserved_buffer, input_reader, input_avail, 0);
+
+    // reset input
+    TSIOBufferReaderConsume(input_reader, input_avail);
+    TSVIONDoneSet(input_vio, upstream_done + input_avail);
+  }
+
+  write_down = 0;
+  if (empty_input == 0) {
+    towrite = TSIOBufferReaderAvail(ti->reserved_reader);
+  } else {
+    towrite = 0;
+  }
+
+  do {
+    TSDebug(WASM_DEBUG_TAG, "[%s] inside transform handler loop", __FUNCTION__);
+    proxy_wasm::FilterDataStatus status = proxy_wasm::FilterDataStatus::Continue;
+
+    if (towrite == 0 && empty_input == 0) {
+      break;
+    }
+
+    TSDebug(WASM_DEBUG_TAG, "[%s] retrieving text and calling the wasm handler function", __FUNCTION__);
+    if (empty_input == 0) {
+      blk   = TSIOBufferReaderStart(ti->reserved_reader);
+      start = TSIOBufferBlockReadStart(blk, ti->reserved_reader, &blk_len);
+
+      int size = 0;
+      if (towrite > blk_len) {
+        c->setTransformResult(start, blk_len);
+        towrite -= blk_len;
+        TSIOBufferReaderConsume(ti->reserved_reader, blk_len);
+        size = blk_len;
+      } else {
+        c->setTransformResult(start, towrite);
+        TSIOBufferReaderConsume(ti->reserved_reader, towrite);
+        size    = towrite;
+        towrite = 0;
+      }
+
+      if (!towrite && eos) {
+        if (ti->request) {
+          status = c->onRequestBody(size, true);
+        } else {
+          status = c->onResponseBody(size, true);
+        }
+      } else {
+        if (ti->request) {
+          status = c->onRequestBody(size, false);
+        } else {
+          status = c->onResponseBody(size, false);
+        }
+      }
+    } else {
+      c->setTransformResult(nullptr, 0);
+      if (ti->request) {
+        status = c->onRequestBody(0, true);
+      } else {
+        status = c->onResponseBody(0, true);
+      }
+    }
+
+    TSDebug(WASM_DEBUG_TAG, "[%s] retrieving returns from wasm handler function and pass back to ATS", __FUNCTION__);
+    if ((status == proxy_wasm::FilterDataStatus::Continue) ||
+        ((status == proxy_wasm::FilterDataStatus::StopIterationAndBuffer ||
+          status == proxy_wasm::FilterDataStatus::StopIterationAndWatermark) &&
+         eos && !towrite)) {
+      res = c->getTransformResult(&res_len);
+
+      if (res && res_len > 0) {
+        if (!ti->output_vio) {
+          if (eos && !towrite) {
+            ti->output_vio = TSVConnWrite(output_conn, contp, ti->output_reader, res_len); // HttpSM go on
+          } else {
+            ti->output_vio = TSVConnWrite(output_conn, contp, ti->output_reader, ti->downstream_bytes); // HttpSM go on
+          }
+        }
+
+        TSIOBufferWrite(ti->output_buffer, res, res_len);
+        ti->total  += res_len;
+        write_down  = 1;
+      }
+
+      c->clearTransformResult();
+    }
+
+    if (status == proxy_wasm::FilterDataStatus::StopIterationNoBuffer) {
+      c->clearTransformResult();
+    }
+
+    if (eos && !towrite) { // EOS
+      eos = 1;
+      break;
+    }
+
+  } while (towrite > 0);
+
+  if (eos && !ti->output_vio) {
+    ti->output_vio = TSVConnWrite(output_conn, contp, ti->output_reader, 0);
+  }
+
+  if (write_down || eos) {
+    TSVIOReenable(ti->output_vio);
+  }
+
+  if (toread > input_avail) { // upstream not finished.
+    if (eos) {
+      TSVIONBytesSet(ti->output_vio, ti->total);
+      if (empty_input == 0) {
+        TSContCall(TSVIOContGet(input_vio), TS_EVENT_VCONN_EOS, input_vio);
+      }
+    } else {
+      if (empty_input == 0) {
+        TSContCall(TSVIOContGet(input_vio), TS_EVENT_VCONN_WRITE_READY, input_vio);
+      }
+    }
+  } else { // upstream is finished.
+    TSVIONBytesSet(ti->output_vio, ti->total);
+    if (empty_input == 0) {
+      TSContCall(TSVIOContGet(input_vio), TS_EVENT_VCONN_WRITE_COMPLETE, input_vio);
+    }
+  }
+
+  return 0;
+}
+
+static int
+transform_entry(TSCont contp, TSEvent ev, void *edata)
+{
+  int event;
+  TSVIO input_vio;
+  ats_wasm::TransformInfo *ti;
+
+  event = (int)ev;
+  ti    = (ats_wasm::TransformInfo *)TSContDataGet(contp);
+
+  TSDebug(WASM_DEBUG_TAG, "[%s] begin transform entry", __FUNCTION__);
+  if (TSVConnClosedGet(contp)) {
+    delete ti;
+    TSContDestroy(contp);
+    return 0;
+  }
+
+  TSDebug(WASM_DEBUG_TAG, "[%s] checking event inside transform entry", __FUNCTION__);
+  switch (event) {
+  case TS_EVENT_ERROR:
+    TSDebug(WASM_DEBUG_TAG, "[%s] event error", __FUNCTION__);
+    input_vio = TSVConnWriteVIOGet(contp);
+    TSContCall(TSVIOContGet(input_vio), TS_EVENT_ERROR, input_vio);
+    break;
+
+  case TS_EVENT_VCONN_WRITE_COMPLETE:
+    TSDebug(WASM_DEBUG_TAG, "[%s] event vconn write complete", __FUNCTION__);
+    TSVConnShutdown(TSTransformOutputVConnGet(contp), 0, 1);
+    break;
+
+  case TS_EVENT_VCONN_WRITE_READY:
+  default:

Review Comment:
   does `TS_EVENT_VCONN_EOS` not have a different course of action or is it assumed that it will eventually go to `TS_EVENT_VCONN_WRITE_COMPLETE`



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@trafficserver.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org