blob: 34e21ae227274b025d78840b903529feb6b49e87 [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 "P_Net.h"
#include "P_QUICNet.h"
#include "quic/QUICEvents.h"
ClassAllocator<QUICPollEvent> quicPollEventAllocator("quicPollEvent");
void
QUICPollEvent::init(QUICConnection *con, UDPPacketInternal *packet)
{
this->con = con;
this->packet = packet;
if (con != nullptr) {
static_cast<QUICNetVConnection *>(con)->refcount_inc();
}
}
void
QUICPollEvent::free()
{
if (this->con != nullptr) {
ink_assert(static_cast<QUICNetVConnection *>(this->con)->refcount_dec() >= 0);
this->con = nullptr;
}
quicPollEventAllocator.free(this);
}
QUICPollCont::QUICPollCont(Ptr<ProxyMutex> &m) : Continuation(m.get()), net_handler(nullptr)
{
SET_HANDLER(&QUICPollCont::pollEvent);
}
QUICPollCont::QUICPollCont(Ptr<ProxyMutex> &m, NetHandler *nh) : Continuation(m.get()), net_handler(nh)
{
SET_HANDLER(&QUICPollCont::pollEvent);
}
QUICPollCont::~QUICPollCont() {}
void
QUICPollCont::_process_long_header_packet(QUICPollEvent *e, NetHandler *nh)
{
UDPPacketInternal *p = e->packet;
// FIXME: VC is nullptr ?
QUICNetVConnection *vc = static_cast<QUICNetVConnection *>(e->con);
uint8_t *buf = (uint8_t *)p->getIOBlockChain()->buf();
QUICPacketType ptype;
QUICLongHeaderPacketR::type(ptype, buf, 1);
if (ptype == QUICPacketType::INITIAL && !vc->read.triggered) {
SCOPED_MUTEX_LOCK(lock, vc->mutex, this_ethread());
vc->read.triggered = 1;
vc->handle_received_packet(p);
vc->handleEvent(QUIC_EVENT_PACKET_READ_READY, nullptr);
e->free();
return;
}
if (vc) {
SCOPED_MUTEX_LOCK(lock, vc->mutex, this_ethread());
vc->read.triggered = 1;
vc->handle_received_packet(p);
} else {
this->_longInQueue.push(p);
}
// Push QUICNetVC into nethandler's enabled list
if (vc != nullptr) {
int isin = ink_atomic_swap(&vc->read.in_enabled_list, 1);
if (!isin) {
nh->read_enable_list.push(vc);
}
}
// Note: We should free QUICPollEvent here since vc could be freed from other thread.
e->free();
}
void
QUICPollCont::_process_short_header_packet(QUICPollEvent *e, NetHandler *nh)
{
UDPPacketInternal *p = e->packet;
QUICNetVConnection *vc = static_cast<QUICNetVConnection *>(e->con);
vc->read.triggered = 1;
vc->handle_received_packet(p);
// Push QUICNetVC into nethandler's enabled list
int isin = ink_atomic_swap(&vc->read.in_enabled_list, 1);
if (!isin) {
nh->read_enable_list.push(vc);
}
// Note: We should free QUICPollEvent here since vc could be freed from other thread.
e->free();
}
//
// QUICPollCont continuation which traverse the inQueue(ASLL)
// and create new QUICNetVC for Initial Packet,
// and push the triggered QUICNetVC into enable list.
//
int
QUICPollCont::pollEvent(int, Event *)
{
ink_assert(this->mutex->thread_holding == this_thread());
uint8_t *buf;
QUICPollEvent *e;
NetHandler *nh = get_NetHandler(this->mutex->thread_holding);
// Process the ASLL
SList(QUICPollEvent, alink) aq(inQueue.popall());
Queue<QUICPollEvent> result;
while ((e = aq.pop())) {
QUICNetVConnection *qvc = static_cast<QUICNetVConnection *>(e->con);
UDPPacketInternal *p = e->packet;
if (qvc != nullptr && qvc->in_closed_queue) {
p->free();
e->free();
continue;
}
result.push(e);
}
while ((e = result.pop())) {
buf = (uint8_t *)e->packet->getIOBlockChain()->buf();
if (QUICInvariants::is_long_header(buf)) {
// Long Header Packet with Connection ID, has a valid type value.
this->_process_long_header_packet(e, nh);
} else {
// Short Header Packet with Connection ID, has a valid type value.
this->_process_short_header_packet(e, nh);
}
}
return EVENT_CONT;
}
void
initialize_thread_for_quic_net(EThread *thread)
{
NetHandler *nh = get_NetHandler(thread);
QUICPollCont *quicpc = get_QUICPollCont(thread);
new ((ink_dummy_for_new *)quicpc) QUICPollCont(thread->mutex, nh);
thread->schedule_every(quicpc, -HRTIME_MSECONDS(UDP_PERIOD));
}