You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@qpid.apache.org by tr...@apache.org on 2017/10/02 20:31:34 UTC

qpid-dispatch git commit: DISPATCH-551 - Added a configurable timeout to close connections that don't complete the opening handshake after transport establishment.

Repository: qpid-dispatch
Updated Branches:
  refs/heads/master 24a7085f2 -> 272398ddc


DISPATCH-551 - Added a configurable timeout to close connections that don't complete the opening handshake after transport establishment.


Project: http://git-wip-us.apache.org/repos/asf/qpid-dispatch/repo
Commit: http://git-wip-us.apache.org/repos/asf/qpid-dispatch/commit/272398dd
Tree: http://git-wip-us.apache.org/repos/asf/qpid-dispatch/tree/272398dd
Diff: http://git-wip-us.apache.org/repos/asf/qpid-dispatch/diff/272398dd

Branch: refs/heads/master
Commit: 272398ddc282da2e3751917c18e4e7f8a472ba42
Parents: 24a7085
Author: Ted Ross <tr...@redhat.com>
Authored: Mon Oct 2 16:30:12 2017 -0400
Committer: Ted Ross <tr...@redhat.com>
Committed: Mon Oct 2 16:30:12 2017 -0400

----------------------------------------------------------------------
 include/qpid/dispatch/server.h                |  7 ++++
 python/qpid_dispatch/management/qdrouter.json |  8 +++++
 src/connection_manager.c                      |  8 +++--
 src/server.c                                  | 38 +++++++++++++++++++++-
 src/server_private.h                          |  1 +
 5 files changed, 58 insertions(+), 4 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/qpid-dispatch/blob/272398dd/include/qpid/dispatch/server.h
----------------------------------------------------------------------
diff --git a/include/qpid/dispatch/server.h b/include/qpid/dispatch/server.h
index db25856..472fda6 100644
--- a/include/qpid/dispatch/server.h
+++ b/include/qpid/dispatch/server.h
@@ -350,6 +350,13 @@ typedef struct qd_server_config_t {
     int idle_timeout_seconds;
 
     /**
+     * The timeout, in seconds, for the initial connection handshake.  If a connection is established
+     * inbound (via a listener) and the timeout expires before the OPEN frame arrives, the connection
+     * shall be closed.
+     */
+    int initial_handshake_timeout_seconds;
+
+    /**
      *  Holds comma separated list that indicates which components of the message should be logged.
      *  Defaults to 'none' (log nothing). If you want all properties and application properties of the message logged use 'all'.
      *  Specific components of the message can be logged by indicating the components via a comma separated list.

http://git-wip-us.apache.org/repos/asf/qpid-dispatch/blob/272398dd/python/qpid_dispatch/management/qdrouter.json
----------------------------------------------------------------------
diff --git a/python/qpid_dispatch/management/qdrouter.json b/python/qpid_dispatch/management/qdrouter.json
index fd78c96..aeebe9a 100644
--- a/python/qpid_dispatch/management/qdrouter.json
+++ b/python/qpid_dispatch/management/qdrouter.json
@@ -680,6 +680,14 @@
                     "type": "integer",
                     "default": 16,
                     "description": "The idle timeout, in seconds, for connections through this listener.  If no frames are received on the connection for this time interval, the connection shall be closed.",
+                    "required": false,
+                    "create": true
+                },
+                "initialHandshakeTimeoutSeconds": {
+                    "type": "integer",
+                    "default": 0,
+                    "description": "The timeout, in seconds, for the initial handshake for connections coming in through listeners.  If the time interval expires before the peer sends the AMQP OPEN frame, the connection shall be closed.  A value of zero (the default) disables this timeout.",
+                    "required": false,
                     "create": true
                 },
                 "stripAnnotations": {

http://git-wip-us.apache.org/repos/asf/qpid-dispatch/blob/272398dd/src/connection_manager.c
----------------------------------------------------------------------
diff --git a/src/connection_manager.c b/src/connection_manager.c
index 84cd504..f9e0e76 100644
--- a/src/connection_manager.c
+++ b/src/connection_manager.c
@@ -283,7 +283,7 @@ static qd_log_bits populate_log_message(const qd_server_config_t *config)
 }
 
 
-static qd_error_t load_server_config(qd_dispatch_t *qd, qd_server_config_t *config, qd_entity_t* entity)
+static qd_error_t load_server_config(qd_dispatch_t *qd, qd_server_config_t *config, qd_entity_t* entity, bool is_listener)
 {
     qd_error_clear();
 
@@ -307,6 +307,8 @@ static qd_error_t load_server_config(qd_dispatch_t *qd, qd_server_config_t *conf
     config->max_sessions         = qd_entity_get_long(entity, "maxSessions");         CHECK();
     uint64_t ssn_frames          = qd_entity_opt_long(entity, "maxSessionFrames", 0); CHECK();
     config->idle_timeout_seconds = qd_entity_get_long(entity, "idleTimeoutSeconds");  CHECK();
+    if (is_listener)
+        config->initial_handshake_timeout_seconds = qd_entity_get_long(entity, "initialHandshakeTimeoutSeconds");  CHECK();
     config->sasl_username        = qd_entity_opt_string(entity, "saslUsername", 0);   CHECK();
     config->sasl_password        = qd_entity_opt_string(entity, "saslPassword", 0);   CHECK();
     config->sasl_mechanisms      = qd_entity_opt_string(entity, "saslMechanisms", 0); CHECK();
@@ -577,7 +579,7 @@ qd_listener_t *qd_dispatch_configure_listener(qd_dispatch_t *qd, qd_entity_t *en
 {
     qd_connection_manager_t *cm = qd->connection_manager;
     qd_listener_t *li = qd_server_listener(qd->server);
-    if (!li || load_server_config(qd, &li->config, entity) != QD_ERROR_NONE) {
+    if (!li || load_server_config(qd, &li->config, entity, true) != QD_ERROR_NONE) {
         qd_log(cm->log_source, QD_LOG_ERROR, "Unable to create listener: %s", qd_error_message());
         qd_listener_decref(li);
         return 0;
@@ -686,7 +688,7 @@ qd_connector_t *qd_dispatch_configure_connector(qd_dispatch_t *qd, qd_entity_t *
 {
     qd_connection_manager_t *cm = qd->connection_manager;
     qd_connector_t *ct = qd_server_connector(qd->server);
-    if (ct && load_server_config(qd, &ct->config, entity) == QD_ERROR_NONE) {
+    if (ct && load_server_config(qd, &ct->config, entity, false) == QD_ERROR_NONE) {
         DEQ_ITEM_INIT(ct);
         DEQ_INSERT_TAIL(cm->connectors, ct);
         log_config(cm->log_source, &ct->config, "Connector");

http://git-wip-us.apache.org/repos/asf/qpid-dispatch/blob/272398dd/src/server.c
----------------------------------------------------------------------
diff --git a/src/server.c b/src/server.c
index 2c2dd36..4b96ffb 100644
--- a/src/server.c
+++ b/src/server.c
@@ -686,7 +686,7 @@ static void handle_listener(pn_event_t *e, qd_server_t *qd_server) {
         break;
 
     case PN_LISTENER_ACCEPT:
-        qd_log(log, QD_LOG_INFO, "Accepting connection on %s", host_port);
+        qd_log(log, QD_LOG_TRACE, "Accepting connection on %s", host_port);
         on_accept(e);
         break;
 
@@ -780,6 +780,31 @@ void qd_connection_free(qd_connection_t *ctx)
 }
 
 
+static void timeout_on_handhsake(void *context, bool discard)
+{
+    if (discard)
+        return;
+
+    qd_connection_t *ctx   = (qd_connection_t*) context;
+    pn_transport_t  *tport = pn_connection_transport(ctx->pn_conn);
+    pn_transport_close_head(tport);
+    connect_fail(ctx, QD_AMQP_COND_NOT_ALLOWED, "Timeout waiting for initial handshake");
+}
+
+
+static void startup_timer_handler(void *context)
+{
+    //
+    // This timer fires for a connection if it has not had a REMOTE_OPEN
+    // event in a time interval from the CONNECTION_INIT event.  Close
+    // down the transport in an IO thread reserved for that connection.
+    //
+    qd_connection_t *ctx = (qd_connection_t*) context;
+    qd_timer_free(ctx->timer);
+    qd_connection_invoke_deferred(ctx, timeout_on_handhsake, context);
+}
+
+
 /* Events involving a connection or listener are serialized by the proactor so
  * only one event per connection / listener will be processed at a time.
  */
@@ -809,12 +834,23 @@ static bool handle(qd_server_t *qd_server, pn_event_t *e) {
         handle_listener(e, qd_server);
         break;
 
+    case PN_CONNECTION_INIT: {
+        const qd_server_config_t *config = ctx && ctx->listener ? &ctx->listener->config : 0;
+        if (config && config->initial_handshake_timeout_seconds > 0) {
+            ctx->timer = qd_timer(qd_server->qd, startup_timer_handler, ctx);
+            qd_timer_schedule(ctx->timer, config->initial_handshake_timeout_seconds * 1000);
+        }
+        break;
+    }
+        
     case PN_CONNECTION_BOUND:
         on_connection_bound(qd_server, e);
         break;
 
     case PN_CONNECTION_REMOTE_OPEN:
         // If we are transitioning to the open state, notify the client via callback.
+        if (ctx->timer)
+            qd_timer_free(ctx->timer);
         if (!ctx->opened) {
             ctx->opened = true;
             if (ctx->connector) {

http://git-wip-us.apache.org/repos/asf/qpid-dispatch/blob/272398dd/src/server_private.h
----------------------------------------------------------------------
diff --git a/src/server_private.h b/src/server_private.h
index 2e66587..ff675e0 100644
--- a/src/server_private.h
+++ b/src/server_private.h
@@ -139,6 +139,7 @@ struct qd_connection_t {
     bool                      opened; // An open callback was invoked for this connection
     bool                      closed;
     int                       enqueued;
+    qd_timer_t               *timer;   // Timer for initial-setup
     pn_connection_t          *pn_conn;
     pn_ssl_t                 *ssl;
     qd_listener_t            *listener;


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org
For additional commands, e-mail: commits-help@qpid.apache.org