]> granicus.if.org Git - apache/commitdiff
Added cping/cpong support for the AJP protocol.
authorMladen Turk <mturk@apache.org>
Tue, 25 Jul 2006 16:50:07 +0000 (16:50 +0000)
committerMladen Turk <mturk@apache.org>
Tue, 25 Jul 2006 16:50:07 +0000 (16:50 +0000)
git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@425454 13f79535-47bb-0310-9956-ffa450edef68

CHANGES
modules/proxy/NWGNUproxyajp
modules/proxy/ajp_utils.c [new file with mode: 0644]
modules/proxy/mod_proxy.c
modules/proxy/mod_proxy.h
modules/proxy/mod_proxy_ajp.c
modules/proxy/mod_proxy_ajp.dsp

diff --git a/CHANGES b/CHANGES
index fd4e833bd5b24ac8f4cedbdba678c9daf491d19b..837345450d1740b2d18464350e87477cac603fc2 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -2,6 +2,12 @@
 Changes with Apache 2.3.0
   [Remove entries to the current 2.0 and 2.2 section below, when backported]
 
+  *) mod_proxy_ajp: Added cping/cpong support for the AJP protocol.
+     A new worker directive ping=timeout will cause CPING packet
+     to be send expecting CPONG packet within defined timeout.
+     In case the backend is too busy this will fail instead
+     sending the full header.  [Mladen Turk]
+
   *) mod_dbd: Fix dependence on virtualhost configuration in
      defining prepared statements (possible segfault at startup
      in user modules such as mod_authn_dbd).  [Nick Kew]
index 3d65d706c43a36bf1fd35f0ab7a88f68ab37d81d..6750891413dff5a176a15e6bb6232b91e6269f8e 100644 (file)
@@ -171,6 +171,7 @@ FILES_nlm_objs = \
        $(OBJDIR)/ajp_header.o \
        $(OBJDIR)/ajp_msg.o \
        $(OBJDIR)/ajp_link.o \
+       $(OBJDIR)/ajp_utils.o \
        $(OBJDIR)/libprews.o \
        $(EOLIST)
 
diff --git a/modules/proxy/ajp_utils.c b/modules/proxy/ajp_utils.c
new file mode 100644 (file)
index 0000000..3532eb8
--- /dev/null
@@ -0,0 +1,104 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more\r
+ * contributor license agreements.  See the NOTICE file distributed with\r
+ * this work for additional information regarding copyright ownership.\r
+ * The ASF licenses this file to You under the Apache License, Version 2.0\r
+ * (the "License"); you may not use this file except in compliance with\r
+ * the License.  You may obtain a copy of the License at\r
+ *\r
+ *     http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+\r
+#include "ajp.h"\r
+\r
+/*\r
+ * Handle the CPING/CPONG\r
+ */\r
+apr_status_t ajp_handle_cping_cpong(apr_socket_t *sock,\r
+                                    request_rec *r,\r
+                                    apr_interval_time_t timeout)\r
+{\r
+    ajp_msg_t *msg;\r
+    apr_status_t rc;\r
+    apr_interval_time_t org;\r
+    apr_byte_t result;\r
+\r
+    ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,\r
+                         "Into ajp_handle_cping_cpong");\r
+\r
+    rc = ajp_msg_create(r->pool, &msg);\r
+    if (rc != APR_SUCCESS) {\r
+        ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server,\r
+               "ajp_handle_cping_cpong: ajp_msg_create failed");\r
+        return rc;\r
+    }\r
+\r
+    rc = ajp_msg_serialize_cping(msg);\r
+    if (rc != APR_SUCCESS) {\r
+        ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server,\r
+               "ajp_handle_cping_cpong: ajp_marshal_into_msgb failed");\r
+        return rc;\r
+    }\r
+\r
+    rc = ajp_ilink_send(sock, msg);\r
+    if (rc != APR_SUCCESS) {\r
+        ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server,\r
+               "ajp_handle_cping_cpong: ajp_ilink_send failed");\r
+        return rc;\r
+    }\r
+\r
+    rc = apr_socket_timeout_get(sock, &org);\r
+    if (rc != APR_SUCCESS) {\r
+        ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server,\r
+               "ajp_handle_cping_cpong: apr_socket_timeout_get failed");\r
+        return rc;\r
+    }\r
+\r
+    /* Set CPING/CPONG response timeout */\r
+    rc = apr_socket_timeout_set(sock, timeout);\r
+    if (rc != APR_SUCCESS) {\r
+        ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server,\r
+               "ajp_handle_cping_cpong: apr_socket_timeout_set failed");\r
+        return rc;\r
+    }\r
+    ajp_msg_reuse(msg);\r
+\r
+    /* Read CPONG reply */\r
+    rc = ajp_ilink_receive(sock, msg);\r
+    if (rc != APR_SUCCESS) {\r
+        ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server,\r
+               "ajp_handle_cping_cpong: ajp_ilink_receive failed");\r
+        return rc;\r
+    }\r
+\r
+    rc = ajp_msg_get_uint8(msg, &result);\r
+    if (rc != APR_SUCCESS) {\r
+        ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server,\r
+               "ajp_handle_cping_cpong: invalid CPONG message");\r
+        return rc;\r
+    }\r
+    if (result != CMD_AJP13_CPONG) {\r
+        ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server,\r
+               "ajp_handle_cping_cpong: awaited CPONG, received %d ",\r
+               result);\r
+        return APR_EGENERAL;\r
+\r
+    }\r
+\r
+    /* Restore original socket timeout */\r
+    rc = apr_socket_timeout_set(sock, org);\r
+    if (rc != APR_SUCCESS) {\r
+        ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server,\r
+               "ajp_handle_cping_cpong: apr_socket_timeout_set failed");\r
+        return rc;\r
+    }\r
+\r
+    ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,\r
+                         "ajp_handle_cping_cpong: Done");\r
+    return APR_SUCCESS;\r
+}\r
index 26aae7fb9ab7e80cbbe19d8891f74a54def79f09..2b1a9ba3d04cadf1396315ad334c2f14e21e2e69 100644 (file)
@@ -244,6 +244,15 @@ static const char *set_worker_param(apr_pool_t *p,
         else
             worker->flush_wait = ival * 1000;    /* change to microseconds */
     }
+    else if (!strcasecmp(key, "ping")) {
+        /* Ping/Pong timeout in seconds.
+         */
+        ival = atoi(val);
+        if (ival < 1)
+            return "Ping/Pong timeout must be at least one second";
+        worker->ping_timeout = apr_time_from_sec(ival);
+        worker->ping_timeout_set = 1;
+    }
     else {
         return "unknown Worker parameter";
     }
@@ -423,7 +432,7 @@ static const char *proxy_interpolate(request_rec *r, const char *str)
     const char *var;
     const char *val;
     const char *firstpart;
-    
+
     start = ap_strstr_c(str, "${");
     if (start == NULL) {
         return str;
index bc35f87e7988205ebd666c6e7d4c6d55d677a502..66e27dcbf6e2c3a6f77abc3c74ea59b5fd036061 100644 (file)
@@ -332,6 +332,8 @@ struct proxy_worker {
          flush_auto
     } flush_packets;           /* control AJP flushing */
     int                 flush_wait;  /* poll wait time in microseconds if flush_auto */
+    apr_interval_time_t ping_timeout;
+    char ping_timeout_set;
 };
 
 /*
index 1a0d6e155e27847bd6691c67153869d4d95feea5..bbca7fe9ba6d8fba4496db719adbbff1bcdf598a 100644 (file)
@@ -530,6 +530,20 @@ static int proxy_ajp_handler(request_rec *r, proxy_worker *worker,
         goto cleanup;
     }
 
+    /* Handle CPING/CPONG */
+    if (worker->ping_timeout_set) {
+        status = ajp_handle_cping_cpong(backend->sock, r,
+                                        worker->ping_timeout);
+        if (status != APR_SUCCESS) {
+            backend->close++;
+            ap_log_error(APLOG_MARK, APLOG_ERR, status, r->server,
+                         "proxy: AJP: cping/cpong failed to %pI (%s)",
+                         worker->cp->addr,
+                         worker->hostname);
+            status = HTTP_SERVICE_UNAVAILABLE;
+            goto cleanup;
+        }
+    }
     /* Step Three: Process the Request */
     status = ap_proxy_ajp_request(p, r, backend, origin, dconf, uri, url,
                                   server_portstr);
index 989a702028a2786d6b90dc5dda14aef2afdc3663..0a0873b92faac173f19b1dbb7edfd2059cf735e0 100644 (file)
@@ -126,6 +126,10 @@ SOURCE=.\ajp_link.c
 
 SOURCE=.\ajp_msg.c
 # End Source File
+# Begin Source File
+
+SOURCE=.\ajp_utils.c
+# End Source File
 # End Group
 # Begin Source File