blob: b6dc02a9b2f76e159f068fbe856829fea0f95ef0 [file] [log] [blame]
/** @file
*
* A brief file description
*
* @section license License
*
* 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 "Http09App.h"
#include "tscore/ink_resolver.h"
#include "P_Net.h"
#include "P_VConnection.h"
#include "P_QUICNetVConnection.h"
#include "QUICDebugNames.h"
#include "QUICStreamVCAdapter.h"
#include "Http3Session.h"
#include "Http3Transaction.h"
static constexpr char debug_tag[] = "quic_simple_app";
static constexpr char debug_tag_v[] = "v_quic_simple_app";
Http09App::Http09App(QUICNetVConnection *client_vc, IpAllow::ACL &&session_acl, const HttpSessionAccept::Options &options)
: QUICApplication(client_vc)
{
this->_ssn = new Http09Session(client_vc);
this->_ssn->acl = std::move(session_acl);
this->_ssn->accept_options = &options;
this->_ssn->new_connection(client_vc, nullptr, nullptr);
this->_qc->stream_manager()->set_default_application(this);
SET_HANDLER(&Http09App::main_event_handler);
}
Http09App::~Http09App()
{
delete this->_ssn;
}
void
Http09App::on_new_stream(QUICStream &stream)
{
auto ret = this->_streams.emplace(stream.id(), stream);
auto &info = ret.first->second;
switch (stream.direction()) {
case QUICStreamDirection::BIDIRECTIONAL:
info.setup_read_vio(this);
info.setup_write_vio(this);
break;
case QUICStreamDirection::SEND:
info.setup_write_vio(this);
break;
case QUICStreamDirection::RECEIVE:
info.setup_read_vio(this);
break;
default:
ink_assert(false);
break;
}
stream.set_io_adapter(&info.adapter);
}
int
Http09App::main_event_handler(int event, Event *data)
{
Debug(debug_tag_v, "[%s] %s (%d)", this->_qc->cids().data(), get_vc_event_name(event), event);
VIO *vio = reinterpret_cast<VIO *>(data->cookie);
QUICStreamVCAdapter *adapter = static_cast<QUICStreamVCAdapter *>(vio->vc_server);
if (adapter == nullptr) {
Debug(debug_tag, "[%s] Unknown Stream", this->_qc->cids().data());
return -1;
}
bool is_bidirectional = adapter->stream().is_bidirectional();
QUICStreamId stream_id = adapter->stream().id();
Http09Transaction *txn = static_cast<Http09Transaction *>(this->_ssn->get_transaction(stream_id));
switch (event) {
case VC_EVENT_READ_READY:
case VC_EVENT_READ_COMPLETE:
if (!is_bidirectional) {
// FIXME Ignore unidirectional streams for now
break;
}
if (txn == nullptr) {
if (auto ret = this->_streams.find(stream_id); ret != this->_streams.end()) {
txn = new Http09Transaction(this->_ssn, ret->second);
SCOPED_MUTEX_LOCK(lock, txn->mutex, this_ethread());
txn->new_transaction();
} else {
ink_assert(!"Stream info should exist");
}
} else {
SCOPED_MUTEX_LOCK(lock, txn->mutex, this_ethread());
txn->handleEvent(event);
}
break;
case VC_EVENT_WRITE_READY:
case VC_EVENT_WRITE_COMPLETE:
if (txn != nullptr) {
SCOPED_MUTEX_LOCK(lock, txn->mutex, this_ethread());
txn->handleEvent(event);
}
break;
case VC_EVENT_EOS:
case VC_EVENT_ERROR:
case VC_EVENT_INACTIVITY_TIMEOUT:
case VC_EVENT_ACTIVE_TIMEOUT:
ink_assert(false);
break;
default:
break;
}
return EVENT_CONT;
}