You are viewing a plain text version of this content. The canonical link for it is here.
Posted to cvs@httpd.apache.org by ji...@apache.org on 2014/05/01 13:39:32 UTC

svn commit: r1591620 [11/14] - in /httpd/mod_spdy/branches/httpd-2.2.x: ./ base/ base/metrics/ build/ install/ install/common/ install/debian/ install/rpm/ mod_spdy/ mod_spdy/apache/ mod_spdy/apache/filters/ mod_spdy/apache/testing/ mod_spdy/common/ mo...

Added: httpd/mod_spdy/branches/httpd-2.2.x/mod_spdy/mod_spdy.cc
URL: http://svn.apache.org/viewvc/httpd/mod_spdy/branches/httpd-2.2.x/mod_spdy/mod_spdy.cc?rev=1591620&view=auto
==============================================================================
--- httpd/mod_spdy/branches/httpd-2.2.x/mod_spdy/mod_spdy.cc (added)
+++ httpd/mod_spdy/branches/httpd-2.2.x/mod_spdy/mod_spdy.cc Thu May  1 11:39:27 2014
@@ -0,0 +1,915 @@
+// Copyright 2010 Google Inc.
+//
+// Licensed 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.
+
+// References to "TAMB" below refer to _The Apache Modules Book_ by Nick Kew
+// (ISBN: 0-13-240967-4).
+
+#include "mod_spdy/mod_spdy.h"
+
+#include <algorithm>  // for std::min
+
+#include "httpd.h"
+#include "http_connection.h"
+#include "http_config.h"
+#include "http_log.h"
+#include "http_protocol.h"
+#include "http_request.h"
+#include "apr_optional.h"
+#include "apr_optional_hooks.h"
+#include "apr_tables.h"
+
+#include "base/basictypes.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/strings/string_piece.h"
+#include "mod_spdy/apache/apache_spdy_session_io.h"
+#include "mod_spdy/apache/apache_spdy_stream_task_factory.h"
+#include "mod_spdy/apache/config_commands.h"
+#include "mod_spdy/apache/config_util.h"
+#include "mod_spdy/apache/id_pool.h"
+#include "mod_spdy/apache/filters/server_push_discovery_filter.h"
+#include "mod_spdy/apache/filters/server_push_filter.h"
+#include "mod_spdy/apache/log_message_handler.h"
+#include "mod_spdy/apache/master_connection_context.h"
+#include "mod_spdy/apache/pool_util.h"
+#include "mod_spdy/apache/slave_connection_context.h"
+#include "mod_spdy/apache/slave_connection_api.h"
+#include "mod_spdy/apache/ssl_util.h"
+#include "mod_spdy/common/executor.h"
+#include "mod_spdy/common/protocol_util.h"
+#include "mod_spdy/common/server_push_discovery_learner.h"
+#include "mod_spdy/common/server_push_discovery_session.h"
+#include "mod_spdy/common/spdy_server_config.h"
+#include "mod_spdy/common/spdy_session.h"
+#include "mod_spdy/common/spdy_stream.h"
+#include "mod_spdy/common/thread_pool.h"
+#include "mod_spdy/common/version.h"
+
+extern "C" {
+
+// Declaring mod_so's optional hooks here (so that we don't need to
+// #include "mod_so.h").
+APR_DECLARE_OPTIONAL_FN(module*, ap_find_loaded_module_symbol,
+                        (server_rec*, const char*));
+
+// Declaring modified mod_ssl's optional hooks here (so that we don't need to
+// #include "mod_ssl.h").
+APR_DECLARE_EXTERNAL_HOOK(modssl, AP, int, npn_advertise_protos_hook,
+                          (conn_rec *connection, apr_array_header_t *protos));
+APR_DECLARE_EXTERNAL_HOOK(modssl, AP, int, npn_proto_negotiated_hook,
+                          (conn_rec *connection, const char *proto_name,
+                           apr_size_t proto_name_len));
+
+}  // extern "C"
+
+namespace {
+
+const char kFakeModSpdyProtocolName[] =
+    "x-mod-spdy/" MOD_SPDY_VERSION_STRING "-" LASTCHANGE_STRING;
+COMPILE_ASSERT(arraysize(kFakeModSpdyProtocolName) <= 255,
+               fake_protocol_name_is_not_too_long_for_npn);
+const char kFakeModSpdyProtocolNameNoVersion[] = "x-mod-spdy/no-version";
+COMPILE_ASSERT(arraysize(kFakeModSpdyProtocolNameNoVersion) <= 255,
+               fake_protocol_name_no_version_is_not_too_long_for_npn);
+
+const char* const kHttpProtocolName = "http/1.1";
+const char* const kSpdy2ProtocolName = "spdy/2";
+const char* const kSpdy3ProtocolName = "spdy/3";
+const char* const kSpdy31ProtocolName = "spdy/3.1";
+const char* const kSpdyVersionEnvironmentVariable = "SPDY_VERSION";
+
+const char* const kPhpModuleNames[] = {
+  "php_module",
+  "php2_module",
+  "php3_module",
+  "php4_module",
+  "php5_module",
+  "php6_module"
+};
+
+// These globals store the filter handles for our output filters.  Normally,
+// global variables would be very dangerous in a concurrent environment like
+// Apache, but this one is okay because it is assigned just once, at
+// start-up (during which Apache is running single-threaded; see TAMB 2.2.1),
+// and are read-only thereafter.
+ap_filter_rec_t* gServerPushFilterHandle = NULL;
+ap_filter_rec_t* gServerPushDiscoveryFilterHandle = NULL;
+
+// A process-global thread pool for processing SPDY streams concurrently.  This
+// is initialized once in *each child process* by our child-init hook.  Note
+// that in a non-threaded MPM (e.g. Prefork), this thread pool will be used by
+// just one SPDY connection at a time, but in a threaded MPM (e.g. Worker) it
+// will shared by several SPDY connections at once.  That's okay though,
+// because ThreadPool objects are thread-safe.  Users just have to make sure
+// that they configure SpdyMaxThreadsPerProcess depending on the MPM.
+mod_spdy::ThreadPool* gPerProcessThreadPool = NULL;
+
+// Process-global objects used for SPDY server push discovery;
+mod_spdy::ServerPushDiscoveryLearner* gServerPushDiscoveryLearner = NULL;
+mod_spdy::ServerPushDiscoverySessionPool*
+gServerPushDiscoverySessionPool = NULL;
+
+// Optional function provided by mod_spdy.  Return zero if the connection is
+// not using SPDY, otherwise return the SPDY version number in use.  Note that
+// unlike our private functions, we use Apache C naming conventions for this
+// function because we export it to other modules.
+int spdy_get_version(conn_rec* connection) {
+  if (mod_spdy::HasMasterConnectionContext(connection)) {
+    mod_spdy::MasterConnectionContext* master_context =
+        mod_spdy::GetMasterConnectionContext(connection);
+    if (master_context->is_using_spdy()) {
+      return mod_spdy::SpdyVersionToFramerVersion(
+          master_context->spdy_version());
+    }
+  }
+
+  if (mod_spdy::HasSlaveConnectionContext(connection)) {
+    mod_spdy::SlaveConnectionContext* slave_context =
+        mod_spdy::GetSlaveConnectionContext(connection);
+    if (slave_context->spdy_version() != mod_spdy::spdy::SPDY_VERSION_NONE) {
+      return mod_spdy::SpdyVersionToFramerVersion(
+          slave_context->spdy_version());
+    }
+  }
+
+  return 0;
+}
+
+apr_status_t ServerPushFilterFunc(ap_filter_t* filter,
+                                  apr_bucket_brigade* input_brigade) {
+  mod_spdy::ServerPushFilter* server_push_filter =
+      static_cast<mod_spdy::ServerPushFilter*>(filter->ctx);
+  return server_push_filter->Write(filter, input_brigade);
+}
+
+apr_status_t ServerPushDiscoveryFilterFunc(ap_filter_t* filter,
+                                           apr_bucket_brigade* input_brigade) {
+  // Don't auto-generate more pushes for pushed content.
+  if (mod_spdy::HasSlaveConnectionContext(filter->r->connection)) {
+    mod_spdy::SlaveConnectionContext* slave_context =
+        mod_spdy::GetSlaveConnectionContext(filter->r->connection);
+    mod_spdy::SpdyStream* stream = slave_context->slave_stream();
+    if (stream && stream->server_push_depth() > 0) {
+      ap_remove_output_filter(filter);
+      return ap_pass_brigade(filter->next, input_brigade);
+    }
+  }
+
+  ServerPushDiscoveryFilter(
+      filter,
+      input_brigade,
+      gServerPushDiscoveryLearner,
+      gServerPushDiscoverySessionPool,
+      spdy_get_version(filter->r->connection),
+      mod_spdy::GetServerConfig(filter->r->connection)->
+          server_push_discovery_send_debug_headers());
+
+  ap_remove_output_filter(filter);
+  return ap_pass_brigade(filter->next, input_brigade);
+}
+
+// Called on server startup, after all modules have loaded.
+void RetrieveOptionalFunctions() {
+  mod_spdy::RetrieveModSslFunctions();
+}
+
+// Called after configuration has completed.
+int PostConfig(apr_pool_t* pconf, apr_pool_t* plog, apr_pool_t* ptemp,
+               server_rec* server_list) {
+  mod_spdy::ScopedServerLogHandler log_handler(server_list);
+
+  // Check if any of the virtual hosts have mod_spdy enabled.
+  bool any_enabled = false;
+  for (server_rec* server = server_list; server != NULL;
+       server = server->next) {
+    if (mod_spdy::GetServerConfig(server)->spdy_enabled()) {
+      any_enabled = true;
+      break;
+    }
+  }
+
+  // Log a message indicating whether mod_spdy is enabled or not.  It's all too
+  // easy to install mod_spdy and forget to turn it on, so this may be helpful
+  // for debugging server behavior.
+  if (!any_enabled) {
+    LOG(WARNING) << "mod_spdy is installed, but has not been enabled in the "
+                 << "Apache config. SPDY will not be used by this server.  "
+                 << "See http://code.google.com/p/mod-spdy/wiki/ConfigOptions "
+                 << "for how to enable.";
+  }
+
+
+  // Modules which may not be thread-safe shouldn't be used with mod_spdy.
+  // That mainly seems to be mod_php.  If mod_php is installed, log a warning
+  // pointing the user to docs on how to use PHP safely with mod_spdy.
+  if (any_enabled) {
+    module* (*get_module)(server_rec*, const char*) =
+        APR_RETRIEVE_OPTIONAL_FN(ap_find_loaded_module_symbol);
+    if (get_module != NULL) {
+      for (size_t i = 0; i < arraysize(kPhpModuleNames); ++i) {
+        if (get_module(server_list, kPhpModuleNames[i]) != NULL) {
+          LOG(WARNING)
+              << kPhpModuleNames[i] << " may not be thread-safe, and "
+              << "should not be used with mod_spdy.  Instead, see "
+              << "https://developers.google.com/speed/spdy/mod_spdy/php for "
+              << "how to configure your server to use PHP safely.";
+        }
+      }
+    }
+  }
+
+  return OK;
+}
+
+// Called exactly once for each child process, before that process starts
+// spawning worker threads.
+void ChildInit(apr_pool_t* pool, server_rec* server_list) {
+  mod_spdy::ScopedServerLogHandler log_handler(server_list);
+
+  // Check whether mod_spdy is enabled for any server_rec in the list, and
+  // determine the most verbose log level of any server in the list.
+  // Also determines if server push discovery is enabled for any server.
+  bool spdy_enabled = false;
+  bool server_push_discovery_enabled = false;
+  int max_apache_log_level = APLOG_EMERG;  // the least verbose log level
+  COMPILE_ASSERT(APLOG_INFO > APLOG_ERR, bigger_number_means_more_verbose);
+  for (server_rec* server = server_list; server != NULL;
+       server = server->next) {
+    spdy_enabled |= mod_spdy::GetServerConfig(server)->spdy_enabled();
+    server_push_discovery_enabled |=
+        mod_spdy::GetServerConfig(server)->server_push_discovery_enabled();
+    if (server->loglevel > max_apache_log_level) {
+      max_apache_log_level = server->loglevel;
+    }
+  }
+
+  // There are a couple config options we need to check (vlog_level and
+  // max_threads_per_process) that are only settable at the top level of the
+  // config, so it doesn't matter which server in the list we read them from.
+  const mod_spdy::SpdyServerConfig* top_level_config =
+      mod_spdy::GetServerConfig(server_list);
+
+  // We set mod_spdy's global logging level to that of the most verbose server
+  // in the list.  The scoped logging handlers we establish will sometimes
+  // restrict things further, if they are for a less verbose virtual host.
+  mod_spdy::SetLoggingLevel(max_apache_log_level,
+                            top_level_config->vlog_level());
+
+  // If mod_spdy is not enabled on any server_rec, don't do any other setup.
+  if (!spdy_enabled) {
+    return;
+  }
+
+  // Create the per-process thread pool.
+  const int max_threads = top_level_config->max_threads_per_process();
+  const int min_threads =
+      std::min(max_threads, top_level_config->min_threads_per_process());
+  scoped_ptr<mod_spdy::ThreadPool> thread_pool(
+      new mod_spdy::ThreadPool(min_threads, max_threads));
+  if (thread_pool->Start()) {
+    gPerProcessThreadPool = thread_pool.release();
+    mod_spdy::PoolRegisterDelete(pool, gPerProcessThreadPool);
+  } else {
+    LOG(DFATAL) << "Could not create mod_spdy thread pool; "
+                << "mod_spdy will not function.";
+  }
+
+  if (server_push_discovery_enabled) {
+    gServerPushDiscoveryLearner = new mod_spdy::ServerPushDiscoveryLearner;
+    mod_spdy::PoolRegisterDelete(pool, gServerPushDiscoveryLearner);
+    gServerPushDiscoverySessionPool =
+        new mod_spdy::ServerPushDiscoverySessionPool;
+    mod_spdy::PoolRegisterDelete(pool, gServerPushDiscoverySessionPool);
+  }
+}
+
+// A pre-connection hook, to be run _before_ mod_ssl's pre-connection hook.
+// Disables mod_ssl for our slave connections.
+int DisableSslForSlaves(conn_rec* connection, void* csd) {
+  mod_spdy::ScopedConnectionLogHandler log_handler(connection);
+
+  if (!mod_spdy::HasSlaveConnectionContext(connection)) {
+    // For master connections, the context object should't have been created
+    // yet (it gets created in PreConnection).
+    DCHECK(!mod_spdy::HasMasterConnectionContext(connection));
+    return DECLINED;  // only do things for slave connections.
+  }
+
+  // If a slave context has already been created, mod_spdy must be enabled.
+  DCHECK(mod_spdy::GetServerConfig(connection)->spdy_enabled());
+
+  // Disable mod_ssl for the slave connection so it doesn't get in our way.
+  if (!mod_spdy::DisableSslForConnection(connection)) {
+    // Hmm, mod_ssl either isn't installed or isn't enabled.  That should be
+    // impossible (we wouldn't _have_ a slave connection without having SSL for
+    // the master connection), unless we're configured to assume SPDY for
+    // non-SSL connections.  Let's check if that's the case, and LOG(DFATAL) if
+    // it's not.
+    if (mod_spdy::GetServerConfig(connection)->
+        use_spdy_version_without_ssl() == mod_spdy::spdy::SPDY_VERSION_NONE) {
+      LOG(DFATAL) << "mod_ssl missing for slave connection";
+    }
+  }
+  return OK;
+}
+
+// A pre-connection hook, to be run _after_ mod_ssl's pre-connection hook, but
+// just _before_ the core pre-connection hook.  For master connections, this
+// checks if SSL is active; for slave connections, this adds our
+// connection-level filters and prevents core filters from being inserted.
+int PreConnection(conn_rec* connection, void* csd) {
+  mod_spdy::ScopedConnectionLogHandler log_handler(connection);
+
+  // If a slave context has not yet been created, this is a "real" connection.
+  if (!mod_spdy::HasSlaveConnectionContext(connection)) {
+    // Master context should not have been created yet, either.
+    DCHECK(!mod_spdy::HasMasterConnectionContext(connection));
+
+    // If mod_spdy is disabled on this server, don't allocate our context
+    // object.
+    const mod_spdy::SpdyServerConfig* config =
+        mod_spdy::GetServerConfig(connection);
+    if (!config->spdy_enabled()) {
+      return DECLINED;
+    }
+
+    // We'll set this to a nonzero SPDY version number momentarily if we're
+    // configured to assume a particular SPDY version for this connection.
+    mod_spdy::spdy::SpdyVersion assume_spdy_version =
+        mod_spdy::spdy::SPDY_VERSION_NONE;
+
+    // Check if this connection is over SSL; if not, we can't do NPN, so we
+    // definitely won't be using SPDY (unless we're configured to assume SPDY
+    // for non-SSL connections).
+    const bool using_ssl = mod_spdy::IsUsingSslForConnection(connection);
+    if (!using_ssl) {
+      // This is not an SSL connection, so we can't talk SPDY on it _unless_ we
+      // have opted to assume SPDY over non-SSL connections (presumably for
+      // debugging purposes; this would normally break browsers).
+      assume_spdy_version = config->use_spdy_version_without_ssl();
+      if (assume_spdy_version == mod_spdy::spdy::SPDY_VERSION_NONE) {
+        return DECLINED;
+      }
+    }
+
+    // Okay, we've got a real connection over SSL, so we'll be negotiating with
+    // the client to see if we can use SPDY for this connection.  Create our
+    // connection context object to keep track of the negotiation.
+    mod_spdy::MasterConnectionContext* master_context =
+        mod_spdy::CreateMasterConnectionContext(connection, using_ssl);
+    // If we're assuming SPDY for this connection, it means we know NPN won't
+    // happen at all, and we're just going to assume a particular SPDY version.
+    if (assume_spdy_version != mod_spdy::spdy::SPDY_VERSION_NONE) {
+      master_context->set_assume_spdy(true);
+      master_context->set_spdy_version(assume_spdy_version);
+    }
+    return OK;
+  }
+  // If the context has already been created, this is a slave connection.
+  else {
+    mod_spdy::SlaveConnectionContext* slave_context =
+        mod_spdy::GetSlaveConnectionContext(connection);
+
+    DCHECK(mod_spdy::GetServerConfig(connection)->spdy_enabled());
+
+    // Add our input and output filters.
+    ap_add_input_filter_handle(
+        slave_context->input_filter_handle(),  // filter handle
+        slave_context->input_filter_context(), // context (any void* we want)
+        NULL,                     // request object
+        connection);              // connection object
+
+    ap_add_output_filter_handle(
+        slave_context->output_filter_handle(),    // filter handle
+        slave_context->output_filter_context(),   // context (any void* we want)
+        NULL,                       // request object
+        connection);                // connection object
+
+    // Prevent core pre-connection hooks from running (thus preventing core
+    // filters from being inserted).
+    return DONE;
+  }
+}
+
+// Called to see if we want to take care of processing this connection -- if
+// so, we do so and return OK, otherwise we return DECLINED.  For slave
+// connections, we want to return DECLINED.  For "real" connections, we need to
+// determine if they are using SPDY; if not we returned DECLINED, but if so we
+// process this as a master SPDY connection and then return OK.
+int ProcessConnection(conn_rec* connection) {
+  mod_spdy::ScopedConnectionLogHandler log_handler(connection);
+
+  // If mod_spdy is disabled on this server, don't use SPDY.
+  const mod_spdy::SpdyServerConfig* config =
+      mod_spdy::GetServerConfig(connection);
+  if (!config->spdy_enabled()) {
+    return DECLINED;
+  }
+
+  // We do not want to attach to non-inbound connections (e.g. connections
+  // created by mod_proxy).  Non-inbound connections do not get a scoreboard
+  // hook, so we abort if the connection doesn't have the scoreboard hook.  See
+  // http://mail-archives.apache.org/mod_mbox/httpd-dev/201008.mbox/%3C99EA83DCDE961346AFA9B5EC33FEC08B047FDC26@VF-MBX11.internal.vodafone.com%3E
+  // for more details.
+  if (connection->sbh == NULL) {
+    return DECLINED;
+  }
+
+  // Our connection context object will have been created by now, unless our
+  // pre-connection hook saw that this was a non-SSL connection, in which case
+  // we won't be using SPDY so we can stop now. It may also mean that this is
+  // a slave connection, in which case we don't want to deal with it here --
+  // instead we will let Apache treat it like a regular HTTP connection.
+  if (!mod_spdy::HasMasterConnectionContext(connection)) {
+    return DECLINED;
+  }
+
+  mod_spdy::MasterConnectionContext* master_context =
+      mod_spdy::GetMasterConnectionContext(connection);
+
+  // In the unlikely event that we failed to create our per-process thread
+  // pool, we're not going to be able to operate.
+  if (gPerProcessThreadPool == NULL) {
+    return DECLINED;
+  }
+
+  // Unless we're simply assuming SPDY for this connection, we need to do NPN
+  // to decide whether to use SPDY or not.
+  if (!master_context->is_assuming_spdy()) {
+    // We need to pull some data through mod_ssl in order to force the SSL
+    // handshake, and hence NPN, to take place.  To that end, perform a small
+    // SPECULATIVE read (and then throw away whatever data we got).
+    apr_bucket_brigade* temp_brigade =
+        apr_brigade_create(connection->pool, connection->bucket_alloc);
+    const apr_status_t status =
+        ap_get_brigade(connection->input_filters, temp_brigade,
+                       AP_MODE_SPECULATIVE, APR_BLOCK_READ, 1);
+    apr_brigade_destroy(temp_brigade);
+
+    // If we were unable to pull any data through, give up and return DECLINED.
+    if (status != APR_SUCCESS) {
+      // Depending on exactly what went wrong, we may want to log something
+      // before returning DECLINED.
+      if (APR_STATUS_IS_EOF(status)) {
+        // EOF errors are to be expected sometimes (e.g. if the connection was
+        // closed), and we should just quietly give up.  No need to log in this
+        // case.
+      } else if (APR_STATUS_IS_TIMEUP(status)) {
+        // TIMEUP errors also seem to happen occasionally.  I think we should
+        // also give up in this case, but I'm not sure yet; for now let's VLOG
+        // when it happens, to help with debugging [mdsteele].
+        VLOG(1) << "Couldn't read from SSL connection (TIMEUP).";
+      } else {
+        // Any other error could be a real issue, so let's log it (slightly)
+        // more noisily.
+        LOG(INFO) << "Couldn't read from SSL connection; failed with status "
+                  << status << ": " << mod_spdy::AprStatusString(status);
+      }
+      return DECLINED;
+    }
+
+    // If we did pull some data through, then NPN should have happened and our
+    // OnNextProtocolNegotiated() hook should have been called by now.  If NPN
+    // hasn't happened, it's probably because we're using an old version of
+    // mod_ssl that doesn't support NPN, in which case we should probably warn
+    // the user that mod_spdy isn't going to work.
+    if (master_context->npn_state() ==
+        mod_spdy::MasterConnectionContext::NOT_DONE_YET) {
+      LOG(WARNING)
+          << "NPN didn't happen during SSL handshake.  You're probably using "
+          << "a version of mod_ssl that doesn't support NPN. Without NPN "
+          << "support, the server cannot use SPDY. See "
+          << "http://code.google.com/p/mod-spdy/wiki/GettingStarted for more "
+          << "information on installing a version of mod_spdy with NPN "
+          << "support.";
+    }
+  }
+
+  // If NPN didn't choose SPDY, then don't use SPDY.
+  if (!master_context->is_using_spdy()) {
+    return DECLINED;
+  }
+
+  const mod_spdy::spdy::SpdyVersion spdy_version =
+      master_context->spdy_version();
+  LOG(INFO) << "Starting SPDY/" <<
+      mod_spdy::SpdyVersionNumberString(spdy_version) << " session";
+
+  // At this point, we and the client have agreed to use SPDY (either that, or
+  // we've been configured to use SPDY regardless of what the client says), so
+  // process this as a SPDY master connection.
+  mod_spdy::ApacheSpdySessionIO session_io(connection);
+  mod_spdy::ApacheSpdyStreamTaskFactory task_factory(connection);
+  scoped_ptr<mod_spdy::Executor> executor(
+      gPerProcessThreadPool->NewExecutor());
+  mod_spdy::SpdySession spdy_session(
+      spdy_version, config, &session_io, &task_factory, executor.get());
+  // This call will block until the session has closed down.
+  spdy_session.Run();
+
+  LOG(INFO) << "Terminating SPDY/" <<
+      mod_spdy::SpdyVersionNumberString(spdy_version) << " session";
+
+  // Return OK to tell Apache that we handled this connection.
+  return OK;
+}
+
+// Called by mod_ssl when it needs to decide what protocols to advertise to the
+// client during Next Protocol Negotiation (NPN).
+int AdvertiseSpdy(conn_rec* connection, apr_array_header_t* protos) {
+  // If mod_spdy is disabled on this server, then we shouldn't advertise SPDY
+  // to the client.
+  if (!mod_spdy::GetServerConfig(connection)->spdy_enabled()) {
+    return DECLINED;
+  }
+
+  // Advertise SPDY to the client.  We push protocol names in descending order
+  // of preference; the one we'd most prefer comes first.
+  APR_ARRAY_PUSH(protos, const char*) = kSpdy31ProtocolName;
+  APR_ARRAY_PUSH(protos, const char*) = kSpdy3ProtocolName;
+  APR_ARRAY_PUSH(protos, const char*) = kSpdy2ProtocolName;
+  return OK;
+}
+
+// Called by mod_ssl (along with the AdvertiseSpdy function) when it needs to
+// decide what protocols to advertise to the client during Next Protocol
+// Negotiation (NPN).  These two functions are separate so that AdvertiseSpdy
+// can run early in the hook order, and AdvertiseHttp can run late.
+int AdvertiseHttp(conn_rec* connection, apr_array_header_t* protos) {
+  const mod_spdy::SpdyServerConfig* config =
+      mod_spdy::GetServerConfig(connection);
+  // If mod_spdy is disabled on this server, don't do anything.
+  if (!config->spdy_enabled()) {
+    return DECLINED;
+  }
+
+  // Apache definitely supports HTTP/1.1, and so it ought to advertise it
+  // during NPN.  However, the Apache core HTTP module doesn't yet know about
+  // this hook, so we advertise HTTP/1.1 for them.  But to be future-proof, we
+  // don't add "http/1.1" to the list if it's already there.
+  bool http_not_advertised = true;
+  for (int i = 0; i < protos->nelts; ++i) {
+    if (!strcmp(APR_ARRAY_IDX(protos, i, const char*), kHttpProtocolName)) {
+      http_not_advertised = false;
+      break;
+    }
+  }
+  if (http_not_advertised) {
+    // No one's advertised HTTP/1.1 yet, so let's do it now.
+    APR_ARRAY_PUSH(protos, const char*) = kHttpProtocolName;
+  }
+
+  // Advertise a fake protocol, indicating the mod_spdy version in use.  We
+  // push this last, so the client doesn't think we prefer it to HTTP.
+  if (config->send_version_header()) {
+    APR_ARRAY_PUSH(protos, const char*) = kFakeModSpdyProtocolName;
+  } else {
+    // If the user prefers not to send a version number, leave out the version
+    // number.
+    APR_ARRAY_PUSH(protos, const char*) = kFakeModSpdyProtocolNameNoVersion;
+  }
+
+  return OK;
+}
+
+// Called by mod_ssl after Next Protocol Negotiation (NPN) has completed,
+// informing us which protocol was chosen by the client.
+int OnNextProtocolNegotiated(conn_rec* connection, const char* proto_name,
+                             apr_size_t proto_name_len) {
+  mod_spdy::ScopedConnectionLogHandler log_handler(connection);
+
+  // If mod_spdy is disabled on this server, then ignore the results of NPN.
+  if (!mod_spdy::GetServerConfig(connection)->spdy_enabled()) {
+    return DECLINED;
+  }
+
+  // We disable mod_ssl for slave connections, so NPN shouldn't be happening
+  // unless this is a non-slave connection.
+  if (mod_spdy::HasSlaveConnectionContext(connection)) {
+    LOG(DFATAL) << "mod_ssl was aparently not disabled for slave connection";
+    return DECLINED;
+  }
+
+  // Given that mod_spdy is enabled, our context object should have already
+  // been created in our pre-connection hook, unless this is a non-SSL
+  // connection.  But if it's a non-SSL connection, then NPN shouldn't be
+  // happening, and this hook shouldn't be getting called!  So, let's
+  // LOG(DFATAL) if context is NULL here.
+  if (!mod_spdy::HasMasterConnectionContext(connection)) {
+    LOG(DFATAL) << "NPN happened, but there is no connection context.";
+    return DECLINED;
+  }
+
+  mod_spdy::MasterConnectionContext* master_context =
+      mod_spdy::GetMasterConnectionContext(connection);
+
+  // NPN should happen only once, so npn_state should still be NOT_DONE_YET.
+  if (master_context->npn_state() !=
+      mod_spdy::MasterConnectionContext::NOT_DONE_YET) {
+    LOG(DFATAL) << "NPN happened twice.";
+    return DECLINED;
+  }
+
+  // If the client chose the SPDY version that we advertised, then mark this
+  // connection as using SPDY.
+  const base::StringPiece protocol_name(proto_name, proto_name_len);
+  if (protocol_name == kSpdy2ProtocolName) {
+    master_context->set_npn_state(
+        mod_spdy::MasterConnectionContext::USING_SPDY);
+    master_context->set_spdy_version(mod_spdy::spdy::SPDY_VERSION_2);
+  } else if (protocol_name == kSpdy3ProtocolName) {
+    master_context->set_npn_state(
+        mod_spdy::MasterConnectionContext::USING_SPDY);
+    master_context->set_spdy_version(mod_spdy::spdy::SPDY_VERSION_3);
+  } else if (protocol_name == kSpdy31ProtocolName) {
+    master_context->set_npn_state(
+        mod_spdy::MasterConnectionContext::USING_SPDY);
+    master_context->set_spdy_version(mod_spdy::spdy::SPDY_VERSION_3_1);
+  }
+  // Otherwise, explicitly mark this connection as not using SPDY.
+  else {
+    master_context->set_npn_state(
+        mod_spdy::MasterConnectionContext::NOT_USING_SPDY);
+  }
+  return OK;
+}
+
+int SetUpSubprocessEnv(request_rec* request) {
+  conn_rec* connection = request->connection;
+  mod_spdy::ScopedConnectionLogHandler log_handler(connection);
+
+  // If mod_spdy is disabled on this server, then don't do anything.
+  if (!mod_spdy::GetServerConfig(connection)->spdy_enabled()) {
+    return DECLINED;
+  }
+
+  // Don't do anything unless this is a slave connection.
+  if (!mod_spdy::HasSlaveConnectionContext(connection)) {
+    return DECLINED;
+  }
+
+  mod_spdy::SlaveConnectionContext* slave_context =
+      mod_spdy::GetSlaveConnectionContext(connection);
+
+  // If this request is over SPDY (which it might not be, if this slave
+  // connection is being used by another module through the slave connection
+  // API), then for the benefit of CGI scripts, which have no way of calling
+  // spdy_get_version(), set an environment variable indicating what SPDY
+  // version is being used, allowing them to optimize the response for SPDY.
+  // See http://code.google.com/p/mod-spdy/issues/detail?id=27 for details.
+  const mod_spdy::spdy::SpdyVersion spdy_version =
+      slave_context->spdy_version();
+  if (spdy_version != mod_spdy::spdy::SPDY_VERSION_NONE) {
+    apr_table_set(request->subprocess_env, kSpdyVersionEnvironmentVariable,
+                  mod_spdy::SpdyVersionNumberString(spdy_version));
+  }
+
+  // Normally, mod_ssl sets the HTTPS environment variable to "on" for requests
+  // served over SSL.  We turn mod_ssl off for our slave connections, but those
+  // requests _are_ (usually) being served over SSL (via the master
+  // connection), so we set the variable ourselves if we are in fact using SSL.
+  // See http://code.google.com/p/mod-spdy/issues/detail?id=32 for details.
+  if (slave_context->is_using_ssl()) {
+    apr_table_setn(request->subprocess_env, "HTTPS", "on");
+  }
+
+  return OK;
+}
+
+void InsertRequestFilters(request_rec* request) {
+  conn_rec* const connection = request->connection;
+  mod_spdy::ScopedConnectionLogHandler log_handler(connection);
+
+  // If mod_spdy is disabled on this server, then don't do anything.
+  if (!mod_spdy::GetServerConfig(connection)->spdy_enabled()) {
+    return;
+  }
+
+  if (mod_spdy::GetServerConfig(connection)->server_push_discovery_enabled()) {
+    ap_add_output_filter_handle(
+        gServerPushDiscoveryFilterHandle,  // filter handle
+        NULL,                              // context (any void* we want)
+        request,                           // request object
+        connection);                       // connection object
+  }
+
+  // Don't do anything unless this is a slave connection.
+  if (!mod_spdy::HasSlaveConnectionContext(connection)) {
+    return;
+  }
+
+  mod_spdy::SlaveConnectionContext* slave_context =
+      mod_spdy::GetSlaveConnectionContext(connection);
+
+  // Insert a filter that will initiate server pushes when so instructed (such
+  // as by an X-Associated-Content header). This is conditional on this
+  // connection being managed entirely on mod_spdy, and not being done on
+  // behalf of someone else using the slave connection API.
+  if (slave_context->slave_stream() != NULL) {
+    mod_spdy::ServerPushFilter* server_push_filter =
+        new mod_spdy::ServerPushFilter(slave_context->slave_stream(), request,
+                                       mod_spdy::GetServerConfig(request));
+    PoolRegisterDelete(request->pool, server_push_filter);
+    ap_add_output_filter_handle(
+        gServerPushFilterHandle,  // filter handle
+        server_push_filter,       // context (any void* we want)
+        request,                  // request object
+        connection);              // connection object
+  }
+}
+
+apr_status_t InvokeIdPoolDestroyInstance(void*) {
+  mod_spdy::IdPool::DestroyInstance();
+  return APR_SUCCESS;
+}
+
+// Called when the module is loaded to register all of our hook functions.
+void RegisterHooks(apr_pool_t* pool) {
+  mod_spdy::InstallLogMessageHandler(pool);
+  mod_spdy::IdPool::CreateInstance();
+  apr_pool_cleanup_register(pool, NULL, InvokeIdPoolDestroyInstance,
+                            apr_pool_cleanup_null /* no cleanup on fork*/);
+
+  static const char* const modules_core[] = {"core.c", NULL};
+  static const char* const modules_mod_ssl[] = {"mod_ssl.c", NULL};
+
+  // Register a hook to be called after all modules have been loaded, so we can
+  // retrieve optional functions from mod_ssl.
+  ap_hook_optional_fn_retrieve(
+      RetrieveOptionalFunctions,  // hook function to be called
+      NULL,                       // predecessors
+      NULL,                       // successors
+      APR_HOOK_MIDDLE);           // position
+
+  // Register a hook to be called after configuration has completed.  We use
+  // this hook to log whether or not mod_spdy is enabled on this server.
+  ap_hook_post_config(PostConfig, NULL, NULL, APR_HOOK_MIDDLE);
+
+  // Register a hook to be called once for each child process spawned by
+  // Apache, before the MPM starts spawning worker threads.  We use this hook
+  // to initialize our per-process thread pool.
+  ap_hook_child_init(ChildInit, NULL, NULL, APR_HOOK_MIDDLE);
+
+  // Register a pre-connection hook to turn off mod_ssl for our slave
+  // connections.  This must run before mod_ssl's pre-connection hook, so that
+  // we can disable mod_ssl before it inserts its filters, so we name mod_ssl
+  // as an explicit successor.
+  ap_hook_pre_connection(
+      DisableSslForSlaves,        // hook function to be called
+      NULL,                       // predecessors
+      modules_mod_ssl,            // successors
+      APR_HOOK_FIRST);            // position
+
+  // Register our pre-connection hook, which will be called shortly before our
+  // process-connection hook.  The hooking order is very important here.  In
+  // particular:
+  //   * We must run before the core pre-connection hook, so that we can return
+  //     DONE and stop the core filters from being inserted.  Thus, we name
+  //     core.c as a successor.
+  //   * We should run after almost all other modules (except core.c) so that
+  //     our returning DONE doesn't prevent other modules from working.  Thus,
+  //     we use APR_HOOK_LAST for our position argument.
+  //   * In particular, we MUST run after mod_ssl's pre-connection hook, so
+  //     that we can ask mod_ssl if this connection is using SSL.  Thus, we
+  //     name mod_ssl.c as a predecessor.  This is redundant, since mod_ssl's
+  //     pre-connection hook uses APR_HOOK_MIDDLE, but it's good to be sure.
+  // For more about controlling hook order, see TAMB 10.2.2 or
+  // http://httpd.apache.org/docs/trunk/developer/hooks.html#hooking-order
+  ap_hook_pre_connection(
+      PreConnection,              // hook function to be called
+      modules_mod_ssl,            // predecessors
+      modules_core,               // successors
+      APR_HOOK_LAST);             // position
+
+  // Register our process-connection hook, which will handle SPDY connections.
+  // The first process-connection hook in the chain to return OK gets to be in
+  // charge of handling the connection from start to finish, so we put
+  // ourselves in APR_HOOK_FIRST so we can get an early look at the connection.
+  // If it turns out not to be a SPDY connection, we'll get out of the way and
+  // let other modules deal with it.
+  ap_hook_process_connection(ProcessConnection, NULL, NULL, APR_HOOK_FIRST);
+
+  // For the benefit of e.g. PHP/CGI scripts, we need to set various subprocess
+  // environment variables for each request served via SPDY.  Register a hook
+  // to do so; we use the fixup hook for this because that's the same hook that
+  // mod_ssl uses for setting its subprocess environment variables.
+  ap_hook_fixups(SetUpSubprocessEnv, NULL, NULL, APR_HOOK_MIDDLE);
+
+  // Our server push filter is a request-level filter, so we insert it with the
+  // insert-filter hook.
+  ap_hook_insert_filter(InsertRequestFilters, NULL, NULL, APR_HOOK_MIDDLE);
+
+  // Register a hook with mod_ssl to be called when deciding what protocols to
+  // advertise during Next Protocol Negotiatiation (NPN); we'll use this
+  // opportunity to advertise that we support SPDY.  This hook is declared in
+  // mod_ssl.h, for appropriately-patched versions of mod_ssl.  See TAMB 10.2.3
+  // for more about optional hooks.
+  APR_OPTIONAL_HOOK(
+      modssl,                     // prefix of optional hook
+      npn_advertise_protos_hook,  // name of optional hook
+      AdvertiseSpdy,              // hook function to be called
+      NULL,                       // predecessors
+      NULL,                       // successors
+      APR_HOOK_MIDDLE);           // position
+  // If we're advertising SPDY support via NPN, we ought to also advertise HTTP
+  // support.  Ideally, the Apache core HTTP module would do this, but for now
+  // it doesn't, so we'll do it for them.  We use APR_HOOK_LAST here, since
+  // http/1.1 is our last choice.  Note that our AdvertiseHttp function won't
+  // add "http/1.1" to the list if it's already there, so this is future-proof.
+  APR_OPTIONAL_HOOK(modssl, npn_advertise_protos_hook,
+                    AdvertiseHttp, NULL, NULL, APR_HOOK_LAST);
+
+  // Register a hook with mod_ssl to be called when NPN has been completed and
+  // the next protocol decided upon.  This hook will check if we're actually to
+  // be using SPDY with the client, and enable this module if so.  This hook is
+  // declared in mod_ssl.h, for appropriately-patched versions of mod_ssl.
+  APR_OPTIONAL_HOOK(
+      modssl,                     // prefix of optional hook
+      npn_proto_negotiated_hook,  // name of optional hook
+      OnNextProtocolNegotiated,   // hook function to be called
+      NULL,                       // predecessors
+      NULL,                       // successors
+      APR_HOOK_MIDDLE);           // position
+
+  // Create the various filters that will be used to route bytes to/from us
+  // on slave connections.
+  mod_spdy::ApacheSpdyStreamTaskFactory::InitFilters();
+
+  // Also create the filter we will use to detect us being instructed to
+  // do server pushes.
+  gServerPushFilterHandle = ap_register_output_filter(
+      "SPDY_SERVER_PUSH",         // name
+      ServerPushFilterFunc,       // filter function
+      NULL,                       // init function (n/a in our case)
+      // We use PROTOCOL-1 so that we come in just before the core HTTP_HEADER
+      // filter serializes the response header table.  That way we have a
+      // chance to remove the X-Associated-Content header before it is sent to
+      // the client, while still letting us run as late as possible so that we
+      // can catch headers set by a variety of modules (for example,
+      // mod_headers doesn't run until the CONTENT_SET stage, so if we ran at
+      // the RESOURCE stage, that would be too early).
+      static_cast<ap_filter_type>(AP_FTYPE_PROTOCOL - 1));
+
+  // Create the filter used to do server push discovery for auto-generation of
+  // X-Associated-Content headers.
+  gServerPushDiscoveryFilterHandle = ap_register_output_filter(
+      "SPDY_SERVER_PUSH_DISCOVERY",   // name
+      ServerPushDiscoveryFilterFunc,  // filter function
+      NULL,                           // init function
+      // Should always be before the SPDY_SERVER_PUSH filter.
+      AP_FTYPE_CONTENT_SET);
+
+  // Register our optional functions, so that other modules can retrieve and
+  // use them.  See TAMB 10.1.2.
+  APR_REGISTER_OPTIONAL_FN(spdy_get_version);
+  ModSpdyExportSlaveConnectionFunctions();
+}
+
+}  // namespace
+
+extern "C" {
+
+  // Export our module so Apache is able to load us.
+  // See http://gcc.gnu.org/wiki/Visibility for more information.
+#if defined(__linux)
+#pragma GCC visibility push(default)
+#endif
+
+  // Declare our module object (note that "module" is a typedef for "struct
+  // module_struct"; see http_config.h for the definition of module_struct).
+  module AP_MODULE_DECLARE_DATA spdy_module = {
+    // This next macro indicates that this is a (non-MPM) Apache 2.0 module
+    // (the macro actually expands to multiple comma-separated arguments; see
+    // http_config.h for the definition):
+    STANDARD20_MODULE_STUFF,
+
+    // These next four arguments are callbacks for manipulating configuration
+    // structures (the ones we don't need are left null):
+    NULL,  // create per-directory config structure
+    NULL,  // merge per-directory config structures
+    mod_spdy::CreateSpdyServerConfig,  // create per-server config structure
+    mod_spdy::MergeSpdyServerConfigs,  // merge per-server config structures
+
+    // This argument supplies a table describing the configuration directives
+    // implemented by this module:
+    mod_spdy::kSpdyConfigCommands,
+
+    // Finally, this function will be called to register hooks for this module:
+    RegisterHooks
+  };
+
+#if defined(__linux)
+#pragma GCC visibility pop
+#endif
+
+}  // extern "C"

Added: httpd/mod_spdy/branches/httpd-2.2.x/mod_spdy/mod_spdy.gyp
URL: http://svn.apache.org/viewvc/httpd/mod_spdy/branches/httpd-2.2.x/mod_spdy/mod_spdy.gyp?rev=1591620&view=auto
==============================================================================
--- httpd/mod_spdy/branches/httpd-2.2.x/mod_spdy/mod_spdy.gyp (added)
+++ httpd/mod_spdy/branches/httpd-2.2.x/mod_spdy/mod_spdy.gyp Thu May  1 11:39:27 2014
@@ -0,0 +1,204 @@
+# Copyright 2010 Google Inc.
+#
+# Licensed 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.
+
+{
+  'variables': {
+    # Turning on chromium_code mode enables extra compiler warnings.  See
+    # src/build/common.gypi.
+    'chromium_code': 1,
+  },
+  'targets': [
+    {
+      'target_name': 'spdy_common',
+      'type': '<(library)',
+      'dependencies': [
+        '<(DEPTH)/base/base.gyp:base',
+        '<(DEPTH)/build/build_util.gyp:mod_spdy_version_header',
+        '<(DEPTH)/net/net.gyp:instaweb_util',
+        '<(DEPTH)/net/net.gyp:spdy',
+      ],
+      'include_dirs': [
+        '<(DEPTH)',
+      ],
+      'export_dependent_settings': [
+        '<(DEPTH)/base/base.gyp:base',
+        '<(DEPTH)/net/net.gyp:spdy',
+      ],
+      'sources': [
+        'common/executor.cc',
+        'common/http_request_visitor_interface.cc',
+        'common/http_response_parser.cc',
+        'common/http_response_visitor_interface.cc',
+        'common/http_string_builder.cc',
+        'common/http_to_spdy_converter.cc',
+        'common/protocol_util.cc',
+        'common/server_push_discovery_learner.cc',
+        'common/server_push_discovery_session.cc',
+        'common/shared_flow_control_window.cc',
+        'common/spdy_frame_priority_queue.cc',
+        'common/spdy_frame_queue.cc',
+        'common/spdy_server_config.cc',
+        'common/spdy_server_push_interface.cc',
+        'common/spdy_session.cc',
+        'common/spdy_session_io.cc',
+        'common/spdy_stream.cc',
+        'common/spdy_stream_task_factory.cc',
+        'common/spdy_to_http_converter.cc',
+        'common/thread_pool.cc',
+      ],
+    },
+    {
+      'target_name': 'spdy_apache',
+      'type': '<(library)',
+      'dependencies': [
+        'spdy_common',
+        '<(DEPTH)/base/base.gyp:base',
+        '<(DEPTH)/build/build_util.gyp:mod_spdy_version_header',
+        '<(DEPTH)/third_party/apache/httpd/httpd.gyp:include',
+        '<(DEPTH)/third_party/apache/util_cookies/util_cookies.gyp:include',
+      ],
+      'include_dirs': [
+        '<(DEPTH)',
+      ],
+      'export_dependent_settings': [
+        'spdy_common',
+        '<(DEPTH)/base/base.gyp:base',
+        '<(DEPTH)/third_party/apache/httpd/httpd.gyp:include',
+      ],
+      'sources': [
+        'apache/apache_spdy_session_io.cc',
+        'apache/apache_spdy_stream_task_factory.cc',
+        'apache/config_commands.cc',
+        'apache/config_util.cc',
+        'apache/filters/http_to_spdy_filter.cc',
+        'apache/filters/server_push_filter.cc',
+        'apache/filters/server_push_discovery_filter.cc',
+        'apache/filters/spdy_to_http_filter.cc',
+        'apache/id_pool.cc',
+        'apache/log_message_handler.cc',
+        'apache/master_connection_context.cc',
+        'apache/pool_util.cc',
+        'apache/sockaddr_util.cc',
+        'apache/slave_connection.cc',
+        'apache/slave_connection_api.cc',
+        'apache/slave_connection_context.cc',
+        'apache/ssl_util.cc',
+      ],
+    },
+    {
+      'target_name': 'mod_spdy',
+      'type': 'loadable_module',
+      'dependencies': [
+        'spdy_apache',
+        '<(DEPTH)/base/base.gyp:base',
+        '<(DEPTH)/build/build_util.gyp:mod_spdy_version_header',
+        '<(DEPTH)/net/net.gyp:spdy',
+        '<(DEPTH)/third_party/apache/httpd/httpd.gyp:include',
+        '<(DEPTH)/third_party/apache/util_cookies/util_cookies.gyp:util_cookies',
+      ],
+      'include_dirs': [
+        '<(DEPTH)',
+      ],
+      'sources': [
+        'mod_spdy.cc',
+      ],
+      'conditions': [['OS == "mac"', {
+        'xcode_settings': {
+          # We must null out these two variables when building this target,
+          # because it is a loadable_module (-bundle).
+          'DYLIB_COMPATIBILITY_VERSION':'',
+          'DYLIB_CURRENT_VERSION':'',
+        }
+      }]],
+    },
+    {
+      'target_name': 'spdy_common_testing',
+      'type': '<(library)',
+      'dependencies': [
+        '<(DEPTH)/base/base.gyp:base',
+        '<(DEPTH)/net/net.gyp:instaweb_util',
+        '<(DEPTH)/net/net.gyp:spdy',
+        '<(DEPTH)/testing/gmock.gyp:gmock',
+      ],
+      'include_dirs': [
+        '<(DEPTH)',
+      ],
+      'export_dependent_settings': [
+        '<(DEPTH)/base/base.gyp:base',
+        '<(DEPTH)/net/net.gyp:spdy',
+        '<(DEPTH)/testing/gmock.gyp:gmock',
+      ],
+      'sources': [
+        'common/testing/async_task_runner.cc',
+        'common/testing/notification.cc',
+        'common/testing/spdy_frame_matchers.cc',
+      ],
+    },
+    {
+      'target_name': 'spdy_common_test',
+      'type': 'executable',
+      'dependencies': [
+        'spdy_common',
+        'spdy_common_testing',
+        '<(DEPTH)/testing/gmock.gyp:gmock',
+        '<(DEPTH)/testing/gtest.gyp:gtest',
+        '<(DEPTH)/testing/gtest.gyp:gtest_main',
+      ],
+      'include_dirs': [
+        '<(DEPTH)',
+      ],
+      'sources': [
+        'common/http_response_parser_test.cc',
+        'common/http_to_spdy_converter_test.cc',
+        'common/protocol_util_test.cc',
+        'common/server_push_discovery_learner_test.cc',
+        'common/server_push_discovery_session_test.cc',
+        'common/shared_flow_control_window_test.cc',
+        'common/spdy_frame_priority_queue_test.cc',
+        'common/spdy_frame_queue_test.cc',
+        'common/spdy_session_test.cc',
+        'common/spdy_stream_test.cc',
+        'common/spdy_to_http_converter_test.cc',
+        'common/thread_pool_test.cc',
+      ],
+    },
+    {
+      'target_name': 'spdy_apache_test',
+      'type': 'executable',
+      'dependencies': [
+        'spdy_apache',
+        'spdy_common_testing',
+        '<(DEPTH)/build/build_util.gyp:mod_spdy_version_header',
+        '<(DEPTH)/testing/gtest.gyp:gtest',
+        '<(DEPTH)/third_party/apache/apr/apr.gyp:apr',
+        '<(DEPTH)/third_party/apache/aprutil/aprutil.gyp:aprutil',
+        '<(DEPTH)/third_party/apache/util_cookies/util_cookies.gyp:util_cookies',
+      ],
+      'include_dirs': [
+        '<(DEPTH)',
+      ],
+      'sources': [
+        'apache/filters/http_to_spdy_filter_test.cc',
+        'apache/filters/server_push_discovery_filter_test.cc',
+        'apache/filters/server_push_filter_test.cc',
+        'apache/filters/spdy_to_http_filter_test.cc',
+        'apache/id_pool_test.cc',
+        'apache/pool_util_test.cc',
+        'apache/sockaddr_util_test.cc',
+        'apache/testing/dummy_util_filter.cc',
+        'apache/testing/spdy_apache_test_main.cc',
+      ],
+    },
+  ],
+}

Added: httpd/mod_spdy/branches/httpd-2.2.x/mod_spdy/mod_spdy.h
URL: http://svn.apache.org/viewvc/httpd/mod_spdy/branches/httpd-2.2.x/mod_spdy/mod_spdy.h?rev=1591620&view=auto
==============================================================================
--- httpd/mod_spdy/branches/httpd-2.2.x/mod_spdy/mod_spdy.h (added)
+++ httpd/mod_spdy/branches/httpd-2.2.x/mod_spdy/mod_spdy.h Thu May  1 11:39:27 2014
@@ -0,0 +1,47 @@
+/* Copyright 2011 Google Inc.
+ *
+ * Licensed 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.
+ */
+
+/* This is a public header file, to be used by other Apache modules.  So,
+ * identifiers declared here should follow Apache module naming conventions
+ * (specifically, identifiers should be lowercase_with_underscores, and our
+ * identifiers should start with the spdy_ prefix), and this header file must
+ * be valid in old-school C (not just C++). */
+
+#ifndef MOD_SPDY_MOD_SPDY_H_
+#define MOD_SPDY_MOD_SPDY_H_
+
+#include "httpd.h"
+#include "apr_optional.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** An optional function which returns zero if the given connection is _not_
+ * using SPDY, and otherwise returns the (non-zero) SPDY protocol version
+ * number being used on the connection.  This can be used e.g. to alter the
+ * response for a given request to optimize for SPDY if SPDY is being used. */
+APR_DECLARE_OPTIONAL_FN(int, spdy_get_version, (conn_rec*));
+
+/* TODO(mdsteele): Add an optional function for doing a SPDY server push. */
+
+/* TODO(mdsteele): Consider adding an optional function to tell mod_spdy NOT to
+ * use SPDY for a connection (similar to ssl_engine_disable in mod_ssl). */
+
+#ifdef __cplusplus
+}  /* extern "C" */
+#endif
+
+#endif  /* MOD_SPDY_MOD_SPDY_H_ */

Propchange: httpd/mod_spdy/branches/httpd-2.2.x/mod_spdy/mod_spdy.h
------------------------------------------------------------------------------
    svn:eol-style = native

Added: httpd/mod_spdy/branches/httpd-2.2.x/net/net.gyp
URL: http://svn.apache.org/viewvc/httpd/mod_spdy/branches/httpd-2.2.x/net/net.gyp?rev=1591620&view=auto
==============================================================================
--- httpd/mod_spdy/branches/httpd-2.2.x/net/net.gyp (added)
+++ httpd/mod_spdy/branches/httpd-2.2.x/net/net.gyp Thu May  1 11:39:27 2014
@@ -0,0 +1,51 @@
+# Copyright (c) 2009 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+  'variables': {
+    'chromium_code': 1,
+    'chromium_root': '<(DEPTH)/third_party/chromium/src',
+  },
+  'targets': [
+    {
+      'target_name': 'instaweb_util',
+      'type': '<(library)',
+      'dependencies': [
+        '<(DEPTH)/base/base.gyp:base',
+      ],
+      'include_dirs': [
+        '<(DEPTH)',
+      ],
+      'export_dependent_settings': [
+        '<(DEPTH)/base/base.gyp:base',
+      ],
+      'sources': [
+        # TODO(mdsteele): Add sources here as we need them.
+        'instaweb/util/function.cc',
+      ],
+    },
+    {
+      'target_name': 'spdy',
+      'type': '<(library)',
+      'dependencies': [
+        '<(DEPTH)/base/base.gyp:base',
+        '<(DEPTH)/third_party/zlib/zlib.gyp:zlib',
+      ],
+      'export_dependent_settings': [
+        '<(DEPTH)/base/base.gyp:base',
+      ],
+      'include_dirs': [
+        '<(DEPTH)',
+        '<(chromium_root)',
+      ],
+      'sources': [
+        '<(chromium_root)/net/spdy/buffered_spdy_framer.cc',
+        '<(chromium_root)/net/spdy/spdy_frame_builder.cc',
+        '<(chromium_root)/net/spdy/spdy_frame_reader.cc',
+        '<(chromium_root)/net/spdy/spdy_framer.cc',
+        '<(chromium_root)/net/spdy/spdy_protocol.cc',
+      ],
+    },
+  ],
+}

Added: httpd/mod_spdy/branches/httpd-2.2.x/scripts/loadtest.py
URL: http://svn.apache.org/viewvc/httpd/mod_spdy/branches/httpd-2.2.x/scripts/loadtest.py?rev=1591620&view=auto
==============================================================================
--- httpd/mod_spdy/branches/httpd-2.2.x/scripts/loadtest.py (added)
+++ httpd/mod_spdy/branches/httpd-2.2.x/scripts/loadtest.py Thu May  1 11:39:27 2014
@@ -0,0 +1,187 @@
+#!/usr/bin/env python
+
+# Copyright 2012 Google Inc.
+#
+# Licensed 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.
+
+# A simple script for load-testing mod_spdy (or any other SPDY server).  For
+# example, to hit the server with 150 simultaneous SPDY clients, each fetching
+# the URLs https://example.com/ and https://example.com/image.jpg, you would
+# run:
+#
+#  $ ./loadtest.py spdy 150 https://example.com/ https://example.com/image.jpg
+#
+# To run the same test with plain HTTPS clients instead of SPDY clients (for
+# comparison), you would run:
+#
+#  $ ./loadtest.py https 150 https://example.com/ https://example.com/image.jpg
+#
+# Press Ctrl-C to stop the test.
+#
+# You must have spdycat (https://github.com/tatsuhiro-t/spdylay) installed and
+# on your $PATH in order to run SPDY tests, and you must have curl installed in
+# order to run HTTPS or HTTP tests.
+
+from __future__ import division  # Always convert ints to floats for / operator
+from __future__ import print_function  # Treat print as function, not keyword
+
+import re
+import subprocess
+import sys
+import time
+
+#=============================================================================#
+
+def print_usage_and_quit():
+  sys.stderr.write('Usage: {0} TYPE MAX_CLIENTS URL...\n'.format(sys.argv[0]))
+  sys.stderr.write('TYPE must be one of "spdy", "https", or "http"\n')
+  sys.stderr.write('MAX_CLIENTS must be a positive integer\n')
+  sys.exit(1)
+
+def with_scheme(url, scheme):
+  """Given a URL string, return a new URL string with the given scheme."""
+  if re.match(r'^[a-zA-Z0-9]+:', url):
+    return re.sub(r'^[a-zA-Z0-9]+:', scheme + ':', url)
+  elif url.startswith('//'):
+    return scheme + ':' + url
+  else:
+    return scheme + '://' + url
+
+
+class ClientProcess (object):
+  """A client subprocess that will try to load the URLs from the server."""
+
+  def __init__(self, key, command, factory):
+    self.__key = key
+    self.__child = subprocess.Popen(command, stdout=open('/dev/null', 'wb'))
+    self.__start_time = time.time()
+    self.__factory = factory
+
+  def get_key(self):
+    return self.__key
+
+  def get_start_time(self):
+    return self.__start_time
+
+  def check_done(self):
+    """If the client is done, print time and return True, else return False."""
+    code = self.__child.poll()
+    if code is None:
+      return False
+    else:
+      duration = time.time() - self.__start_time
+      self.__factory._client_finished(self.__key, code, duration)
+      return True
+
+  def kill(self):
+    """Shut down this client."""
+    self.__child.kill()
+
+
+class ClientFactory (object):
+  """A factory for ClientProcess objects, that also tracks stats."""
+
+  def __init__(self, command):
+    """Create a factory that will use the given command for subprocesses."""
+    self.__command = command
+    self.num_started = 0
+    self.num_finished = 0
+    self.max_duration = 0.0
+    self.total_duration = 0.0
+
+  def new_client(self):
+    """Create and return a new ClientProcess."""
+    self.num_started += 1
+    return ClientProcess(key=self.num_started, command=self.__command,
+                         factory=self)
+
+  def _client_finished(self, key, code, duration):
+    """Called by each ClientProcess when it finishes."""
+    self.num_finished += 1
+    self.max_duration = max(self.max_duration, duration)
+    self.total_duration += duration
+    print('Client {0} exit {1} after {2:.3f}s'.format(key, code, duration))
+
+#=============================================================================#
+
+if len(sys.argv) < 4:
+  print_usage_and_quit()
+
+# Determine what type of test we're doing and what URL scheme to use.
+TYPE = sys.argv[1].lower()
+if TYPE not in ['spdy', 'https', 'http']:
+  print_usage_and_quit()
+SCHEME = 'https' if TYPE == 'spdy' else TYPE
+
+# Determine how many clients to have at once.
+try:
+  MAX_CLIENTS = int(sys.argv[2])
+except ValueError:
+  print_usage_and_quit()
+if MAX_CLIENTS < 1:
+  print_usage_and_quit()
+
+# Collect the URLs to fetch from.
+URLS = []
+for url in sys.argv[3:]:
+  URLS.append(with_scheme(url, SCHEME))
+
+# Put together the subprocess command to issue for each client.
+if TYPE == 'spdy':
+  # The -n flag tells spdycat throw away the downloaded data without saving it.
+  COMMAND = ['spdycat', '-n'] + URLS
+else:
+  # The -s flag tells curl to be silent (don't display progress meter); the -k
+  # flag tells curl to ignore certificate errors (e.g. self-signed certs).
+  COMMAND = ['curl', '-sk'] + URLS
+
+# Print out a summary of the test we'll be doing before we start.
+print('TYPE={0}'.format(TYPE))
+print('URLS ({0}):'.format(len(URLS)))
+for url in URLS:
+    print('  ' + url)
+print('MAX_CLIENTS={0}'.format(MAX_CLIENTS))
+
+# Run the test.
+factory = ClientFactory(COMMAND)
+clients = []
+try:
+  # Start us off with an initial batch of clients.
+  for index in xrange(MAX_CLIENTS):
+    clients.append(factory.new_client())
+  # Each time a client finishes, replace it with a new client.
+  # TODO(mdsteele): This is a busy loop, which isn't great.  What we want is to
+  #   sleep until one or more children are done.  Maybe we could do something
+  #   clever that would allow us to do a select() call here or something.
+  while True:
+    for index in xrange(MAX_CLIENTS):
+      if clients[index].check_done():
+        clients[index] = factory.new_client()
+# Stop when the user hits Ctrl-C, and print a summary of the results.
+except KeyboardInterrupt:
+  print()
+  if clients:
+    slowpoke = min(clients, key=(lambda c: c.get_key()))
+    print('Earliest unfinished client, {0}, not done after {1:.3f}s'.format(
+        slowpoke.get_key(), time.time() - slowpoke.get_start_time()))
+  if factory.num_finished > 0:
+    print('Avg time per client: {0:.3f}s ({1} started, {2} completed)'.format(
+        factory.total_duration / factory.num_finished,
+        factory.num_started, factory.num_finished))
+    print('Max time per client: {0:.3f}s'.format(factory.max_duration))
+    print("URLs served per second: {0:.3f}".format(
+        factory.num_finished * len(URLS) / factory.total_duration))
+for client in clients:
+  client.kill()
+
+#=============================================================================#

Propchange: httpd/mod_spdy/branches/httpd-2.2.x/scripts/loadtest.py
------------------------------------------------------------------------------
    svn:eol-style = native

Added: httpd/mod_spdy/branches/httpd-2.2.x/scripts/mod_ssl_with_npn.patch
URL: http://svn.apache.org/viewvc/httpd/mod_spdy/branches/httpd-2.2.x/scripts/mod_ssl_with_npn.patch?rev=1591620&view=auto
==============================================================================
--- httpd/mod_spdy/branches/httpd-2.2.x/scripts/mod_ssl_with_npn.patch (added)
+++ httpd/mod_spdy/branches/httpd-2.2.x/scripts/mod_ssl_with_npn.patch Thu May  1 11:39:27 2014
@@ -0,0 +1,235 @@
+Index: modules/ssl/ssl_private.h
+===================================================================
+--- modules/ssl/ssl_private.h	(revision 1585744)
++++ modules/ssl/ssl_private.h	(working copy)
+@@ -653,6 +653,7 @@
+ #ifndef OPENSSL_NO_TLSEXT
+ int          ssl_callback_ServerNameIndication(SSL *, int *, modssl_ctx_t *);
+ #endif
++int ssl_callback_AdvertiseNextProtos(SSL *ssl, const unsigned char **data, unsigned int *len, void *arg);
+ 
+ /**  Session Cache Support  */
+ void         ssl_scache_init(server_rec *, apr_pool_t *);
+Index: modules/ssl/ssl_engine_init.c
+===================================================================
+--- modules/ssl/ssl_engine_init.c	(revision 1585744)
++++ modules/ssl/ssl_engine_init.c	(working copy)
+@@ -654,6 +654,11 @@
+ #endif
+ 
+     SSL_CTX_set_info_callback(ctx, ssl_callback_Info);
++
++#ifdef HAVE_TLS_NPN
++    SSL_CTX_set_next_protos_advertised_cb(
++        ctx, ssl_callback_AdvertiseNextProtos, NULL);
++#endif
+ }
+ 
+ static void ssl_init_ctx_verify(server_rec *s,
+Index: modules/ssl/ssl_engine_io.c
+===================================================================
+--- modules/ssl/ssl_engine_io.c	(revision 1585744)
++++ modules/ssl/ssl_engine_io.c	(working copy)
+@@ -338,6 +338,7 @@
+     apr_pool_t *pool;
+     char buffer[AP_IOBUFSIZE];
+     ssl_filter_ctx_t *filter_ctx;
++    int npn_finished;  /* 1 if NPN has finished, 0 otherwise */
+ } bio_filter_in_ctx_t;
+ 
+ /*
+@@ -1451,6 +1452,27 @@
+         APR_BRIGADE_INSERT_TAIL(bb, bucket);
+     }
+ 
++#ifdef HAVE_TLS_NPN
++    /* By this point, Next Protocol Negotiation (NPN) should be completed (if
++     * our version of OpenSSL supports it).  If we haven't already, find out
++     * which protocol was decided upon and inform other modules by calling
++     * npn_proto_negotiated_hook. */
++    if (!inctx->npn_finished) {
++        const unsigned char *next_proto = NULL;
++        unsigned next_proto_len = 0;
++
++        SSL_get0_next_proto_negotiated(
++            inctx->ssl, &next_proto, &next_proto_len);
++        ap_log_cerror(APLOG_MARK, APLOG_DEBUG, APR_SUCCESS, f->c,
++                      "SSL NPN negotiated protocol: '%s'",
++                      apr_pstrmemdup(f->c->pool, (const char*)next_proto,
++                                     next_proto_len));
++        modssl_run_npn_proto_negotiated_hook(
++            f->c, (const char*)next_proto, next_proto_len);
++        inctx->npn_finished = 1;
++    }
++#endif
++
+     return APR_SUCCESS;
+ }
+ 
+@@ -1795,6 +1817,7 @@
+     inctx->block = APR_BLOCK_READ;
+     inctx->pool = c->pool;
+     inctx->filter_ctx = filter_ctx;
++    inctx->npn_finished = 0;
+ }
+ 
+ void ssl_io_filter_init(conn_rec *c, SSL *ssl)
+Index: modules/ssl/ssl_engine_kernel.c
+===================================================================
+--- modules/ssl/ssl_engine_kernel.c	(revision 1585744)
++++ modules/ssl/ssl_engine_kernel.c	(working copy)
+@@ -2141,3 +2141,84 @@
+     return 0;
+ }
+ #endif
++
++#ifdef HAVE_TLS_NPN
++/*
++ * This callback function is executed when SSL needs to decide what protocols
++ * to advertise during Next Protocol Negotiation (NPN).  It must produce a
++ * string in wire format -- a sequence of length-prefixed strings -- indicating
++ * the advertised protocols.  Refer to SSL_CTX_set_next_protos_advertised_cb
++ * in OpenSSL for reference.
++ */
++int ssl_callback_AdvertiseNextProtos(SSL *ssl, const unsigned char **data_out,
++                                     unsigned int *size_out, void *arg)
++{
++    conn_rec *c = (conn_rec*)SSL_get_app_data(ssl);
++    apr_array_header_t *protos;
++    int num_protos;
++    unsigned int size;
++    int i;
++    unsigned char *data;
++    unsigned char *start;
++
++    *data_out = NULL;
++    *size_out = 0;
++
++    /* If the connection object is not available, then there's nothing for us
++     * to do. */
++    if (c == NULL) {
++        return SSL_TLSEXT_ERR_OK;
++    }
++
++    /* Invoke our npn_advertise_protos hook, giving other modules a chance to
++     * add alternate protocol names to advertise. */
++    protos = apr_array_make(c->pool, 0, sizeof(char*));
++    modssl_run_npn_advertise_protos_hook(c, protos);
++    num_protos = protos->nelts;
++
++    /* We now have a list of null-terminated strings; we need to concatenate
++     * them together into a single string, where each protocol name is prefixed
++     * by its length.  First, calculate how long that string will be. */
++    size = 0;
++    for (i = 0; i < num_protos; ++i) {
++        const char *string = APR_ARRAY_IDX(protos, i, const char*);
++        unsigned int length = strlen(string);
++        /* If the protocol name is too long (the length must fit in one byte),
++         * then log an error and skip it. */
++        if (length > 255) {
++            ap_log_cerror(APLOG_MARK, APLOG_ERR, 0, c,
++                          "SSL NPN protocol name too long (length=%u): %s",
++                          length, string);
++            continue;
++        }
++        /* Leave room for the length prefix (one byte) plus the protocol name
++         * itself. */
++        size += 1 + length;
++    }
++
++    /* If there is nothing to advertise (either because no modules added
++     * anything to the protos array, or because all strings added to the array
++     * were skipped), then we're done. */
++    if (size == 0) {
++        return SSL_TLSEXT_ERR_OK;
++    }
++
++    /* Now we can build the string.  Copy each protocol name string into the
++     * larger string, prefixed by its length. */
++    data = apr_palloc(c->pool, size * sizeof(unsigned char));
++    start = data;
++    for (i = 0; i < num_protos; ++i) {
++        const char *string = APR_ARRAY_IDX(protos, i, const char*);
++        apr_size_t length = strlen(string);
++        *start = (unsigned char)length;
++        ++start;
++        memcpy(start, string, length * sizeof(unsigned char));
++        start += length;
++    }
++
++    /* Success. */
++    *data_out = data;
++    *size_out = size;
++    return SSL_TLSEXT_ERR_OK;
++}
++#endif
+Index: modules/ssl/mod_ssl.c
+===================================================================
+--- modules/ssl/mod_ssl.c	(revision 1585744)
++++ modules/ssl/mod_ssl.c	(working copy)
+@@ -237,6 +237,18 @@
+     AP_END_CMD
+ };
+ 
++/* Implement 'modssl_run_npn_advertise_protos_hook'. */
++APR_IMPLEMENT_OPTIONAL_HOOK_RUN_ALL(
++    modssl, AP, int, npn_advertise_protos_hook,
++    (conn_rec *connection, apr_array_header_t *protos),
++    (connection, protos), OK, DECLINED);
++
++/* Implement 'modssl_run_npn_proto_negotiated_hook'. */
++APR_IMPLEMENT_OPTIONAL_HOOK_RUN_ALL(
++    modssl, AP, int, npn_proto_negotiated_hook,
++    (conn_rec *connection, const char *proto_name, apr_size_t proto_name_len),
++    (connection, proto_name, proto_name_len), OK, DECLINED);
++
+ /*
+  *  the various processing hooks
+  */
+Index: modules/ssl/mod_ssl.h
+===================================================================
+--- modules/ssl/mod_ssl.h	(revision 1585744)
++++ modules/ssl/mod_ssl.h	(working copy)
+@@ -60,5 +60,26 @@
+ 
+ APR_DECLARE_OPTIONAL_FN(apr_array_header_t *, ssl_extlist_by_oid, (request_rec *r, const char *oidstr));
+ 
++/** The npn_advertise_protos optional hook allows other modules to add entries
++ * to the list of protocol names advertised by the server during the Next
++ * Protocol Negotiation (NPN) portion of the SSL handshake.  The hook callee is
++ * given the connection and an APR array; it should push one or more char*'s
++ * pointing to null-terminated strings (such as "http/1.1" or "spdy/2") onto
++ * the array and return OK, or do nothing and return DECLINED. */
++APR_DECLARE_EXTERNAL_HOOK(modssl, AP, int, npn_advertise_protos_hook,
++                          (conn_rec *connection, apr_array_header_t *protos));
++
++/** The npn_proto_negotiated optional hook allows other modules to discover the
++ * name of the protocol that was chosen during the Next Protocol Negotiation
++ * (NPN) portion of the SSL handshake.  Note that this may be the empty string
++ * (in which case modules should probably assume HTTP), or it may be a protocol
++ * that was never even advertised by the server.  The hook callee is given the
++ * connection, a non-null-terminated string containing the protocol name, and
++ * the length of the string; it should do something appropriate (i.e. insert or
++ * remove filters) and return OK, or do nothing and return DECLINED. */
++APR_DECLARE_EXTERNAL_HOOK(modssl, AP, int, npn_proto_negotiated_hook,
++                          (conn_rec *connection, const char *proto_name,
++                           apr_size_t proto_name_len));
++
+ #endif /* __MOD_SSL_H__ */
+ /** @} */
+Index: modules/ssl/ssl_toolkit_compat.h
+===================================================================
+--- modules/ssl/ssl_toolkit_compat.h	(revision 1585744)
++++ modules/ssl/ssl_toolkit_compat.h	(working copy)
+@@ -151,6 +151,11 @@
+ #define HAVE_FIPS
+ #endif
+ 
++#if OPENSSL_VERSION_NUMBER >= 0x10001000L && !defined(OPENSSL_NO_NEXTPROTONEG) \
++    && !defined(OPENSSL_NO_TLSEXT)
++#define HAVE_TLS_NPN
++#endif
++
+ #ifndef PEM_F_DEF_CALLBACK
+ #ifdef PEM_F_PEM_DEF_CALLBACK
+ /** In OpenSSL 0.9.8 PEM_F_DEF_CALLBACK was renamed */

Added: httpd/mod_spdy/branches/httpd-2.2.x/third_party/apache/apr/apr.gyp
URL: http://svn.apache.org/viewvc/httpd/mod_spdy/branches/httpd-2.2.x/third_party/apache/apr/apr.gyp?rev=1591620&view=auto
==============================================================================
--- httpd/mod_spdy/branches/httpd-2.2.x/third_party/apache/apr/apr.gyp (added)
+++ httpd/mod_spdy/branches/httpd-2.2.x/third_party/apache/apr/apr.gyp Thu May  1 11:39:27 2014
@@ -0,0 +1,212 @@
+# Copyright 2010 Google Inc.
+#
+# Licensed 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.
+
+
+{
+  'variables': {
+    'apr_root': '<(DEPTH)/third_party/apache/apr',
+    'apr_src_root': '<(apr_root)/src',
+    'apr_gen_os_root': '<(apr_root)/gen/arch/<(OS)',
+    'apr_gen_arch_root': '<(apr_gen_os_root)/<(target_arch)',
+    'system_include_path_apr%': '/usr/include/apr-1.0',
+    'conditions': [
+      ['OS!="win"', {
+        'apr_os_include': '<(apr_src_root)/include/arch/unix',
+      }, {  # else, OS=="win"
+        'apr_os_include': '<(apr_src_root)/include/arch/win32',
+      }]
+    ],
+  },
+  'conditions': [
+    ['use_system_apache_dev==0', {
+      'targets': [
+        {
+          'target_name': 'include',
+          'type': 'none',
+          'direct_dependent_settings': {
+            'include_dirs': [
+              '<(apr_src_root)/include',
+              '<(apr_os_include)',
+              '<(apr_gen_arch_root)/include',
+            ],
+            'conditions': [
+              ['OS=="mac"', {
+                'defines': [
+                  'HAVE_CONFIG_H',
+                  'DARWIN',
+                  'SIGPROCMASK_SETS_THREAD_MASK',
+                ]}],
+              ['OS=="linux"', {
+                'defines': [
+                  # We need to define _LARGEFILE64_SOURCE so <sys/types.h>
+                  # provides off64_t.
+                  '_LARGEFILE64_SOURCE',
+                  'HAVE_CONFIG_H',
+                  'LINUX=2',
+                  '_REENTRANT',
+                  '_GNU_SOURCE',
+                ],
+              }],
+            ],
+          },
+        },
+        {
+          'target_name': 'apr',
+          'type': '<(library)',
+          'dependencies': [
+            'include',
+          ],
+          'export_dependent_settings': [
+            'include',
+          ],
+          'sources': [
+            '<(apr_src_root)/passwd/apr_getpass.c',
+            '<(apr_src_root)/strings/apr_strnatcmp.c',
+            '<(apr_src_root)/strings/apr_strtok.c',
+            '<(apr_src_root)/strings/apr_strings.c',
+            '<(apr_src_root)/strings/apr_snprintf.c',
+            '<(apr_src_root)/strings/apr_fnmatch.c',
+            '<(apr_src_root)/strings/apr_cpystrn.c',
+            '<(apr_src_root)/tables/apr_tables.c',
+            '<(apr_src_root)/tables/apr_hash.c',
+          ],
+          'conditions': [
+            ['OS!="win"', { # TODO(lsong): Add win sources.
+              'conditions': [
+                ['OS=="linux"', {
+                  'cflags': [
+                    '-pthread',
+                    '-Wall',
+                  ],
+                  'link_settings': {
+                    'libraries': [
+                      '-ldl',
+                  ]},
+                }],
+              ],
+              'sources': [
+                'src/atomic/unix/builtins.c',
+                'src/atomic/unix/ia32.c',
+                'src/atomic/unix/mutex.c',
+                'src/atomic/unix/ppc.c',
+                'src/atomic/unix/s390.c',
+                'src/atomic/unix/solaris.c',
+                'src/dso/unix/dso.c',
+                'src/file_io/unix/buffer.c',
+                'src/file_io/unix/copy.c',
+                'src/file_io/unix/dir.c',
+                'src/file_io/unix/fileacc.c',
+                'src/file_io/unix/filedup.c',
+                'src/file_io/unix/filepath.c',
+                'src/file_io/unix/filepath_util.c',
+                'src/file_io/unix/filestat.c',
+                'src/file_io/unix/flock.c',
+                'src/file_io/unix/fullrw.c',
+                'src/file_io/unix/mktemp.c',
+                'src/file_io/unix/open.c',
+                'src/file_io/unix/pipe.c',
+                'src/file_io/unix/readwrite.c',
+                'src/file_io/unix/seek.c',
+                'src/file_io/unix/tempdir.c',
+                'src/locks/unix/global_mutex.c',
+                'src/locks/unix/proc_mutex.c',
+                'src/locks/unix/thread_cond.c',
+                'src/locks/unix/thread_mutex.c',
+                'src/locks/unix/thread_rwlock.c',
+                'src/memory/unix/apr_pools.c',
+                'src/misc/unix/charset.c',
+                'src/misc/unix/env.c',
+                'src/misc/unix/errorcodes.c',
+                'src/misc/unix/getopt.c',
+                'src/misc/unix/otherchild.c',
+                'src/misc/unix/rand.c',
+                'src/misc/unix/start.c',
+                'src/misc/unix/version.c',
+                'src/mmap/unix/common.c',
+                'src/mmap/unix/mmap.c',
+                'src/network_io/unix/inet_ntop.c',
+                'src/network_io/unix/inet_pton.c',
+                'src/network_io/unix/multicast.c',
+                'src/network_io/unix/sendrecv.c',
+                'src/network_io/unix/sockaddr.c',
+                'src/network_io/unix/socket_util.c',
+                'src/network_io/unix/sockets.c',
+                'src/network_io/unix/sockopt.c',
+                'src/poll/unix/epoll.c',
+                'src/poll/unix/kqueue.c',
+                'src/poll/unix/poll.c',
+                'src/poll/unix/pollcb.c',
+                'src/poll/unix/pollset.c',
+                'src/poll/unix/port.c',
+                'src/poll/unix/select.c',
+                'src/random/unix/apr_random.c',
+                'src/random/unix/sha2.c',
+                'src/random/unix/sha2_glue.c',
+                'src/shmem/unix/shm.c',
+                'src/support/unix/waitio.c',
+                'src/threadproc/unix/proc.c',
+                'src/threadproc/unix/procsup.c',
+                'src/threadproc/unix/signals.c',
+                'src/threadproc/unix/thread.c',
+                'src/threadproc/unix/threadpriv.c',
+                'src/time/unix/time.c',
+                'src/time/unix/timestr.c',
+                'src/user/unix/groupinfo.c',
+                'src/user/unix/userinfo.c',
+              ],
+            }],
+          ],
+        }
+      ],
+    },
+    { # use_system_apache_dev
+      'targets': [
+        {
+          'target_name': 'include',
+          'type': 'none',
+          'direct_dependent_settings': {
+            'include_dirs': [
+              '<(system_include_path_apr)',
+            ],
+            'defines': [
+              # We need to define _LARGEFILE64_SOURCE so <sys/types.h>
+              # provides off64_t.
+              '_LARGEFILE64_SOURCE',
+              'HAVE_CONFIG_H',
+              'LINUX=2',
+              '_REENTRANT',
+              '_GNU_SOURCE',
+            ],
+          },
+        },
+        {
+          'target_name': 'apr',
+          'type': 'settings',
+          'dependencies': [
+            'include',
+          ],
+          'export_dependent_settings': [
+            'include',
+          ],
+          'link_settings': {
+            'libraries': [
+              '-lapr-1',
+            ],
+          },
+        },
+      ],
+    }],
+  ],
+}
+