This is an automated email from the ASF dual-hosted git repository.

masaori pushed a commit to branch quic-latest
in repository https://gitbox.apache.org/repos/asf/trafficserver.git


The following commit(s) were added to refs/heads/quic-latest by this push:
     new 7052a17  Close QUIC Connection by inactivity timeout
7052a17 is described below

commit 7052a17f4e884e013d6efc78167375a6e2787093
Author: Masaori Koshiba <masa...@apache.org>
AuthorDate: Wed Aug 9 15:20:35 2017 +0900

    Close QUIC Connection by inactivity timeout
---
 iocore/net/P_QUICNetVConnection.h   | 30 +++++++++++----
 iocore/net/P_UnixNetVConnection.h   | 15 ++++----
 iocore/net/QUICNetVConnection.cc    | 75 ++++++++++++++++++++++++++++++++++---
 iocore/net/quic/QUICEvents.h        |  1 +
 iocore/net/quic/QUICLossDetector.cc | 14 ++++++-
 iocore/net/quic/QUICLossDetector.h  |  1 +
 6 files changed, 114 insertions(+), 22 deletions(-)

diff --git a/iocore/net/P_QUICNetVConnection.h 
b/iocore/net/P_QUICNetVConnection.h
index e0bd7cc..09caae2 100644
--- a/iocore/net/P_QUICNetVConnection.h
+++ b/iocore/net/P_QUICNetVConnection.h
@@ -93,6 +93,15 @@ typedef enum {
   QUIC_HOOK_OP_LAST = QUIC_HOOK_OP_TERMINATE ///< End marker value.
 } QuicVConnOp;
 
+enum class QUICConnectionState {
+  Open = 0,
+  Handshake,
+  Established,
+  TimeWait,
+  Closing,
+  Closed,
+};
+
 //////////////////////////////////////////////////////////////////
 //
 //  class NetVConnection
@@ -113,20 +122,23 @@ class QUICLossDetector;
  *
  * state_handshake()
  *  | READ:
- *  |  _state_handshake_process_initial_client_packet()
- *  |  _state_handshake_process_client_cleartext_packet()
- *  |  _state_handshake_process_zero_rtt_protected_packet()
+ *  |   _state_handshake_process_initial_client_packet()
+ *  |   _state_handshake_process_client_cleartext_packet()
+ *  |   _state_handshake_process_zero_rtt_protected_packet()
  *  | WRITE:
- *  |  _state_common_send_packet()
+ *  |   _state_common_send_packet()
  *  v
  * state_connection_established()
  *  | READ:
- *  |  _state_connection_established_process_packet()
+ *  |   _state_connection_established_process_packet()
  *  | WRITE:
- *  |  _state_common_send_packet()
+ *  |   _state_common_send_packet()
  *  v
- *  X
- *
+ * state_connection_close()
+ *    READ:
+ *      Do nothing
+ *    WRITE:
+ *      _state_common_send_packet()
  **/
 class QUICNetVConnection : public UnixNetVConnection, public 
QUICPacketTransmitter, public QUICFrameTransmitter
 {
@@ -143,6 +155,7 @@ public:
   int startEvent(int event, Event *e);
   int state_handshake(int event, Event *data);
   int state_connection_established(int event, Event *data);
+  int state_connection_closed(int event, Event *data);
   void start(SSL_CTX *);
   uint32_t maximum_quic_packet_size();
   uint32_t minimum_quic_packet_size();
@@ -168,6 +181,7 @@ private:
   QUICPacketFactory _packet_factory;
   QUICFrameFactory _frame_factory;
   QUICAckFrameCreator _ack_frame_creator;
+  QUICConnectionState _state = QUICConnectionState::Open;
 
   uint32_t _pmtu = 1280;
 
diff --git a/iocore/net/P_UnixNetVConnection.h 
b/iocore/net/P_UnixNetVConnection.h
index c86a136..91b8d2c 100644
--- a/iocore/net/P_UnixNetVConnection.h
+++ b/iocore/net/P_UnixNetVConnection.h
@@ -150,14 +150,14 @@ public:
   // called when handing an  event from this NetVConnection,//
   // or the NetVConnection creation callback.               //
   ////////////////////////////////////////////////////////////
-  void set_active_timeout(ink_hrtime timeout_in) override;
-  void set_inactivity_timeout(ink_hrtime timeout_in) override;
-  void cancel_active_timeout() override;
-  void cancel_inactivity_timeout() override;
+  virtual void set_active_timeout(ink_hrtime timeout_in) override;
+  virtual void set_inactivity_timeout(ink_hrtime timeout_in) override;
+  virtual void cancel_active_timeout() override;
+  virtual void cancel_inactivity_timeout() override;
   void set_action(Continuation *c) override;
-  void add_to_keep_alive_queue() override;
-  void remove_from_keep_alive_queue() override;
-  bool add_to_active_queue() override;
+  virtual void add_to_keep_alive_queue() override;
+  virtual void remove_from_keep_alive_queue() override;
+  virtual bool add_to_active_queue() override;
   virtual void remove_from_active_queue();
 
   // The public interface is VIO::reenable()
@@ -432,5 +432,6 @@ UnixNetVConnection::set_action(Continuation *c)
 void close_UnixNetVConnection(UnixNetVConnection *vc, EThread *t);
 void write_to_net(NetHandler *nh, UnixNetVConnection *vc, EThread *thread);
 void write_to_net_io(NetHandler *nh, UnixNetVConnection *vc, EThread *thread);
+void net_activity(UnixNetVConnection *vc, EThread *thread);
 
 #endif
diff --git a/iocore/net/QUICNetVConnection.cc b/iocore/net/QUICNetVConnection.cc
index afb4226..5eb4130 100644
--- a/iocore/net/QUICNetVConnection.cc
+++ b/iocore/net/QUICNetVConnection.cc
@@ -49,6 +49,7 @@ ClassAllocator<QUICNetVConnection> 
quicNetVCAllocator("quicNetVCAllocator");
 
 QUICNetVConnection::QUICNetVConnection() : UnixNetVConnection()
 {
+  this->_state = QUICConnectionState::Handshake;
   SET_HANDLER((NetVConnHandler)&QUICNetVConnection::state_handshake);
 }
 
@@ -99,16 +100,13 @@ QUICNetVConnection::start(SSL_CTX *ssl_ctx)
   std::shared_ptr<QUICCongestionController> congestionController = 
std::make_shared<QUICCongestionController>();
   this->_frame_dispatcher =
     new QUICFrameDispatcher(connectionManager, this->_stream_manager, 
flowController, congestionController, this->_loss_detector);
-
-  // TODO set timeout from conf
-  this->set_active_timeout(0);
-  this->set_inactivity_timeout(2);
 }
 
-// TODO: call free when close connection
 void
 QUICNetVConnection::free(EThread *t)
 {
+  Debug(tag, "Free connection: %p", this);
+
   this->_udp_con        = nullptr;
   this->_packet_handler = nullptr;
 
@@ -215,6 +213,7 @@ QUICNetVConnection::close(QUICError error)
   
this->transmit_frame(QUICFrameFactory::create_connection_close_frame(error.code,
 0, ""));
 }
 
+// TODO: Timeout by active_timeout / inactive_timeout
 int
 QUICNetVConnection::state_handshake(int event, Event *data)
 {
@@ -231,6 +230,8 @@ QUICNetVConnection::state_handshake(int event, Event *data)
   switch (event) {
   case QUIC_EVENT_PACKET_READ_READY: {
     std::unique_ptr<const QUICPacket> p = std::unique_ptr<const 
QUICPacket>(this->_packet_recv_queue.dequeue());
+    net_activity(this, this_ethread());
+
     switch (p->type()) {
     case QUICPacketType::CLIENT_INITIAL:
       error = 
this->_state_handshake_process_initial_client_packet(std::move(p));
@@ -263,7 +264,14 @@ QUICNetVConnection::state_handshake(int event, Event *data)
 
   if (this->_handshake_handler && this->_handshake_handler->is_completed()) {
     Debug(tag, "Enter state_connection_established");
+    this->_state = QUICConnectionState::Established;
     
SET_HANDLER((NetVConnHandler)&QUICNetVConnection::state_connection_established);
+
+    // TODO: switch waiting for a CONNECTION_CLOSE frame for first 
implementation
+    // TODO: read idle_timeout from Transport Prameters
+    ink_hrtime idle_timeout = HRTIME_SECONDS(3);
+    this->set_inactivity_timeout(idle_timeout);
+    this->add_to_active_queue();
   }
 
   return EVENT_CONT;
@@ -276,6 +284,8 @@ QUICNetVConnection::state_connection_established(int event, 
Event *data)
   switch (event) {
   case QUIC_EVENT_PACKET_READ_READY: {
     std::unique_ptr<const QUICPacket> p = std::unique_ptr<const 
QUICPacket>(this->_packet_recv_queue.dequeue());
+    net_activity(this, this_ethread());
+
     switch (p->type()) {
     case QUICPacketType::ONE_RTT_PROTECTED_KEY_PHASE_0:
     case QUICPacketType::ONE_RTT_PROTECTED_KEY_PHASE_1:
@@ -291,6 +301,22 @@ QUICNetVConnection::state_connection_established(int 
event, Event *data)
     error = this->_state_common_send_packet();
     break;
   }
+
+  case EVENT_IMMEDIATE: {
+    // Start Implicit Shutdown. Because no network activity for the duration 
of the idle timeout.
+    this->remove_from_active_queue();
+
+    // TODO: signal VC_EVENT_ACTIVE_TIMEOUT/VC_EVENT_INACTIVITY_TIMEOUT to 
application
+    Debug(tag, "Enter state_connection_close");
+    this->_state = QUICConnectionState::Closing;
+    SET_HANDLER((NetVConnHandler)&QUICNetVConnection::state_connection_closed);
+
+    this->close({QUICErrorClass::NONE, QUICErrorCode::QUIC_TRANSPORT_ERROR});
+
+    break;
+  }
+  default:
+    Debug(tag, "Unexpected event: %u", event);
   }
 
   if (error.cls != QUICErrorClass::NONE) {
@@ -301,6 +327,43 @@ QUICNetVConnection::state_connection_established(int 
event, Event *data)
   return EVENT_CONT;
 }
 
+int
+QUICNetVConnection::state_connection_closed(int event, Event *data)
+{
+  switch (event) {
+  case QUIC_EVENT_PACKET_READ_READY: {
+    // TODO: send GOAWAY frame
+    break;
+  }
+  case QUIC_EVENT_PACKET_WRITE_READY: {
+    // TODO: Retransmit CONNECTION_CLOSE when Explicit Shutdown (Out of scope 
from first implementation)
+    // Inplicit Shutdown
+    if (this->_state == QUICConnectionState::Closing) {
+      this->_state_common_send_packet();
+      this->_state = QUICConnectionState::Closed;
+
+      this->next_inactivity_timeout_at = 0;
+      this->next_activity_timeout_at   = 0;
+
+      this->inactivity_timeout_in = 0;
+      this->active_timeout_in     = 0;
+
+      // TODO: Drop record from Connection-ID - QUICNetVConnection table in 
QUICPacketHandler
+      // Shutdown loss detector
+      this->_loss_detector->handleEvent(QUIC_EVENT_LD_SHUTDOWN, nullptr);
+
+      this->free(this_ethread());
+    }
+
+    break;
+  }
+  default:
+    Debug(tag, "Unexpected event: %u", event);
+  }
+
+  return EVENT_DONE;
+}
+
 UDPConnection *
 QUICNetVConnection::get_udp_con()
 {
@@ -437,6 +500,8 @@ QUICNetVConnection::_state_common_send_packet()
     this->_loss_detector->on_packet_sent(std::unique_ptr<const 
QUICPacket>(packet));
   }
 
+  net_activity(this, this_ethread());
+
   return QUICError(QUICErrorClass::NONE);
 }
 
diff --git a/iocore/net/quic/QUICEvents.h b/iocore/net/quic/QUICEvents.h
index 1a8a9b2..de27a78 100644
--- a/iocore/net/quic/QUICEvents.h
+++ b/iocore/net/quic/QUICEvents.h
@@ -28,4 +28,5 @@
 enum {
   QUIC_EVENT_PACKET_READ_READY = QUIC_EVENT_EVENTS_START,
   QUIC_EVENT_PACKET_WRITE_READY,
+  QUIC_EVENT_LD_SHUTDOWN,
 };
diff --git a/iocore/net/quic/QUICLossDetector.cc 
b/iocore/net/quic/QUICLossDetector.cc
index 5ffc58f..4e2cdbf 100644
--- a/iocore/net/quic/QUICLossDetector.cc
+++ b/iocore/net/quic/QUICLossDetector.cc
@@ -53,9 +53,19 @@ int
 QUICLossDetector::event_handler(int event, Event *edata)
 {
   switch (event) {
-  case EVENT_INTERVAL:
+  case EVENT_INTERVAL: {
     this->_on_loss_detection_alarm();
     break;
+  }
+  case QUIC_EVENT_LD_SHUTDOWN: {
+    SCOPED_MUTEX_LOCK(lock, this->mutex, this_ethread());
+    Debug("quic_loss_detector", "Shutdown");
+
+    if (this->_loss_detection_alarm) {
+      this->_loss_detection_alarm->cancel();
+    }
+    break;
+  }
   default:
     break;
   }
@@ -121,7 +131,7 @@ QUICLossDetector::on_packet_sent(std::unique_ptr<const 
QUICPacket> packet)
 {
   bool is_handshake   = false;
   QUICPacketType type = packet->type();
-  if (type != QUICPacketType::ZERO_RTT_PROTECTED || type != 
QUICPacketType::ONE_RTT_PROTECTED_KEY_PHASE_0 ||
+  if (type != QUICPacketType::ZERO_RTT_PROTECTED && type != 
QUICPacketType::ONE_RTT_PROTECTED_KEY_PHASE_0 &&
       type != QUICPacketType::ONE_RTT_PROTECTED_KEY_PHASE_1) {
     is_handshake = true;
   }
diff --git a/iocore/net/quic/QUICLossDetector.h 
b/iocore/net/quic/QUICLossDetector.h
index 0a2b71c..7d6f325 100644
--- a/iocore/net/quic/QUICLossDetector.h
+++ b/iocore/net/quic/QUICLossDetector.h
@@ -100,6 +100,7 @@ private:
   void _detect_lost_packets(QUICPacketNumber largest_acked);
   void _set_loss_detection_alarm();
   void _on_loss_detection_alarm();
+
   std::set<QUICPacketNumber> _determine_newly_acked_packets(const QUICAckFrame 
&ack_frame);
 
   void _retransmit_handshake_packets();

-- 
To stop receiving notification emails like this one, please contact
['"commits@trafficserver.apache.org" <commits@trafficserver.apache.org>'].

Reply via email to