/* Process a read event from the SM */ static void acme_process_read(TSCont contp, TSEvent event, AcmeState *my_state) { if (event == TS_EVENT_VCONN_READ_READY) { if (-1 == my_state->fd) { my_state->output_bytes = add_data_to_resp(ACME_DENIED_RESP, strlen(ACME_DENIED_RESP), my_state); } else { my_state->output_bytes = add_data_to_resp(ACME_OK_RESP, strlen(ACME_OK_RESP), my_state); } TSVConnShutdown(my_state->net_vc, 1, 0); my_state->write_vio = TSVConnWrite(my_state->net_vc, contp, my_state->resp_reader, INT64_MAX); } else if (event == TS_EVENT_ERROR) { TSError("[%s] acme_process_read: Received TS_EVENT_ERROR", PLUGIN_NAME); } else if (event == TS_EVENT_VCONN_EOS) { /* client may end the connection, simply return */ return; } else if (event == TS_EVENT_NET_ACCEPT_FAILED) { TSError("[%s] acme_process_read: Received TS_EVENT_NET_ACCEPT_FAILED", PLUGIN_NAME); } else { TSReleaseAssert(!"Unexpected Event"); } }
/* Process a write event from the SM */ static void hc_process_write(TSCont contp, TSEvent event, HCState *my_state) { if (event == TS_EVENT_VCONN_WRITE_READY) { char buf[48]; int len; len = snprintf(buf, sizeof(buf)-1, "Content-Length: %d\r\n\r\n", my_state->data->b_len); my_state->output_bytes += add_data_to_resp(buf, len, my_state); if (my_state->data->b_len > 0) my_state->output_bytes += add_data_to_resp(my_state->data->body, my_state->data->b_len, my_state); else my_state->output_bytes += add_data_to_resp("\r\n", 2, my_state); TSVIONBytesSet(my_state->write_vio, my_state->output_bytes); TSVIOReenable(my_state->write_vio); } else if (TS_EVENT_VCONN_WRITE_COMPLETE) { cleanup(contp, my_state); } else if (event == TS_EVENT_ERROR) { TSError("hc_process_write: Received TS_EVENT_ERROR\n"); } else { TSReleaseAssert(!"Unexpected Event"); } }
/* Process a read event from the SM */ static void hc_process_read(TSCont contp, TSEvent event, HCState *my_state) { if (event == TS_EVENT_VCONN_READ_READY) { if (my_state->data->exists) { TSDebug(PLUGIN_NAME, "Setting OK response header"); my_state->output_bytes = add_data_to_resp(my_state->info->ok, my_state->info->o_len, my_state); } else { TSDebug(PLUGIN_NAME, "Setting MISS response header"); my_state->output_bytes = add_data_to_resp(my_state->info->miss, my_state->info->m_len, my_state); } TSVConnShutdown(my_state->net_vc, 1, 0); my_state->write_vio = TSVConnWrite(my_state->net_vc, contp, my_state->resp_reader, INT64_MAX); } else if (event == TS_EVENT_ERROR) { TSError("hc_process_read: Received TS_EVENT_ERROR\n"); } else if (event == TS_EVENT_VCONN_EOS) { /* client may end the connection, simply return */ return; } else if (event == TS_EVENT_NET_ACCEPT_FAILED) { TSError("hc_process_read: Received TS_EVENT_NET_ACCEPT_FAILED\n"); } else { TSReleaseAssert(!"Unexpected Event"); } }
/* Process a write event from the SM */ static void acme_process_write(TSCont contp, TSEvent event, AcmeState *my_state) { if (event == TS_EVENT_VCONN_WRITE_READY) { char buf[64]; /* Plenty of space for CL: header */ int len; len = snprintf(buf, sizeof(buf) - 1, "Content-Length: %zd\r\n\r\n", my_state->stat_buf.st_size); my_state->output_bytes += add_data_to_resp(buf, len, my_state); my_state->output_bytes += add_file_to_resp(my_state); TSVIONBytesSet(my_state->write_vio, my_state->output_bytes); TSVIOReenable(my_state->write_vio); } else if (TS_EVENT_VCONN_WRITE_COMPLETE) { cleanup(contp, my_state); } else if (event == TS_EVENT_ERROR) { TSError("[%s] acme_process_write: Received TS_EVENT_ERROR", PLUGIN_NAME); } else { TSReleaseAssert(!"Unexpected Event"); } }
static int add_file_to_resp(AcmeState *my_state) { if (-1 == my_state->fd) { return add_data_to_resp("\r\n", 2, my_state); } else { int ret = 0, len; char buf[8192]; while (1) { len = read(my_state->fd, buf, sizeof(buf)); if ((0 == len) || ((-1 == len) && (errno != EAGAIN) && (errno != EINTR))) { break; } else { TSIOBufferWrite(my_state->resp_buffer, buf, len); ret += len; } } close(my_state->fd); my_state->fd = -1; return ret; } }