| /** @file | |
| Licensed to the Apache Software Foundation (ASF) under one | |
| or more contributor license agreements. See the NOTICE file | |
| distributed with this work for additional information | |
| regarding copyright ownership. The ASF licenses this file | |
| to you under the Apache License, Version 2.0 (the | |
| "License"); you may not use this file except in compliance | |
| with the License. You may obtain a copy of the License at | |
| http://www.apache.org/licenses/LICENSE-2.0 | |
| Unless required by applicable law or agreed to in writing, software | |
| distributed under the License is distributed on an "AS IS" BASIS, | |
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
| See the License for the specific language governing permissions and | |
| limitations under the License. | |
| */ | |
| #include "intercept.h" | |
| #include "Data.h" | |
| #include "client.h" | |
| #include "server.h" | |
| #include "slice.h" | |
| int | |
| intercept_hook(TSCont contp, TSEvent event, void *edata) | |
| { | |
| Data *const data = static_cast<Data *>(TSContDataGet(contp)); | |
| if (nullptr == data) { | |
| ERROR_LOG("intercept_hook called without data"); | |
| TSContDestroy(contp); | |
| return TS_EVENT_ERROR; | |
| } | |
| // After the initial TS_EVENT_NET_ACCEPT | |
| // any "events" will be handled by the vio read or write channel handler | |
| switch (event) { | |
| case TS_EVENT_NET_ACCEPT: { | |
| // set up reader from client | |
| TSVConn const downvc = static_cast<TSVConn>(edata); | |
| data->m_dnstream.setupConnection(downvc); | |
| data->m_dnstream.setupVioRead(contp, INT64_MAX); | |
| } break; | |
| case TS_EVENT_NET_ACCEPT_FAILED: | |
| case TS_EVENT_VCONN_INACTIVITY_TIMEOUT: | |
| case TS_EVENT_VCONN_ACTIVE_TIMEOUT: | |
| case TS_EVENT_ERROR: { | |
| abort(contp, data); | |
| } break; | |
| default: { | |
| // data from client -- only the initial header | |
| if (data->m_dnstream.m_read.isOpen() && edata == data->m_dnstream.m_read.m_vio) { | |
| if (handle_client_req(contp, event, data)) { | |
| // DEBUG_LOG("shutting down read from client pipe"); | |
| TSVConnShutdown(data->m_dnstream.m_vc, 1, 0); | |
| } | |
| } | |
| // The complete request header is sufficient for GET, HEAD, and PURGE. | |
| // Mark the write channel done without shutting down the VC write side, | |
| // so the internal transaction does not receive an EOS and interpret it | |
| // as a client abort. | |
| else if (data->m_upstream.m_write.isOpen() && edata == data->m_upstream.m_write.m_vio) { | |
| if (TS_EVENT_VCONN_WRITE_COMPLETE == event) { | |
| data->m_upstream.m_write.close(); | |
| } | |
| } | |
| // server has data for us | |
| else if (data->m_upstream.m_read.isOpen() && edata == data->m_upstream.m_read.m_vio) { | |
| handle_server_resp(contp, event, data); | |
| } | |
| // client wants more data from us, only body content | |
| else if (data->m_dnstream.m_write.isOpen() && edata == data->m_dnstream.m_write.m_vio) { | |
| handle_client_resp(contp, event, data); | |
| } else { | |
| ERROR_LOG("Unhandled event: %d", event); | |
| } | |
| } break; | |
| } | |
| return TS_EVENT_CONTINUE; | |
| } |