+++ /dev/null
-// 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.
-
-#include "mod_spdy/apache/apache_spdy_session_io.h"
-
-#include "apr_buckets.h"
-#include "http_log.h"
-#include "util_filter.h"
-
-#include "base/basictypes.h"
-#include "base/logging.h"
-#include "mod_spdy/apache/pool_util.h" // for AprStatusString
-#include "mod_spdy/common/protocol_util.h" // for FrameData
-#include "net/spdy/buffered_spdy_framer.h"
-#include "net/spdy/spdy_protocol.h"
-
-namespace mod_spdy {
-
-namespace {
-
-// How many bytes to ask for at a time when pulling data from the connection
-// input filters. We use non-blocking reads, so we'll sometimes get less than
-// this.
-const apr_off_t kReadBytes = 4096;
-
-} // namespace
-
-ApacheSpdySessionIO::ApacheSpdySessionIO(conn_rec* connection)
- : connection_(connection),
- input_brigade_(apr_brigade_create(connection_->pool,
- connection_->bucket_alloc)),
- output_brigade_(apr_brigade_create(connection_->pool,
- connection_->bucket_alloc)) {}
-
-ApacheSpdySessionIO::~ApacheSpdySessionIO() {}
-
-bool ApacheSpdySessionIO::IsConnectionAborted() {
- return static_cast<bool>(connection_->aborted);
-}
-
-SpdySessionIO::ReadStatus ApacheSpdySessionIO::ProcessAvailableInput(
- bool block, net::BufferedSpdyFramer* framer) {
- const apr_read_type_e read_type = block ? APR_BLOCK_READ : APR_NONBLOCK_READ;
-
- // Make sure the input brigade we're using is empty.
- if (!APR_BRIGADE_EMPTY(input_brigade_)) {
- LOG(DFATAL) << "input_brigade_ should be empty";
- apr_brigade_cleanup(input_brigade_);
- }
-
- // Try to read some data into the brigade.
- {
- const apr_status_t status = ap_get_brigade(
- connection_->input_filters, input_brigade_, AP_MODE_READBYTES,
- read_type, kReadBytes);
- if (status == APR_SUCCESS) {
- // Success; we'll process the brigade below.
- } else if (APR_STATUS_IS_EAGAIN(status)) {
- // EAGAIN probably indicates that we did a non-blocking read and no data
- // was available. So, just press on and process the brigade (it should
- // be empty, but maybe there'll be metadata buckets or something). Most
- // likely we'll end up returning READ_NO_DATA at the end of this method.
- } else if (APR_STATUS_IS_TIMEUP(status)) {
- // TIMEUP tends to occur for blocking reads, if some upstream filter set
- // a timeout. Just like with EAGAIN, we'll press on and process the
- // probably-empty brigade, but since these seem to be rare, let's VLOG
- // here so that we can see when they happen.
- VLOG(3) << "ap_get_brigade returned TIMEUP";
- } else {
- // Otherwise, something has gone wrong and we should consider the
- // connection closed. If the client merely closed the connection on us,
- // we'll get an EOF error, which is fine; otherwise, something may be
- // wrong, so we should log an error.
- if (APR_STATUS_IS_EOF(status)) {
- VLOG(2) << "ap_get_brigade returned EOF";
- } else {
- LOG(ERROR) << "ap_get_brigade failed with status " << status << ": "
- << AprStatusString(status);
- }
- apr_brigade_cleanup(input_brigade_);
- return READ_CONNECTION_CLOSED;
- }
- }
-
- bool pushed_any_data = false;
- while (!APR_BRIGADE_EMPTY(input_brigade_)) {
- apr_bucket* bucket = APR_BRIGADE_FIRST(input_brigade_);
-
- if (APR_BUCKET_IS_METADATA(bucket)) {
- // Metadata bucket. We don't care about EOS or FLUSH buckets here (or
- // other, unknown metadata buckets), and there's no further filter to
- // pass it to, so we just ignore it.
- } else {
- // Data bucket -- get ready to read.
- const char* data = NULL;
- apr_size_t data_length = 0;
- const apr_status_t status = apr_bucket_read(bucket, &data, &data_length,
- read_type);
- if (status != APR_SUCCESS) {
- // TODO(mdsteele): In what situations might apr_bucket_read fail here?
- // These buckets are almost certainly coming from mod_ssl, which
- // seems to only use transient buckets, for which apr_bucket_read
- // will always succeed. However, in theory there could be another
- // filter between us and mod_ssl, and in theory it could be sending
- // us bucket types for which non-blocking reads can fail.
- LOG(ERROR) << "apr_bucket_read failed with status " << status << ": "
- << AprStatusString(status);
- }
-
- const size_t consumed = framer->ProcessInput(data, data_length);
- // If the SpdyFramer encountered an error (i.e. the client sent us
- // malformed data), then we can't recover.
- if (framer->HasError()) {
- apr_brigade_cleanup(input_brigade_);
- return READ_ERROR;
- }
- // If there was no error, the framer will have consumed all the data.
- // TODO(mdsteele): Is that true? I think it's true.
- DCHECK(consumed == data_length);
- pushed_any_data |= consumed > 0;
- }
-
- // Delete this bucket and move on to the next one.
- apr_bucket_delete(bucket);
- }
-
- // We deleted buckets as we went, so the brigade should be empty now.
- DCHECK(APR_BRIGADE_EMPTY(input_brigade_));
-
- return pushed_any_data ? READ_SUCCESS : READ_NO_DATA;
-}
-
-SpdySessionIO::WriteStatus ApacheSpdySessionIO::SendFrameRaw(
- const net::SpdySerializedFrame& frame) {
- // Make sure the output brigade we're using is empty.
- if (!APR_BRIGADE_EMPTY(output_brigade_)) {
- LOG(DFATAL) << "output_brigade_ should be empty";
- apr_brigade_cleanup(output_brigade_);
- }
-
- // Put the frame data into the output brigade.
- APR_BRIGADE_INSERT_TAIL(output_brigade_, apr_bucket_transient_create(
- frame.data(), frame.size(), output_brigade_->bucket_alloc));
-
- // Append a flush bucket to the end of the brigade, to make sure that this
- // frame makes it all the way out to the client.
- APR_BRIGADE_INSERT_TAIL(output_brigade_, apr_bucket_flush_create(
- output_brigade_->bucket_alloc));
-
- // Send the brigade through the connection's output filter chain.
- const apr_status_t status =
- ap_pass_brigade(connection_->output_filters, output_brigade_);
- apr_brigade_cleanup(output_brigade_);
- DCHECK(APR_BRIGADE_EMPTY(output_brigade_));
-
- // If we sent the data successfully, great; otherwise, consider the
- // connection closed.
- if (status == APR_SUCCESS) {
- return WRITE_SUCCESS;
- } else {
- // ECONNABORTED and EPIPE (broken pipe) are two common symptoms of the
- // connection having been closed; those are no cause for concern. For any
- // other non-success status, log an error (for now).
- if (APR_STATUS_IS_ECONNABORTED(status)) {
- VLOG(2) << "ap_pass_brigade returned ECONNABORTED";
- } else if (APR_STATUS_IS_EPIPE(status)) {
- VLOG(2) << "ap_pass_brigade returned EPIPE";
- } else {
- LOG(ERROR) << "ap_pass_brigade failed with status " << status << ": "
- << AprStatusString(status);
- }
- return WRITE_CONNECTION_CLOSED;
- }
-}
-
-} // namespace mod_spdy
+++ /dev/null
-// 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.
-
-#ifndef MOD_SPDY_APACHE_APACHE_SPDY_SESSION_IO_H_
-#define MOD_SPDY_APACHE_APACHE_SPDY_SESSION_IO_H_
-
-#include "httpd.h"
-
-#include "base/basictypes.h"
-#include "mod_spdy/common/spdy_session_io.h"
-
-namespace net {
-class BufferedSpdyFramer;
-class SpdyFrame;
-} // namespace net
-
-namespace mod_spdy {
-
-class ApacheSpdySessionIO : public SpdySessionIO {
- public:
- explicit ApacheSpdySessionIO(conn_rec* connection);
- ~ApacheSpdySessionIO();
-
- // SpdySessionIO methods:
- virtual bool IsConnectionAborted();
- virtual ReadStatus ProcessAvailableInput(bool block,
- net::BufferedSpdyFramer* framer);
- virtual WriteStatus SendFrameRaw(const net::SpdySerializedFrame& frame);
-
- private:
- conn_rec* const connection_;
- apr_bucket_brigade* const input_brigade_;
- apr_bucket_brigade* const output_brigade_;
-
- DISALLOW_COPY_AND_ASSIGN(ApacheSpdySessionIO);
-};
-
-} // namespace mod_spdy
-
-#endif // MOD_SPDY_APACHE_APACHE_SPDY_SESSION_IO_H_
+++ /dev/null
-// 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.
-
-#include "mod_spdy/apache/apache_spdy_stream_task_factory.h"
-
-#include "apr_buckets.h"
-#include "apr_network_io.h"
-#include "http_log.h"
-#include "util_filter.h"
-
-#include "base/basictypes.h"
-#include "base/logging.h"
-#include "mod_spdy/apache/config_util.h"
-#include "mod_spdy/apache/filters/http_to_spdy_filter.h"
-#include "mod_spdy/apache/filters/spdy_to_http_filter.h"
-#include "mod_spdy/apache/log_message_handler.h"
-#include "mod_spdy/apache/pool_util.h"
-#include "mod_spdy/apache/slave_connection.h"
-#include "mod_spdy/apache/slave_connection_context.h"
-#include "mod_spdy/common/spdy_stream.h"
-#include "net/instaweb/util/public/function.h"
-
-namespace mod_spdy {
-
-namespace {
-
-// These global variables store the filter handles for our filters. Normally,
-// global variables would be very dangerous in a concurrent environment like
-// Apache, but these ones are okay because they are 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* gHttpToSpdyFilterHandle = NULL;
-ap_filter_rec_t* gSpdyToHttpFilterHandle = NULL;
-
-// See TAMB 8.4.2
-apr_status_t SpdyToHttpFilterFunc(ap_filter_t* filter,
- apr_bucket_brigade* brigade,
- ap_input_mode_t mode,
- apr_read_type_e block,
- apr_off_t readbytes) {
- mod_spdy::SpdyToHttpFilter* spdy_to_http_filter =
- static_cast<mod_spdy::SpdyToHttpFilter*>(filter->ctx);
- return spdy_to_http_filter->Read(filter, brigade, mode, block, readbytes);
-}
-
-// See TAMB 8.4.1
-apr_status_t HttpToSpdyFilterFunc(ap_filter_t* filter,
- apr_bucket_brigade* input_brigade) {
- mod_spdy::HttpToSpdyFilter* http_to_spdy_filter =
- static_cast<mod_spdy::HttpToSpdyFilter*>(filter->ctx);
- return http_to_spdy_filter->Write(filter, input_brigade);
-}
-
-// A task to be returned by ApacheSpdyStreamTaskFactory::NewStreamTask().
-class ApacheStreamTask : public net_instaweb::Function {
- public:
- // The task does not take ownership of the arguments.
- ApacheStreamTask(SlaveConnectionFactory* conn_factory,
- SpdyStream* stream);
- virtual ~ApacheStreamTask();
-
- protected:
- // net_instaweb::Function methods:
- virtual void Run();
- virtual void Cancel();
-
- private:
- SpdyStream* const stream_;
- scoped_ptr<SlaveConnection> slave_connection_;
-
- DISALLOW_COPY_AND_ASSIGN(ApacheStreamTask);
-};
-
-ApacheStreamTask::ApacheStreamTask(SlaveConnectionFactory* conn_factory,
- SpdyStream* stream)
- : stream_(stream),
- slave_connection_(conn_factory->Create()) {
- const SpdyServerConfig* config =
- GetServerConfig(slave_connection_->apache_connection());
-
- // SlaveConnectionFactory::Create must have attached a slave context.
- SlaveConnectionContext* slave_context =
- slave_connection_->GetSlaveConnectionContext();
- slave_context->set_slave_stream(stream);
-
- // Create our filters to hook us up to the slave connection.
- SpdyToHttpFilter* spdy_to_http_filter = new SpdyToHttpFilter(stream);
- PoolRegisterDelete(slave_connection_->apache_connection()->pool,
- spdy_to_http_filter);
- slave_context->SetInputFilter(gSpdyToHttpFilterHandle, spdy_to_http_filter);
-
- HttpToSpdyFilter* http_to_spdy_filter = new HttpToSpdyFilter(config, stream);
- PoolRegisterDelete(slave_connection_->apache_connection()->pool,
- http_to_spdy_filter);
- slave_context->SetOutputFilter(gHttpToSpdyFilterHandle, http_to_spdy_filter);
-}
-
-ApacheStreamTask::~ApacheStreamTask() {
-}
-
-void ApacheStreamTask::Run() {
- ScopedStreamLogHandler log_handler(
- slave_connection_->apache_connection(), stream_);
- VLOG(3) << "Starting stream task";
- if (!stream_->is_aborted()) {
- slave_connection_->Run();
- }
- VLOG(3) << "Finishing stream task";
-}
-
-void ApacheStreamTask::Cancel() {
- if (VLOG_IS_ON(3)) {
- ScopedStreamLogHandler log_handler(
- slave_connection_->apache_connection(), stream_);
- VLOG(3) << "Cancelling stream task";
- }
-}
-
-} // namespace
-
-ApacheSpdyStreamTaskFactory::ApacheSpdyStreamTaskFactory(conn_rec* connection)
- : connection_factory_(connection) {}
-
-ApacheSpdyStreamTaskFactory::~ApacheSpdyStreamTaskFactory() {}
-
-void ApacheSpdyStreamTaskFactory::InitFilters() {
- // Register our input filter, and store the filter handle into a global
- // variable so we can use it later to instantiate our filter into a filter
- // chain. The "filter type" argument below determines where in the filter
- // chain our filter will be placed. We use AP_FTYPE_NETWORK so that we will
- // be at the very end of the input chain for slave connections, in place of
- // the usual core input filter.
- gSpdyToHttpFilterHandle = ap_register_input_filter(
- "SPDY_TO_HTTP", // name
- SpdyToHttpFilterFunc, // filter function
- NULL, // init function (n/a in our case)
- AP_FTYPE_NETWORK); // filter type
-
- // Now register our output filter, analogously to the input filter above.
- gHttpToSpdyFilterHandle = ap_register_output_filter(
- "HTTP_TO_SPDY", // name
- HttpToSpdyFilterFunc, // filter function
- NULL, // init function (n/a in our case)
- AP_FTYPE_NETWORK); // filter type
-}
-
-net_instaweb::Function* ApacheSpdyStreamTaskFactory::NewStreamTask(
- SpdyStream* stream) {
- return new ApacheStreamTask(&connection_factory_, stream);
-}
-
-} // namespace mod_spdy
+++ /dev/null
-// 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.
-
-#ifndef MOD_SPDY_APACHE_APACHE_SPDY_STREAM_TASK_FACTORY_H_
-#define MOD_SPDY_APACHE_APACHE_SPDY_STREAM_TASK_FACTORY_H_
-
-#include "httpd.h"
-
-#include "base/basictypes.h"
-#include "mod_spdy/apache/slave_connection.h"
-#include "mod_spdy/common/spdy_stream_task_factory.h"
-
-namespace net_instaweb { class Function; }
-
-namespace mod_spdy {
-
-class SpdyStream;
-
-class ApacheSpdyStreamTaskFactory : public SpdyStreamTaskFactory {
- public:
- explicit ApacheSpdyStreamTaskFactory(conn_rec* connection);
- ~ApacheSpdyStreamTaskFactory();
-
- // This must be called from hooks registration to create the filters
- // this class needs to route bytes between Apache & mod_spdy.
- static void InitFilters();
-
- // SpdyStreamTaskFactory methods:
- virtual net_instaweb::Function* NewStreamTask(SpdyStream* stream);
-
- private:
- SlaveConnectionFactory connection_factory_;
-
- DISALLOW_COPY_AND_ASSIGN(ApacheSpdyStreamTaskFactory);
-};
-
-} // namespace mod_spdy
-
-#endif // MOD_SPDY_APACHE_APACHE_SPDY_STREAM_TASK_FACTORY_H_
+++ /dev/null
-// 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.
-
-#include "mod_spdy/apache/config_commands.h"
-
-#include "apr_strings.h"
-
-#include "base/strings/string_number_conversions.h"
-
-#include "mod_spdy/apache/config_util.h"
-#include "mod_spdy/apache/pool_util.h"
-#include "mod_spdy/common/spdy_server_config.h"
-#include "mod_spdy/common/protocol_util.h"
-
-namespace mod_spdy {
-
-void* CreateSpdyServerConfig(apr_pool_t* pool, server_rec* server) {
- SpdyServerConfig* config = new SpdyServerConfig;
- PoolRegisterDelete(pool, config);
- return config;
-}
-
-void* MergeSpdyServerConfigs(apr_pool_t* pool, void* base, void* add) {
- SpdyServerConfig* config = new SpdyServerConfig;
- PoolRegisterDelete(pool, config);
- config->MergeFrom(*static_cast<SpdyServerConfig*>(base),
- *static_cast<SpdyServerConfig*>(add));
- return config;
-}
-
-namespace {
-
-// A function suitable for for passing to AP_INIT_TAKE1 (and hence to
-// SPDY_CONFIG_COMMAND) for a config option that requires a boolean argument
-// ("on" or "off", case-insensitive; other strings will be rejected). The
-// template argument is a setter method on SpdyServerConfig that takes a bool.
-template <void(SpdyServerConfig::*setter)(bool)>
-const char* SetBoolean(cmd_parms* cmd, void* dir, const char* arg) {
- if (0 == apr_strnatcasecmp(arg, "on")) {
- (GetServerConfig(cmd)->*setter)(true);
- return NULL;
- } else if (0 == apr_strnatcasecmp(arg, "off")) {
- (GetServerConfig(cmd)->*setter)(false);
- return NULL;
- } else {
- return apr_pstrcat(cmd->pool, cmd->cmd->name, " on|off", NULL);
- }
-}
-
-// A function suitable for for passing to AP_INIT_TAKE1 (and hence to
-// SPDY_CONFIG_COMMAND) for a config option that requires a positive integer
-// argument. The template argument is a setter method on SpdyServerConfig that
-// takes an int; the method will only ever be called with a positive argument
-// (if the user gives a non-positive argument, or a string that isn't even an
-// integer, this function will reject it with an error message).
-template <void(SpdyServerConfig::*setter)(int)>
-const char* SetPositiveInt(cmd_parms* cmd, void* dir, const char* arg) {
- int value;
- if (!base::StringToInt(arg, &value) || value < 1) {
- return apr_pstrcat(cmd->pool, cmd->cmd->name,
- " must specify a positive integer", NULL);
- }
- (GetServerConfig(cmd)->*setter)(value);
- return NULL;
-}
-
-// Like SetPositiveInt, but allows any non-negative value, not just positive.
-template <void(SpdyServerConfig::*setter)(int)>
-const char* SetNonNegativeInt(cmd_parms* cmd, void* dir, const char* arg) {
- int value;
- if (!base::StringToInt(arg, &value) || value < 0) {
- return apr_pstrcat(cmd->pool, cmd->cmd->name,
- " must specify a non-negative integer", NULL);
- }
- (GetServerConfig(cmd)->*setter)(value);
- return NULL;
-}
-
-const char* SetUseSpdyForNonSslConnections(cmd_parms* cmd, void* dir,
- const char* arg) {
- spdy::SpdyVersion value;
- if (0 == apr_strnatcasecmp(arg, "off")) {
- value = spdy::SPDY_VERSION_NONE;
- } else if (0 == apr_strnatcasecmp(arg, "2")) {
- value = spdy::SPDY_VERSION_2;
- } else if (0 == apr_strnatcasecmp(arg, "3")) {
- value = spdy::SPDY_VERSION_3;
- } else if (0 == apr_strnatcasecmp(arg, "3.1")) {
- value = spdy::SPDY_VERSION_3_1;
- } else {
- return apr_pstrcat(cmd->pool, cmd->cmd->name,
- " must be 2, 3, 3.1, or off", NULL);
- }
- GetServerConfig(cmd)->set_use_spdy_version_without_ssl(value);
- return NULL;
-}
-
-// This template can be wrapped around any of the above functions to restrict
-// the directive to being used only at the top level (as opposed to within a
-// <VirtualHost> directive).
-template <const char*(*setter)(cmd_parms*, void*, const char*)>
-const char* GlobalOnly(cmd_parms* cmd, void* dir, const char* arg) {
- const char* error = ap_check_cmd_context(cmd, GLOBAL_ONLY);
- return error != NULL ? error : (*setter)(cmd, dir, arg);
-}
-
-} // namespace
-
-// The reinterpret_cast is there because Apache's AP_INIT_TAKE1 macro needs to
-// take an old-style C function type with unspecified arguments. The
-// static_cast, then, is just to enforce that we pass the correct type of
-// function -- it will give a compile-time error if we pass a function with the
-// wrong signature.
-#define SPDY_CONFIG_COMMAND(name, fn, help) \
- AP_INIT_TAKE1( \
- name, \
- reinterpret_cast<const char*(*)()>( \
- static_cast<const char*(*)(cmd_parms*,void*,const char*)>(fn)), \
- NULL, RSRC_CONF, help)
-
-const command_rec kSpdyConfigCommands[] = {
- SPDY_CONFIG_COMMAND(
- "SpdyEnabled", SetBoolean<&SpdyServerConfig::set_spdy_enabled>,
- "Enable SPDY support"),
- SPDY_CONFIG_COMMAND(
- "SpdyMaxStreamsPerConnection",
- SetPositiveInt<&SpdyServerConfig::set_max_streams_per_connection>,
- "Maxiumum number of simultaneous SPDY streams per connection"),
- SPDY_CONFIG_COMMAND(
- "SpdyMinThreadsPerProcess",
- GlobalOnly<SetPositiveInt<
- &SpdyServerConfig::set_min_threads_per_process> >,
- "Miniumum number of worker threads to spawn per child process"),
- SPDY_CONFIG_COMMAND(
- "SpdyMaxThreadsPerProcess",
- GlobalOnly<SetPositiveInt<
- &SpdyServerConfig::set_max_threads_per_process> >,
- "Maximum number of worker threads to spawn per child process"),
- SPDY_CONFIG_COMMAND(
- "SpdyMaxServerPushDepth",
- SetNonNegativeInt<
- &SpdyServerConfig::set_max_server_push_depth>,
- "Maximum number of recursive levels to follow X-Associated-Content header. 0 Disables. Defaults to 1."),
- SPDY_CONFIG_COMMAND(
- "SpdySendVersionHeader",
- SetBoolean<&SpdyServerConfig::set_send_version_header>,
- "Send an x-mod-spdy header with the module version number"),
- // Debugging commands, which should not be used in production:
- SPDY_CONFIG_COMMAND(
- "SpdyDebugLoggingVerbosity",
- GlobalOnly<SetNonNegativeInt<&SpdyServerConfig::set_vlog_level> >,
- "Set the verbosity of mod_spdy logging"),
- SPDY_CONFIG_COMMAND(
- "SpdyDebugUseSpdyForNonSslConnections",
- SetUseSpdyForNonSslConnections,
- "Use SPDY even over non-SSL connections; DO NOT USE IN PRODUCTION"),
- {NULL}
-};
-
-} // namespace mod_spdy
+++ /dev/null
-// 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.
-
-#ifndef MOD_SPDY_APACHE_CONFIG_COMMANDS_H_
-#define MOD_SPDY_APACHE_CONFIG_COMMANDS_H_
-
-#include "httpd.h"
-#include "http_config.h"
-
-namespace mod_spdy {
-
-// An array of configuration command objects, to be placed into an Apache
-// module object. See TAMB 9.4.
-extern const command_rec kSpdyConfigCommands[];
-
-// A function to create new server config objects, with a function signature
-// appropriate to be placed into an Apache module object. See TAMB 9.3.1.
-void* CreateSpdyServerConfig(apr_pool_t* pool, server_rec* server);
-
-// A function to merge existing server config objects, with a signature
-// appropriate to be placed into an Apache module object. See TAMB 9.5.
-void* MergeSpdyServerConfigs(apr_pool_t* pool, void* base, void* add);
-
-} // namespace mod_spdy
-
-#endif // MOD_SPDY_APACHE_CONFIG_COMMANDS_H_
+++ /dev/null
-// 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.
-
-#include "mod_spdy/apache/config_util.h"
-
-#include "httpd.h"
-#include "http_config.h"
-
-#include "base/logging.h"
-#include "base/memory/scoped_ptr.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/common/spdy_server_config.h"
-
-extern "C" {
- extern module AP_MODULE_DECLARE_DATA spdy_module;
-}
-
-namespace mod_spdy {
-
-namespace {
-
-struct ConnectionContext {
- // Exactly one of the fields below should be set.
- scoped_ptr<MasterConnectionContext> master_context;
- scoped_ptr<SlaveConnectionContext> slave_context;
-};
-
-SpdyServerConfig* GetServerConfigInternal(server_rec* server) {
- void* ptr = ap_get_module_config(server->module_config, &spdy_module);
- CHECK(ptr) << "mod_spdy server config pointer is NULL";
- return static_cast<SpdyServerConfig*>(ptr);
-}
-
-ConnectionContext* GetConnContextInternal(conn_rec* connection) {
- return static_cast<ConnectionContext*>(
- ap_get_module_config(connection->conn_config, &spdy_module));
-}
-
-ConnectionContext* SetConnContextInternal(
- conn_rec* connection,
- MasterConnectionContext* master_context,
- SlaveConnectionContext* slave_context) {
- DCHECK((master_context == NULL) ^ (slave_context == NULL));
- DCHECK(GetConnContextInternal(connection) == NULL);
- ConnectionContext* context = new ConnectionContext;
- PoolRegisterDelete(connection->pool, context);
- context->master_context.reset(master_context);
- context->slave_context.reset(slave_context);
-
- // Place the context object in the connection's configuration vector, so that
- // other hook functions with access to this connection can get hold of the
- // context object. See TAMB 4.2 for details.
- ap_set_module_config(connection->conn_config, // configuration vector
- &spdy_module, // module with which to associate
- context); // pointer to store (any void* we want)
-
- return context;
-}
-
-MasterConnectionContext* GetMasterConnectionContextInternal(
- conn_rec* connection) {
- ConnectionContext* context = GetConnContextInternal(connection);
- return (context != NULL) ? context->master_context.get() : NULL;
-}
-
-SlaveConnectionContext* GetSlaveConnectionContextInternal(
- conn_rec* connection) {
- ConnectionContext* context = GetConnContextInternal(connection);
- return (context != NULL) ? context->slave_context.get() : NULL;
-}
-
-} // namespace
-
-const SpdyServerConfig* GetServerConfig(server_rec* server) {
- return GetServerConfigInternal(server);
-}
-
-const SpdyServerConfig* GetServerConfig(conn_rec* connection) {
- return GetServerConfigInternal(connection->base_server);
-}
-
-const SpdyServerConfig* GetServerConfig(request_rec* request) {
- return GetServerConfigInternal(request->server);
-}
-
-SpdyServerConfig* GetServerConfig(cmd_parms* command) {
- return GetServerConfigInternal(command->server);
-}
-
-MasterConnectionContext* CreateMasterConnectionContext(conn_rec* connection,
- bool using_ssl) {
- ConnectionContext* context = SetConnContextInternal(
- connection, new MasterConnectionContext(using_ssl), NULL);
- return context->master_context.get();
-}
-
-SlaveConnectionContext* CreateSlaveConnectionContext(conn_rec* connection) {
- ConnectionContext* context = SetConnContextInternal(
- connection, NULL, new SlaveConnectionContext());
- return context->slave_context.get();
-}
-
-bool HasMasterConnectionContext(conn_rec* connection) {
- return GetMasterConnectionContextInternal(connection) != NULL;
-}
-
-bool HasSlaveConnectionContext(conn_rec* connection) {
- return GetSlaveConnectionContextInternal(connection) != NULL;
-}
-
-MasterConnectionContext* GetMasterConnectionContext(conn_rec* connection) {
- MasterConnectionContext* context =
- GetMasterConnectionContextInternal(connection);
- DCHECK(context != NULL);
- return context;
-}
-
-SlaveConnectionContext* GetSlaveConnectionContext(conn_rec* connection) {
- SlaveConnectionContext* context =
- GetSlaveConnectionContextInternal(connection);
- DCHECK(context != NULL);
- return context;
-}
-
-} // namespace mod_spdy
+++ /dev/null
-// 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.
-
-#ifndef MOD_SPDY_APACHE_CONFIG_UTIL_H_
-#define MOD_SPDY_APACHE_CONFIG_UTIL_H_
-
-#include "httpd.h"
-#include "http_config.h"
-
-namespace mod_spdy {
-
-class MasterConnectionContext;
-class SlaveConnectionContext;
-class SpdyServerConfig;
-class SpdyStream;
-
-// Get the server configuration associated with the given object. The
-// configuration object is returned const, since by the time these functions
-// are being used, the configuration should be treated as read-only.
-const SpdyServerConfig* GetServerConfig(server_rec* server);
-const SpdyServerConfig* GetServerConfig(conn_rec* connection);
-const SpdyServerConfig* GetServerConfig(request_rec* request);
-
-// Get the server configuration associated with the given configuration command
-// parameters. Since this is for setting the configuration (rather than just
-// reading it), the configuration object is returned non-const.
-SpdyServerConfig* GetServerConfig(cmd_parms* command);
-
-// Allocate a new MasterConnectionContext object for a master connection in the given
-// connection's pool, attach it to the connection's config vector, and return
-// it. Cannot be called on connection which previously was passed to
-// Create[Master|Slave]ConnectionContext.
-MasterConnectionContext* CreateMasterConnectionContext(
- conn_rec* connection, bool using_ssl);
-
-// Allocate a new ConnectionContext object for a slave connection in the given
-// connection's pool, attach it to the connection's config vector, and return
-// it. Cannot be called on connection which previously was passed to
-// Create[Master|Slave]ConnectionContext.
-SlaveConnectionContext* CreateSlaveConnectionContext(conn_rec* connection);
-
-// Returns true if the connection has had a master connection context set.
-// We expect the result to be true for outgoing connections for which
-// mod_spdy is enabled on the server and which are using SSL, and on which
-// the pre-connection hook has fired.
-bool HasMasterConnectionContext(conn_rec* connection);
-
-// Returns true if the connection has had a slave connection context set.
-bool HasSlaveConnectionContext(conn_rec* connection);
-
-// Get the master connection context that was set on this connection
-// by a call to CreateMasterConnectionContext. Precondition:
-// HasMasterConnectionContext has been called, and returned true.
-MasterConnectionContext* GetMasterConnectionContext(conn_rec* connection);
-
-// Get the slave connection context that was set on this connection
-// by a call to CreateSlaveConnectionContext.
-// Precondition: HasSlaveConnectionContext has been called, and returned true.
-SlaveConnectionContext* GetSlaveConnectionContext(conn_rec* connection);
-
-} // namespace mod_spdy
-
-#endif // MOD_SPDY_APACHE_CONFIG_UTIL_H_
+++ /dev/null
-// 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.
-
-// There are a number of things that every output filter should do, according
-// to <http://httpd.apache.org/docs/2.3/developer/output-filters.html>. In
-// short, these things are:
-//
-// - Respect FLUSH and EOS metadata buckets, and pass other metadata buckets
-// down the chain. Ignore all buckets after an EOS.
-//
-// - Don't allocate long-lived memory on every invocation. In particular, if
-// you need a temp brigade, allocate it once and then reuse it each time.
-//
-// - Never pass an empty brigade down the chain, but be ready to accept one
-// and do nothing.
-//
-// - Calling apr_brigade_destroy can be dangerous; prefer using
-// apr_brigade_cleanup instead.
-//
-// - Don't read the entire brigade into memory at once; the brigade may, for
-// example, contain a FILE bucket representing a 42 GB file. Instead, use
-// apr_bucket_read to read a reasonable portion of the bucket, put the
-// resulting (small) bucket into a temp brigade, pass it down the chain,
-// and then clean up the temp brigade before continuing.
-//
-// - If a bucket is to be saved beyond the scope of the filter invocation
-// that first received it, it must be "set aside" using the
-// apr_bucket_setaside macro.
-//
-// - When reading a bucket, first use a non-blocking read; if it fails with
-// APR_EAGAIN, send a FLUSH bucket down the chain, and then read the bucket
-// with a blocking read.
-//
-// This code attempts to follow these rules.
-
-#include "mod_spdy/apache/filters/http_to_spdy_filter.h"
-
-#include "apr_strings.h"
-
-#include "base/logging.h"
-#include "mod_spdy/apache/pool_util.h" // for AprStatusString
-#include "mod_spdy/common/protocol_util.h"
-#include "mod_spdy/common/spdy_server_config.h"
-#include "mod_spdy/common/spdy_stream.h"
-#include "mod_spdy/common/version.h"
-#include "net/spdy/spdy_protocol.h"
-
-namespace {
-
-const char* kModSpdyVersion = MOD_SPDY_VERSION_STRING "-" LASTCHANGE_STRING;
-
-} // namespace
-
-namespace mod_spdy {
-
-HttpToSpdyFilter::HttpToSpdyFilter(const SpdyServerConfig* config,
- SpdyStream* stream)
- : receiver_(config, stream),
- converter_(stream->spdy_version(), &receiver_),
- eos_bucket_received_(false) {}
-
-HttpToSpdyFilter::~HttpToSpdyFilter() {}
-
-// Check if the SPDY stream has been aborted; if so, mark the connection object
-// as having been aborted and return APR_ECONNABORTED. Hopefully, this will
-// convince Apache to shut down processing for this (slave) connection, thus
-// allowing this stream's thread to complete and exit.
-#define RETURN_IF_STREAM_ABORT(filter) \
- do { \
- if ((filter)->c->aborted || receiver_.stream_->is_aborted()) { \
- (filter)->c->aborted = true; \
- return APR_ECONNABORTED; \
- } \
- } while (false)
-
-apr_status_t HttpToSpdyFilter::Write(ap_filter_t* filter,
- apr_bucket_brigade* input_brigade) {
- // This is a NETWORK-level filter, so there shouldn't be any filter after us.
- if (filter->next != NULL) {
- LOG(WARNING) << "HttpToSpdyFilter is not the last filter in the chain "
- << "(it is followed by " << filter->next->frec->name << ")";
- }
-
- // According to the page at
- // http://httpd.apache.org/docs/2.3/developer/output-filters.html
- // we should never pass an empty brigade down the chain, but to be safe, we
- // should be prepared to accept one and do nothing.
- if (APR_BRIGADE_EMPTY(input_brigade)) {
- LOG(INFO) << "HttpToSpdyFilter received an empty brigade.";
- return APR_SUCCESS;
- }
-
- // Loop through the brigade, reading and sending data. We delete each bucket
- // once we have successfully consumed it, before moving on to the next
- // bucket. There are two reasons to delete buckets as we go:
- //
- // 1) Some output filters (such as mod_deflate) that come before us will
- // expect us to empty out the brigade that they give us before we
- // return. If we don't do so, the second time they call us we'll see
- // all those same buckets again (along with the new buckets).
- //
- // 2) Some bucket types such as FILE don't store their data in memory, and
- // when read, split into two buckets: one containing some data, and the
- // other representing the rest of the file. If we read in all buckets
- // in the brigade without deleting ones we're done with, we will
- // eventually read the whole file into memory; by deleting buckets as we
- // go, only a portion of the file is in memory at a time.
- while (!APR_BRIGADE_EMPTY(input_brigade)) {
- apr_bucket* bucket = APR_BRIGADE_FIRST(input_brigade);
-
- if (APR_BUCKET_IS_METADATA(bucket)) {
- if (APR_BUCKET_IS_EOS(bucket)) {
- // EOS bucket -- there should be no more data buckets in this stream.
- eos_bucket_received_ = true;
- RETURN_IF_STREAM_ABORT(filter);
- converter_.Flush();
- } else if (APR_BUCKET_IS_FLUSH(bucket)) {
- // FLUSH bucket -- call Send() immediately and flush the data buffer.
- RETURN_IF_STREAM_ABORT(filter);
- converter_.Flush();
- } else {
- // Unknown metadata bucket. This bucket has no meaning to us, and
- // there's no further filter to pass it to, so we just ignore it.
- }
- } else if (eos_bucket_received_) {
- // We shouldn't be getting any data buckets after an EOS (since this is a
- // connection-level filter, we do sometimes see other metadata buckets
- // after the EOS). If we do get them, ignore them.
- LOG(INFO) << "HttpToSpdyFilter received " << bucket->type->name
- << " bucket after an EOS (and ignored it).";
- } else {
- // Data bucket -- get ready to read.
- const char* data = NULL;
- apr_size_t data_length = 0;
-
- // First, try a non-blocking read.
- apr_status_t status = apr_bucket_read(bucket, &data, &data_length,
- APR_NONBLOCK_READ);
- if (status == APR_SUCCESS) {
- RETURN_IF_STREAM_ABORT(filter);
- if (!converter_.ProcessInput(data, static_cast<size_t>(data_length))) {
- // Parse failure. The parser will have already logged an error.
- return APR_EGENERAL;
- }
- } else if (APR_STATUS_IS_EAGAIN(status)) {
- // Non-blocking read failed with EAGAIN, so try again with a blocking
- // read (but flush first, in case we block for a long time).
- RETURN_IF_STREAM_ABORT(filter);
- converter_.Flush();
- status = apr_bucket_read(bucket, &data, &data_length, APR_BLOCK_READ);
- if (status != APR_SUCCESS) {
- LOG(ERROR) << "Blocking read failed with status " << status << ": "
- << AprStatusString(status);
- // Since we didn't successfully consume this bucket, don't delete it;
- // rather, leave it (and any remaining buckets) in the brigade.
- return status; // failure
- }
- RETURN_IF_STREAM_ABORT(filter);
- if (!converter_.ProcessInput(data, static_cast<size_t>(data_length))) {
- // Parse failure. The parser will have already logged an error.
- return APR_EGENERAL;
- }
- } else {
- // Since we didn't successfully consume this bucket, don't delete it;
- // rather, leave it (and any remaining buckets) in the brigade.
- return status; // failure
- }
- }
-
- // We consumed this bucket successfully, so delete it and move on to the
- // next.
- apr_bucket_delete(bucket);
- }
-
- // We went through the whole brigade successfully, so it must be empty when
- // we return (see http://code.google.com/p/mod-spdy/issues/detail?id=17).
- DCHECK(APR_BRIGADE_EMPTY(input_brigade));
- return APR_SUCCESS;
-}
-
-HttpToSpdyFilter::ReceiverImpl::ReceiverImpl(const SpdyServerConfig* config,
- SpdyStream* stream)
- : config_(config), stream_(stream) {
- DCHECK(config_);
- DCHECK(stream_);
-}
-
-HttpToSpdyFilter::ReceiverImpl::~ReceiverImpl() {}
-
-void HttpToSpdyFilter::ReceiverImpl::ReceiveSynReply(
- net::SpdyHeaderBlock* headers, bool flag_fin) {
- DCHECK(headers);
- if (config_->send_version_header()) {
- (*headers)[http::kXModSpdy] = kModSpdyVersion;
- }
- // For client-requested streams, we should send a SYN_REPLY. For
- // server-pushed streams, the SpdySession has already sent an initial
- // SYN_STREAM with FLAG_UNIDIRECTIONAL and minimal server push headers, so we
- // now follow up with a HEADERS frame with the response headers.
- if (stream_->is_server_push()) {
- stream_->SendOutputHeaders(*headers, flag_fin);
- } else {
- stream_->SendOutputSynReply(*headers, flag_fin);
- }
-}
-
-void HttpToSpdyFilter::ReceiverImpl::ReceiveData(
- base::StringPiece data, bool flag_fin) {
- stream_->SendOutputDataFrame(data, flag_fin);
-}
-
-} // namespace mod_spdy
+++ /dev/null
-// 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.
-
-#ifndef MOD_SPDY_APACHE_FILTERS_HTTP_TO_SPDY_FILTER_H_
-#define MOD_SPDY_APACHE_FILTERS_HTTP_TO_SPDY_FILTER_H_
-
-#include <string>
-
-#include "apr_buckets.h"
-#include "util_filter.h"
-
-#include "base/basictypes.h"
-#include "mod_spdy/common/http_to_spdy_converter.h"
-
-namespace mod_spdy {
-
-class SpdyServerConfig;
-class SpdyStream;
-
-// An Apache filter for converting HTTP data into SPDY frames and sending them
-// to the output queue of a SpdyStream object. This is intended to be the
-// outermost filter in the output chain of one of our slave connections,
-// essentially taking the place of the network socket.
-//
-// In a previous implementation of this filter, we made this a TRANSCODE-level
-// filter rather than a NETWORK-level filter; this had the advantage that we
-// could pull HTTP header data directly from the Apache request object, rather
-// than having to parse the headers. However, it had the disadvantage of being
-// fragile -- for example, we had an additional output filter whose sole job
-// was to deceive Apache into not chunking the response body, and several
-// different hooks to try to make sure our output filters stayed in place even
-// in the face of Apache's weird error-handling paths. Also, using a
-// NETWORK-level filter decreases the likelihood that we'll break other modules
-// that try to use connection-level filters.
-class HttpToSpdyFilter {
- public:
- HttpToSpdyFilter(const SpdyServerConfig* config, SpdyStream* stream);
- ~HttpToSpdyFilter();
-
- // Read data from the given brigade and write the result through the given
- // filter. This method is responsible for driving the HTTP to SPDY conversion
- // process.
- apr_status_t Write(ap_filter_t* filter, apr_bucket_brigade* input_brigade);
-
- private:
- class ReceiverImpl : public HttpToSpdyConverter::SpdyReceiver {
- public:
- ReceiverImpl(const SpdyServerConfig* config, SpdyStream* stream);
- virtual ~ReceiverImpl();
- virtual void ReceiveSynReply(net::SpdyHeaderBlock* headers, bool flag_fin);
- virtual void ReceiveData(base::StringPiece data, bool flag_fin);
-
- private:
- friend class HttpToSpdyFilter;
- const SpdyServerConfig* config_;
- SpdyStream* const stream_;
-
- DISALLOW_COPY_AND_ASSIGN(ReceiverImpl);
- };
-
- ReceiverImpl receiver_;
- HttpToSpdyConverter converter_;
- bool eos_bucket_received_;
-
- DISALLOW_COPY_AND_ASSIGN(HttpToSpdyFilter);
-};
-
-} // namespace mod_spdy
-
-#endif // MOD_SPDY_APACHE_FILTERS_HTTP_TO_SPDY_FILTER_H_
+++ /dev/null
-// 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.
-
-#include "mod_spdy/apache/filters/http_to_spdy_filter.h"
-
-#include <string>
-
-#include "httpd.h"
-#include "apr_buckets.h"
-#include "apr_tables.h"
-#include "util_filter.h"
-
-#include "base/memory/scoped_ptr.h"
-#include "base/strings/string_piece.h"
-#include "mod_spdy/apache/pool_util.h"
-#include "mod_spdy/common/protocol_util.h"
-#include "mod_spdy/common/shared_flow_control_window.h"
-#include "mod_spdy/common/spdy_frame_priority_queue.h"
-#include "mod_spdy/common/spdy_server_config.h"
-#include "mod_spdy/common/spdy_stream.h"
-#include "mod_spdy/common/testing/spdy_frame_matchers.h"
-#include "mod_spdy/common/version.h"
-#include "net/spdy/spdy_protocol.h"
-#include "testing/gmock/include/gmock/gmock.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-using mod_spdy::testing::IsDataFrame;
-using mod_spdy::testing::IsHeaders;
-using mod_spdy::testing::IsSynReply;
-using testing::Pointee;
-
-namespace {
-
-class MockSpdyServerPushInterface : public mod_spdy::SpdyServerPushInterface {
- public:
- MOCK_METHOD4(StartServerPush,
- mod_spdy::SpdyServerPushInterface::PushStatus(
- net::SpdyStreamId associated_stream_id,
- int32 server_push_depth,
- net::SpdyPriority priority,
- const net::SpdyHeaderBlock& request_headers));
-};
-
-class HttpToSpdyFilterTest :
- public testing::TestWithParam<mod_spdy::spdy::SpdyVersion> {
- public:
- HttpToSpdyFilterTest()
- : spdy_version_(GetParam()),
- shared_window_(net::kSpdyStreamInitialWindowSize,
- net::kSpdyStreamInitialWindowSize),
- connection_(static_cast<conn_rec*>(
- apr_pcalloc(local_.pool(), sizeof(conn_rec)))),
- ap_filter_(static_cast<ap_filter_t*>(
- apr_pcalloc(local_.pool(), sizeof(ap_filter_t)))),
- bucket_alloc_(apr_bucket_alloc_create(local_.pool())),
- brigade_(apr_brigade_create(local_.pool(), bucket_alloc_)) {
- // Set up our Apache data structures. To keep things simple, we set only
- // the bare minimum of necessary fields, and rely on apr_pcalloc to zero
- // all others.
- connection_->pool = local_.pool();
- ap_filter_->c = connection_;
- }
-
- protected:
- void AddHeapBucket(base::StringPiece str) {
- APR_BRIGADE_INSERT_TAIL(brigade_, apr_bucket_heap_create(
- str.data(), str.size(), NULL, bucket_alloc_));
- }
-
- void AddImmortalBucket(base::StringPiece str) {
- APR_BRIGADE_INSERT_TAIL(brigade_, apr_bucket_immortal_create(
- str.data(), str.size(), bucket_alloc_));
- }
-
- void AddFlushBucket() {
- APR_BRIGADE_INSERT_TAIL(brigade_, apr_bucket_flush_create(bucket_alloc_));
- }
-
- void AddEosBucket() {
- APR_BRIGADE_INSERT_TAIL(brigade_, apr_bucket_eos_create(bucket_alloc_));
- }
-
- apr_status_t WriteBrigade(mod_spdy::HttpToSpdyFilter* filter) {
- return filter->Write(ap_filter_, brigade_);
- }
-
- void ExpectSynReply(net::SpdyStreamId stream_id,
- const net::SpdyHeaderBlock& headers,
- bool flag_fin) {
- net::SpdyFrameIR* raw_frame = NULL;
- ASSERT_TRUE(output_queue_.Pop(&raw_frame));
- ASSERT_TRUE(raw_frame != NULL);
- scoped_ptr<net::SpdyFrameIR> frame(raw_frame);
- EXPECT_THAT(*frame, IsSynReply(stream_id, flag_fin, headers));
- }
-
- void ExpectHeaders(net::SpdyStreamId stream_id,
- const net::SpdyHeaderBlock& headers,
- bool flag_fin) {
- net::SpdyFrameIR* raw_frame = NULL;
- ASSERT_TRUE(output_queue_.Pop(&raw_frame));
- ASSERT_TRUE(raw_frame != NULL);
- scoped_ptr<net::SpdyFrameIR> frame(raw_frame);
- EXPECT_THAT(*frame, IsHeaders(stream_id, flag_fin, headers));
- }
-
- void ExpectDataFrame(net::SpdyStreamId stream_id, base::StringPiece data,
- bool flag_fin) {
- net::SpdyFrameIR* raw_frame = NULL;
- ASSERT_TRUE(output_queue_.Pop(&raw_frame));
- ASSERT_TRUE(raw_frame != NULL);
- scoped_ptr<net::SpdyFrameIR> frame(raw_frame);
- EXPECT_THAT(*frame, IsDataFrame(stream_id, flag_fin, data));
- }
-
- void ExpectOutputQueueEmpty() {
- net::SpdyFrameIR* frame;
- EXPECT_FALSE(output_queue_.Pop(&frame));
- }
-
- const char* status_header_name() const {
- return (spdy_version_ < mod_spdy::spdy::SPDY_VERSION_3 ?
- mod_spdy::spdy::kSpdy2Status : mod_spdy::spdy::kSpdy3Status);
- }
-
- const char* version_header_name() const {
- return (spdy_version_ < mod_spdy::spdy::SPDY_VERSION_3 ?
- mod_spdy::spdy::kSpdy2Version : mod_spdy::spdy::kSpdy3Version);
- }
-
- const mod_spdy::spdy::SpdyVersion spdy_version_;
- mod_spdy::SpdyFramePriorityQueue output_queue_;
- mod_spdy::SharedFlowControlWindow shared_window_;
- MockSpdyServerPushInterface pusher_;
- mod_spdy::LocalPool local_;
- conn_rec* const connection_;
- ap_filter_t* const ap_filter_;
- apr_bucket_alloc_t* const bucket_alloc_;
- apr_bucket_brigade* const brigade_;
-};
-
-TEST_P(HttpToSpdyFilterTest, ResponseWithContentLength) {
- // Set up our data structures that we're testing:
- const net::SpdyStreamId stream_id = 3;
- const net::SpdyStreamId associated_stream_id = 0;
- const int32 initial_server_push_depth = 0;
- const net::SpdyPriority priority = 0;
- mod_spdy::SpdyStream stream(
- spdy_version_, stream_id, associated_stream_id,
- initial_server_push_depth, priority, net::kSpdyStreamInitialWindowSize,
- &output_queue_, &shared_window_, &pusher_);
- mod_spdy::SpdyServerConfig config;
- mod_spdy::HttpToSpdyFilter http_to_spdy_filter(&config, &stream);
-
- // Send part of the header data into the filter:
- AddImmortalBucket("HTTP/1.1 200 OK\r\n"
- "Connection: close\r\n");
- ASSERT_EQ(APR_SUCCESS, WriteBrigade(&http_to_spdy_filter));
- EXPECT_TRUE(APR_BRIGADE_EMPTY(brigade_));
-
- // Expect to get nothing out yet:
- ExpectOutputQueueEmpty();
-
- // Send the rest of the header data into the filter:
- AddImmortalBucket("Content-Length: 12000\r\n"
- "Content-Type: text/html\r\n"
- "Host: www.example.com\r\n"
- "\r\n");
- ASSERT_EQ(APR_SUCCESS, WriteBrigade(&http_to_spdy_filter));
- EXPECT_TRUE(APR_BRIGADE_EMPTY(brigade_));
-
- // Expect to get a single SYN_REPLY frame out with all the headers:
- net::SpdyHeaderBlock expected_headers;
- expected_headers[mod_spdy::http::kContentLength] = "12000";
- expected_headers[mod_spdy::http::kContentType] = "text/html";
- expected_headers[mod_spdy::http::kHost] = "www.example.com";
- expected_headers[status_header_name()] = "200";
- expected_headers[version_header_name()] = "HTTP/1.1";
- expected_headers[mod_spdy::http::kXModSpdy] =
- MOD_SPDY_VERSION_STRING "-" LASTCHANGE_STRING;
- ExpectSynReply(stream_id, expected_headers, false);
- ExpectOutputQueueEmpty();
-
- // Now send in some body data, with a FLUSH bucket:
- AddHeapBucket(std::string(1000, 'a'));
- AddFlushBucket();
- ASSERT_EQ(APR_SUCCESS, WriteBrigade(&http_to_spdy_filter));
- EXPECT_TRUE(APR_BRIGADE_EMPTY(brigade_));
-
- // Expect to get a single data frame out, containing the data we just sent:
- ExpectDataFrame(stream_id, std::string(1000, 'a'), false);
- ExpectOutputQueueEmpty();
-
- // Send in some more body data, this time with no FLUSH bucket:
- AddHeapBucket(std::string(2000, 'b'));
- ASSERT_EQ(APR_SUCCESS, WriteBrigade(&http_to_spdy_filter));
- EXPECT_TRUE(APR_BRIGADE_EMPTY(brigade_));
-
- // Expect to get nothing more out yet (because there's too little data to be
- // worth sending a frame):
- ExpectOutputQueueEmpty();
-
- // Send lots more body data, again with a FLUSH bucket:
- AddHeapBucket(std::string(3000, 'c'));
- AddFlushBucket();
- ASSERT_EQ(APR_SUCCESS, WriteBrigade(&http_to_spdy_filter));
- EXPECT_TRUE(APR_BRIGADE_EMPTY(brigade_));
-
- // This time, we should get two data frames out.
- ExpectDataFrame(stream_id, std::string(2000, 'b') + std::string(2096, 'c'),
- false);
- ExpectDataFrame(stream_id, std::string(904, 'c'), false);
- ExpectOutputQueueEmpty();
-
- // Finally, send a bunch more data, followed by an EOS bucket:
- AddHeapBucket(std::string(6000, 'd'));
- AddEosBucket();
- ASSERT_EQ(APR_SUCCESS, WriteBrigade(&http_to_spdy_filter));
- EXPECT_TRUE(APR_BRIGADE_EMPTY(brigade_));
-
- // We should get two last data frames, the latter having FLAG_FIN set.
- ExpectDataFrame(stream_id, std::string(4096, 'd'), false);
- ExpectDataFrame(stream_id, std::string(1904, 'd'), true);
- ExpectOutputQueueEmpty();
-}
-
-TEST_P(HttpToSpdyFilterTest, ChunkedResponse) {
- // Set up our data structures that we're testing:
- const net::SpdyStreamId stream_id = 3;
- const net::SpdyStreamId associated_stream_id = 0;
- const int32 initial_server_push_depth = 0;
- const net::SpdyPriority priority = 0;
- mod_spdy::SpdyStream stream(
- spdy_version_, stream_id, associated_stream_id,
- initial_server_push_depth, priority, net::kSpdyStreamInitialWindowSize,
- &output_queue_, &shared_window_, &pusher_);
- mod_spdy::SpdyServerConfig config;
- mod_spdy::HttpToSpdyFilter http_to_spdy_filter(&config, &stream);
-
- // Send part of the header data into the filter:
- AddImmortalBucket("HTTP/1.1 200 OK\r\n"
- "Keep-Alive: timeout=120\r\n");
- ASSERT_EQ(APR_SUCCESS, WriteBrigade(&http_to_spdy_filter));
- EXPECT_TRUE(APR_BRIGADE_EMPTY(brigade_));
-
- // Expect to get nothing out yet:
- ExpectOutputQueueEmpty();
-
- // Send the rest of the header data into the filter:
- AddImmortalBucket("Content-Type: text/html\r\n"
- "Transfer-Encoding: chunked\r\n"
- "Host: www.example.com\r\n"
- "\r\n");
- ASSERT_EQ(APR_SUCCESS, WriteBrigade(&http_to_spdy_filter));
- EXPECT_TRUE(APR_BRIGADE_EMPTY(brigade_));
-
- // Expect to get a single SYN_REPLY frame out with all the headers:
- net::SpdyHeaderBlock expected_headers;
- expected_headers[mod_spdy::http::kContentType] = "text/html";
- expected_headers[mod_spdy::http::kHost] = "www.example.com";
- expected_headers[status_header_name()] = "200";
- expected_headers[version_header_name()] = "HTTP/1.1";
- expected_headers[mod_spdy::http::kXModSpdy] =
- MOD_SPDY_VERSION_STRING "-" LASTCHANGE_STRING;
- ExpectSynReply(stream_id, expected_headers, false);
- ExpectOutputQueueEmpty();
-
- // Now send in some body data, with a FLUSH bucket:
- AddImmortalBucket("1B\r\n");
- AddImmortalBucket("abcdefghijklmnopqrstuvwxyz\n\r\n");
- AddImmortalBucket("17\r\n");
- AddImmortalBucket("That was ");
- AddFlushBucket();
- ASSERT_EQ(APR_SUCCESS, WriteBrigade(&http_to_spdy_filter));
- EXPECT_TRUE(APR_BRIGADE_EMPTY(brigade_));
-
- // Expect to get a single data frame out, containing the data we just sent:
- ExpectDataFrame(stream_id, "abcdefghijklmnopqrstuvwxyz\nThat was ", false);
- ExpectOutputQueueEmpty();
-
- // Send in some more body data, this time with no FLUSH bucket:
- AddImmortalBucket("the alphabet.\n\r\n");
- ASSERT_EQ(APR_SUCCESS, WriteBrigade(&http_to_spdy_filter));
- EXPECT_TRUE(APR_BRIGADE_EMPTY(brigade_));
-
- // Expect to get nothing more out yet (because there's too little data to be
- // worth sending a frame):
- ExpectOutputQueueEmpty();
-
- // Finally, terminate the response:
- AddImmortalBucket("0\r\n\r\n");
- AddEosBucket();
- ASSERT_EQ(APR_SUCCESS, WriteBrigade(&http_to_spdy_filter));
- EXPECT_TRUE(APR_BRIGADE_EMPTY(brigade_));
-
- // We should get the last data frame, with FLAG_FIN set.
- ExpectDataFrame(stream_id, "the alphabet.\n", true);
- ExpectOutputQueueEmpty();
-}
-
-TEST_P(HttpToSpdyFilterTest, RedirectResponse) {
- // Set up our data structures that we're testing:
- const net::SpdyStreamId stream_id = 5;
- const net::SpdyStreamId associated_stream_id = 0;
- const int32 initial_server_push_depth = 0;
- const net::SpdyPriority priority = 0;
- mod_spdy::SpdyStream stream(
- spdy_version_, stream_id, associated_stream_id,
- initial_server_push_depth, priority, net::kSpdyStreamInitialWindowSize,
- &output_queue_, &shared_window_, &pusher_);
- mod_spdy::SpdyServerConfig config;
- mod_spdy::HttpToSpdyFilter http_to_spdy_filter(&config, &stream);
-
- // Send part of the header data into the filter:
- AddImmortalBucket("HTTP/1.1 301 Moved Permanently\r\n"
- "Location: http://www.example.net/\r\n");
- ASSERT_EQ(APR_SUCCESS, WriteBrigade(&http_to_spdy_filter));
- EXPECT_TRUE(APR_BRIGADE_EMPTY(brigade_));
-
- // Expect to get nothing out yet:
- ExpectOutputQueueEmpty();
-
- // Signal the end of the leading headers:
- AddImmortalBucket("\r\n");
- ASSERT_EQ(APR_SUCCESS, WriteBrigade(&http_to_spdy_filter));
- EXPECT_TRUE(APR_BRIGADE_EMPTY(brigade_));
-
- // Expect to get a single SYN_REPLY frame out. This response has no body, so
- // FLAG_FIN should be set.
- net::SpdyHeaderBlock expected_headers;
- expected_headers["location"] = "http://www.example.net/";
- expected_headers[status_header_name()] = "301";
- expected_headers[version_header_name()] = "HTTP/1.1";
- expected_headers[mod_spdy::http::kXModSpdy] =
- MOD_SPDY_VERSION_STRING "-" LASTCHANGE_STRING;
- ExpectSynReply(stream_id, expected_headers, true);
- ExpectOutputQueueEmpty();
-}
-
-// Test that the filter accepts empty brigades.
-TEST_P(HttpToSpdyFilterTest, AcceptEmptyBrigade) {
- // Set up our data structures that we're testing:
- const net::SpdyStreamId stream_id = 5;
- const net::SpdyStreamId associated_stream_id = 0;
- const int32 initial_server_push_depth = 0;
- const net::SpdyPriority priority = 0;
- mod_spdy::SpdyStream stream(
- spdy_version_, stream_id, associated_stream_id,
- initial_server_push_depth, priority, net::kSpdyStreamInitialWindowSize,
- &output_queue_, &shared_window_, &pusher_);
- mod_spdy::SpdyServerConfig config;
- mod_spdy::HttpToSpdyFilter http_to_spdy_filter(&config, &stream);
-
- // Send the header data into the filter:
- AddImmortalBucket("HTTP/1.1 200 OK\r\n"
- "Content-Length: 6\r\n"
- "Content-Type: text/plain\r\n"
- "\r\n");
- ASSERT_EQ(APR_SUCCESS, WriteBrigade(&http_to_spdy_filter));
- net::SpdyHeaderBlock expected_headers;
- expected_headers[mod_spdy::http::kContentLength] = "6";
- expected_headers[mod_spdy::http::kContentType] = "text/plain";
- expected_headers[status_header_name()] = "200";
- expected_headers[version_header_name()] = "HTTP/1.1";
- expected_headers[mod_spdy::http::kXModSpdy] =
- MOD_SPDY_VERSION_STRING "-" LASTCHANGE_STRING;
- ExpectSynReply(stream_id, expected_headers, false);
- ExpectOutputQueueEmpty();
-
- // Send in some body data:
- AddImmortalBucket("foo");
- ASSERT_EQ(APR_SUCCESS, WriteBrigade(&http_to_spdy_filter));
- EXPECT_TRUE(APR_BRIGADE_EMPTY(brigade_));
- ExpectOutputQueueEmpty();
-
- // Run the filter again, with an empty brigade. It should accept it and do
- // nothing.
- ASSERT_EQ(APR_SUCCESS, WriteBrigade(&http_to_spdy_filter));
- EXPECT_TRUE(APR_BRIGADE_EMPTY(brigade_));
- ExpectOutputQueueEmpty();
-
- // Send in the rest of the body data.
- AddImmortalBucket("bar");
- AddEosBucket();
- ASSERT_EQ(APR_SUCCESS, WriteBrigade(&http_to_spdy_filter));
- EXPECT_TRUE(APR_BRIGADE_EMPTY(brigade_));
- ExpectDataFrame(stream_id, "foobar", true);
- ExpectOutputQueueEmpty();
-}
-
-// Test that the filter behaves correctly when a stream is aborted halfway
-// through producing output.
-TEST_P(HttpToSpdyFilterTest, StreamAbort) {
- // Set up our data structures that we're testing:
- const net::SpdyStreamId stream_id = 7;
- const net::SpdyStreamId associated_stream_id = 0;
- const int32 initial_server_push_depth = 0;
- const net::SpdyPriority priority =
- mod_spdy::LowestSpdyPriorityForVersion(spdy_version_);
- mod_spdy::SpdyStream stream(
- spdy_version_, stream_id, associated_stream_id,
- initial_server_push_depth, priority, net::kSpdyStreamInitialWindowSize,
- &output_queue_, &shared_window_, &pusher_);
- mod_spdy::SpdyServerConfig config;
- mod_spdy::HttpToSpdyFilter http_to_spdy_filter(&config, &stream);
-
- // Send the header data into the filter:
- AddImmortalBucket("HTTP/1.1 200 OK\r\n"
- "Content-Length: 6\r\n"
- "Content-Type: text/plain\r\n"
- "\r\n");
- ASSERT_EQ(APR_SUCCESS, WriteBrigade(&http_to_spdy_filter));
- net::SpdyHeaderBlock expected_headers;
- expected_headers[mod_spdy::http::kContentLength] = "6";
- expected_headers[mod_spdy::http::kContentType] = "text/plain";
- expected_headers[status_header_name()] = "200";
- expected_headers[version_header_name()] = "HTTP/1.1";
- expected_headers[mod_spdy::http::kXModSpdy] =
- MOD_SPDY_VERSION_STRING "-" LASTCHANGE_STRING;
- ExpectSynReply(stream_id, expected_headers, false);
- ExpectOutputQueueEmpty();
-
- // Send in some body data:
- AddImmortalBucket("foo");
- ASSERT_EQ(APR_SUCCESS, WriteBrigade(&http_to_spdy_filter));
- EXPECT_TRUE(APR_BRIGADE_EMPTY(brigade_));
- ExpectOutputQueueEmpty();
-
- // Abort the stream, and then try to send in more data. We should get back
- // ECONNABORTED, the brigade should remain unconsumed, and the connection
- // should be marked as aborted.
- stream.AbortSilently();
- AddImmortalBucket("bar");
- AddEosBucket();
- ASSERT_FALSE(connection_->aborted);
- ASSERT_TRUE(APR_STATUS_IS_ECONNABORTED(WriteBrigade(&http_to_spdy_filter)));
- EXPECT_FALSE(APR_BRIGADE_EMPTY(brigade_));
- ExpectOutputQueueEmpty();
- ASSERT_TRUE(connection_->aborted);
-}
-
-TEST_P(HttpToSpdyFilterTest, ServerPushedStream) {
- // Set up our data structures that we're testing:
- const net::SpdyStreamId stream_id = 4;
- const net::SpdyStreamId associated_stream_id = 3;
- const int32 initial_server_push_depth = 0;
- const net::SpdyPriority priority = 0;
- mod_spdy::SpdyStream stream(
- spdy_version_, stream_id, associated_stream_id,
- initial_server_push_depth, priority, net::kSpdyStreamInitialWindowSize,
- &output_queue_, &shared_window_, &pusher_);
- mod_spdy::SpdyServerConfig config;
- mod_spdy::HttpToSpdyFilter http_to_spdy_filter(&config, &stream);
-
- // Send the response data into the filter:
- AddImmortalBucket("HTTP/1.1 200 OK\r\n"
- "Content-Length: 20\r\n"
- "Content-Type: text/css\r\n"
- "\r\n"
- "BODY { color: red; }");
- ASSERT_EQ(APR_SUCCESS, WriteBrigade(&http_to_spdy_filter));
- EXPECT_TRUE(APR_BRIGADE_EMPTY(brigade_));
-
- // Since this is a server push stream, the SpdySession should have earlier
- // sent a SYN_STREAM with FLAG_UNIDIRECTIONAL, and we now expect to see a
- // HEADERS frame from the filter (rather than a SYN_REPLY):
- net::SpdyHeaderBlock expected_headers;
- expected_headers[mod_spdy::http::kContentLength] = "20";
- expected_headers[mod_spdy::http::kContentType] = "text/css";
- expected_headers[status_header_name()] = "200";
- expected_headers[version_header_name()] = "HTTP/1.1";
- expected_headers[mod_spdy::http::kXModSpdy] =
- MOD_SPDY_VERSION_STRING "-" LASTCHANGE_STRING;
- ExpectHeaders(stream_id, expected_headers, false);
- // And also the pushed data:
- ExpectDataFrame(stream_id, "BODY { color: red; }", true);
- ExpectOutputQueueEmpty();
-}
-
-TEST_P(HttpToSpdyFilterTest, DoNotSendVersionHeaderWhenAskedNotTo) {
- // Set up our data structures that we're testing:
- const net::SpdyStreamId stream_id = 5;
- const net::SpdyStreamId associated_stream_id = 0;
- const int32 initial_server_push_depth = 0;
- const net::SpdyPriority priority = 0;
- mod_spdy::SpdyStream stream(
- spdy_version_, stream_id, associated_stream_id,
- initial_server_push_depth, priority, net::kSpdyStreamInitialWindowSize,
- &output_queue_, &shared_window_, &pusher_);
- mod_spdy::SpdyServerConfig config;
- config.set_send_version_header(false);
- mod_spdy::HttpToSpdyFilter http_to_spdy_filter(&config, &stream);
-
- // Send the response into the filter:
- AddImmortalBucket("HTTP/1.1 301 Moved Permanently\r\n"
- "Location: http://www.example.net/\r\n"
- "\r\n");
- ASSERT_EQ(APR_SUCCESS, WriteBrigade(&http_to_spdy_filter));
- EXPECT_TRUE(APR_BRIGADE_EMPTY(brigade_));
-
- // Expect to get a single SYN_REPLY frame out. This response has no body, so
- // FLAG_FIN should be set. There should be no version header.
- net::SpdyHeaderBlock expected_headers;
- expected_headers["location"] = "http://www.example.net/";
- expected_headers[status_header_name()] = "301";
- expected_headers[version_header_name()] = "HTTP/1.1";
- ExpectSynReply(stream_id, expected_headers, true);
- ExpectOutputQueueEmpty();
-}
-
-// Run each test over SPDY/2, SPDY/3, and SPDY/3.1.
-INSTANTIATE_TEST_CASE_P(Spdy2And3, HttpToSpdyFilterTest, testing::Values(
- mod_spdy::spdy::SPDY_VERSION_2, mod_spdy::spdy::SPDY_VERSION_3,
- mod_spdy::spdy::SPDY_VERSION_3_1));
-
-} // namespace
+++ /dev/null
-// 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.
-
-#include "mod_spdy/apache/filters/server_push_filter.h"
-
-#include <string>
-
-#include "base/logging.h"
-#include "base/strings/string_number_conversions.h" // for StringToUint
-#include "base/strings/string_piece.h"
-#include "mod_spdy/common/protocol_util.h"
-#include "mod_spdy/common/spdy_server_config.h"
-#include "mod_spdy/common/spdy_stream.h"
-
-namespace mod_spdy {
-
-namespace {
-
-// Utility function passed to apr_table_do:
-int AddOneHeader(void* headers, const char* key, const char* value) {
- mod_spdy::MergeInHeader(
- key, value, static_cast<net::SpdyHeaderBlock*>(headers));
- return 1; // return zero to stop, or non-zero to continue iterating
-}
-
-// Modify *source to remove whitespace characters from the front.
-void AbsorbWhiteSpace(base::StringPiece* source) {
- *source = source->substr(source->find_first_not_of(" \n\r\t"));
-}
-
-// If the first thing in *source is '"foobar"', set out to 'foobar', modify
-// *source to skip past both quotes and any whitespace thereafter, and return
-// true. Otherwise return false.
-bool ParseQuotedString(base::StringPiece* source, std::string* out) {
- if (source->empty() || (*source)[0] != '"') {
- return false; // failure: no open quote
- }
- const size_t close = source->find('"', 1);
- if (close == base::StringPiece::npos) {
- return false; // failure: no close quote
- }
- source->substr(1, close - 1).CopyToString(out);
- *source = source->substr(close + 1);
- AbsorbWhiteSpace(source);
- return true;
-}
-
-// If the next character in *source is c, modify *source to skip past the
-// character and any whitespace thereafter, and return true. Otherwise return
-// false.
-bool ParseSeparator(char c, base::StringPiece* source) {
- if (source->empty() || (*source)[0] != c) {
- return false;
- }
- *source = source->substr(1);
- AbsorbWhiteSpace(source);
- return true;
-}
-
-// If the next part of *source looks like ':2' (for some value of 2), parse the
-// number, store it in *out, and modify *source to skip past it. Otherwise,
-// just leave *source unchanged. See ParseAssociatedContent for the full
-// expected format of *source.
-net::SpdyPriority ParseOptionalPriority(SpdyStream* spdy_stream,
- base::StringPiece* source) {
- const net::SpdyPriority lowest_priority =
- LowestSpdyPriorityForVersion(spdy_stream->spdy_version());
- if (!ParseSeparator(':', source)) {
- // It's okay for the ":priority" to not be there. In that case, we default
- // to minimal priority.
- return lowest_priority;
- }
- const size_t end = source->find_first_not_of("0123456789");
- const base::StringPiece number = source->substr(0, end);
- unsigned priority;
- if (!StringToUint(number, &priority)) {
- LOG(INFO) << "Invalid priority value in X-Associated-Content: '"
- << number << "'";
- return lowest_priority;
- }
- *source = source->substr(end);
- AbsorbWhiteSpace(source);
- // Clamp the priority to a legal value (larger numbers represent lower
- // priorities, so we must not return a number greater than lowest_priority).
- return (priority > lowest_priority ? lowest_priority : priority);
-}
-
-} // namespace
-
-ServerPushFilter::ServerPushFilter(SpdyStream* stream, request_rec* request,
- const SpdyServerConfig* server_cfg)
- : stream_(stream), request_(request), server_cfg_(server_cfg) {
- DCHECK(stream_);
- DCHECK(request_);
-}
-
-ServerPushFilter::~ServerPushFilter() {}
-
-apr_status_t ServerPushFilter::Write(ap_filter_t* filter,
- apr_bucket_brigade* input_brigade) {
- DCHECK_EQ(request_, filter->r);
- // We only do server pushes for SPDY v3 and later. Also, to avoid infinite
- // push loops, we don't allow push streams to invoke further push streams
- // beyond a specified depth.
- if (stream_->spdy_version() >= spdy::SPDY_VERSION_3 &&
- stream_->server_push_depth() < server_cfg_->max_server_push_depth()) {
- // Parse and start pushes for each X-Associated-Content header, if any.
- // (Note that APR tables allow multiple entries with the same key, just
- // like HTTP headers.)
- apr_table_do(
- OnXAssociatedContent, // function to call on each key/value pair
- this, // void* to be passed as first arg to function
- request_->headers_out, // the apr_table_t to iterate over
- // Varargs: zero or more char* keys to iterate over, followed by NULL
- http::kXAssociatedContent, NULL);
- // We need to give the same treatment to err_headers_out as we just gave to
- // headers_out. Depending on how the X-Associated-Content header was set,
- // it might end up in either one. For example, using a mod_headers Header
- // directive will put the header in headers_out, but using a PHP header()
- // function call will put the header in err_headers_out.
- apr_table_do(OnXAssociatedContent, this, request_->err_headers_out,
- http::kXAssociatedContent, NULL);
- }
- // Even in cases where we forbid pushes from this stream, we still purge the
- // X-Associated-Content header (from both headers_out and err_headers_out).
- apr_table_unset(request_->headers_out, http::kXAssociatedContent);
- apr_table_unset(request_->err_headers_out, http::kXAssociatedContent);
-
- // Remove ourselves from the filter chain.
- ap_remove_output_filter(filter);
- // Pass the data through unchanged.
- return ap_pass_brigade(filter->next, input_brigade);
-}
-
-void ServerPushFilter::ParseXAssociatedContentHeader(base::StringPiece value) {
- AbsorbWhiteSpace(&value);
- bool first_url = true;
-
- while (!value.empty()) {
- // The URLs should be separated by commas, so a comma should proceed each
- // URL except the first.
- if (first_url) {
- first_url = false;
- } else if (!ParseSeparator(',', &value)) {
- LOG(INFO) << "Parse error in X-Associated-Content: missing comma";
- return;
- }
-
- // Get a quoted URL string.
- std::string url;
- if (!ParseQuotedString(&value, &url)) {
- LOG(INFO) << "Parse error in X-Associated-Content: expected quoted URL";
- return;
- }
-
- // The URL may optionally be followed by a priority. If the priority is
- // not there, use the lowest-importance priority by default.
- net::SpdyPriority priority = ParseOptionalPriority(stream_, &value);
-
- // Try to parse the URL string. If it does not form a valid URL, log an
- // error and skip past this entry.
- apr_uri_t parsed_url;
- {
- const apr_status_t status =
- apr_uri_parse(request_->pool, url.c_str(), &parsed_url);
- if (status != APR_SUCCESS) {
- LOG(ERROR) << "Invalid URL in X-Associated-Content: '" << url << "'";
- continue;
- }
- }
-
- // Populate the fake request headers for the pushed stream.
- net::SpdyHeaderBlock request_headers;
- // Start off by pulling in certain headers from the associated stream's
- // request headers.
- apr_table_do(
- AddOneHeader, // function to call on each key/value pair
- &request_headers, // void* to be passed as first arg to function
- request_->headers_in, // the apr_table_t to iterate over
- // Varargs: zero or more char* keys to iterate over, followed by NULL
- "accept", "accept-charset", "accept-datetime",
- mod_spdy::http::kAcceptEncoding, "accept-language", "authorization",
- "user-agent", NULL);
- // Next, we populate special SPDY headers, using a combination of pushed
- // URL and details from the associated request.
- if (parsed_url.hostinfo != NULL) {
- request_headers[spdy::kSpdy3Host] = parsed_url.hostinfo;
- } else {
- const char* host_header =
- apr_table_get(request_->headers_in, http::kHost);
- request_headers[spdy::kSpdy3Host] =
- (host_header != NULL ? host_header :
- request_->hostname != NULL ? request_->hostname : "");
- }
- request_headers[spdy::kSpdy3Method] = "GET";
- request_headers[spdy::kSpdy3Scheme] =
- (parsed_url.scheme != NULL ? parsed_url.scheme : "https");
- request_headers[spdy::kSpdy3Version] = request_->protocol;
- // Construct the path that we are pushing from the parsed URL.
- // TODO(mdsteele): It'd be nice to support relative URLs.
- {
- std::string* path = &request_headers[spdy::kSpdy3Path];
- path->assign(parsed_url.path == NULL ? "/" : parsed_url.path);
- if (parsed_url.query != NULL) {
- path->push_back('?');
- path->append(parsed_url.query);
- }
- if (parsed_url.fragment != NULL) {
- // It's a little weird to try to push a URL with a fragment in it, but
- // if someone does so anyway, we may as well honor it.
- path->push_back('#');
- path->append(parsed_url.fragment);
- }
- }
- // Finally, we set the HTTP referrer to be the associated stream's URL.
- request_headers[http::kReferer] = request_->unparsed_uri;
-
- // Try to perform the push. If it succeeds, we'll continue with parsing.
- const SpdyServerPushInterface::PushStatus status =
- stream_->StartServerPush(priority, request_headers);
- switch (status) {
- case SpdyServerPushInterface::PUSH_STARTED:
- break; // success
- case SpdyServerPushInterface::INVALID_REQUEST_HEADERS:
- // This shouldn't happen unless there's a bug in the above code.
- LOG(DFATAL) << "ParseAssociatedContent: invalid request headers";
- return;
- case SpdyServerPushInterface::ASSOCIATED_STREAM_INACTIVE:
- case SpdyServerPushInterface::CANNOT_PUSH_EVER_AGAIN:
- case SpdyServerPushInterface::TOO_MANY_CONCURRENT_PUSHES:
- case SpdyServerPushInterface::PUSH_INTERNAL_ERROR:
- // In any of these cases, any remaining pushes specified by the header
- // are unlikely to succeed, so just stop parsing and quit.
- LOG(INFO) << "Push failed while processing X-Associated-Content "
- << "header (status=" << status << "). Skipping remainder.";
- return;
- default:
- LOG(DFATAL) << "Invalid push status value: " << status;
- return;
- }
- }
-}
-
-// static
-int ServerPushFilter::OnXAssociatedContent(
- void* server_push_filter, const char* key, const char* value) {
- static_cast<ServerPushFilter*>(server_push_filter)->
- ParseXAssociatedContentHeader(value);
- return 1; // return zero to stop, or non-zero to continue iterating
-}
-
-} // namespace mod_spdy
+++ /dev/null
-// 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.
-
-#ifndef MOD_SPDY_APACHE_FILTERS_SERVER_PUSH_FILTER_H_
-#define MOD_SPDY_APACHE_FILTERS_SERVER_PUSH_FILTER_H_
-
-#include <string>
-
-#include "apr_buckets.h"
-#include "util_filter.h"
-
-#include "base/basictypes.h"
-#include "base/strings/string_piece.h"
-#include "mod_spdy/common/spdy_server_config.h"
-
-
-namespace mod_spdy {
-
-class SpdyStream;
-
-// An Apache filter for initiating SPDY server pushes based on the
-// X-Associated-Content response header, which may be set by e.g. mod_headers
-// or a CGI script.
-class ServerPushFilter {
- public:
- // Does not take ownership of either argument.
- ServerPushFilter(SpdyStream* stream, request_rec* request,
- const SpdyServerConfig* server_cfg);
- ~ServerPushFilter();
-
- // Read data from the given brigade and write the result through the given
- // filter. This filter doesn't touch the data; it only looks at the request
- // headers.
- apr_status_t Write(ap_filter_t* filter, apr_bucket_brigade* input_brigade);
-
- private:
- // Parse the value of an X-Associated-Content header, and initiate any
- // specified server pushes. The expected format of the header value is a
- // comma-separated list of quoted URLs, each of which may optionally be
- // followed by colon and a SPDY priority value. The URLs may be fully
- // qualified URLs, or simply absolute paths (for the same scheme/host as the
- // original request). If the optional priority is omitted for a URL, then it
- // uses the lowest possible priority. Whitespace is permitted between
- // tokens. For example:
- //
- // X-Associated-Content: "https://www.example.com/foo.css",
- // "/bar/baz.js?x=y" : 1, "https://www.example.com/quux.css":3
- void ParseXAssociatedContentHeader(base::StringPiece value);
- // Utility function passed to apr_table_do. The first argument must point to
- // a ServerPushFilter; this will call ParseXAssociatedContentHeader on it.
- static int OnXAssociatedContent(void*, const char*, const char*);
-
- SpdyStream* const stream_;
- request_rec* const request_;
- const SpdyServerConfig* server_cfg_;
-
- DISALLOW_COPY_AND_ASSIGN(ServerPushFilter);
-};
-
-} // namespace mod_spdy
-
-#endif // MOD_SPDY_APACHE_FILTERS_SERVER_PUSH_FILTER_H_
+++ /dev/null
-// 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.
-
-#include "mod_spdy/apache/filters/server_push_filter.h"
-
-#include <string>
-
-#include "httpd.h"
-#include "apr_buckets.h"
-#include "apr_tables.h"
-#include "util_filter.h"
-
-#include "base/strings/string_piece.h"
-#include "mod_spdy/apache/pool_util.h"
-#include "mod_spdy/common/protocol_util.h"
-#include "mod_spdy/common/shared_flow_control_window.h"
-#include "mod_spdy/common/spdy_frame_priority_queue.h"
-#include "mod_spdy/common/spdy_server_config.h"
-#include "mod_spdy/common/spdy_stream.h"
-#include "net/spdy/spdy_framer.h"
-#include "net/spdy/spdy_protocol.h"
-#include "testing/gmock/include/gmock/gmock.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-using testing::_;
-using testing::Contains;
-using testing::Eq;
-using testing::Pair;
-using testing::Return;
-
-namespace {
-
-const char* const kRefererUrl = "https://www.example.com/index.html";
-
-class MockSpdyServerPushInterface : public mod_spdy::SpdyServerPushInterface {
- public:
- MOCK_METHOD4(StartServerPush,
- mod_spdy::SpdyServerPushInterface::PushStatus(
- net::SpdyStreamId associated_stream_id,
- int32 server_push_depth,
- net::SpdyPriority priority,
- const net::SpdyHeaderBlock& request_headers));
-};
-
-class ServerPushFilterTest :
- public testing::TestWithParam<mod_spdy::spdy::SpdyVersion> {
- public:
- ServerPushFilterTest()
- : spdy_version_(GetParam()),
- shared_window_(net::kSpdyStreamInitialWindowSize,
- net::kSpdyStreamInitialWindowSize),
- connection_(static_cast<conn_rec*>(
- apr_pcalloc(local_.pool(), sizeof(conn_rec)))),
- request_(static_cast<request_rec*>(
- apr_pcalloc(local_.pool(), sizeof(request_rec)))),
- ap_filter_(static_cast<ap_filter_t*>(
- apr_pcalloc(local_.pool(), sizeof(ap_filter_t)))),
- bucket_alloc_(apr_bucket_alloc_create(local_.pool())),
- brigade_(apr_brigade_create(local_.pool(), bucket_alloc_)) {
- // Set up our Apache data structures. To keep things simple, we set only
- // the bare minimum of necessary fields, and rely on apr_pcalloc to zero
- // all others.
- connection_->pool = local_.pool();
- request_->pool = local_.pool();
- request_->connection = connection_;
- request_->headers_in = apr_table_make(local_.pool(), 5);
- request_->headers_out = apr_table_make(local_.pool(), 5);
- request_->err_headers_out = apr_table_make(local_.pool(), 5);
- request_->protocol = const_cast<char*>("HTTP/1.1");
- request_->unparsed_uri = const_cast<char*>(kRefererUrl);
- ap_filter_->c = connection_;
- ap_filter_->r = request_;
- }
-
- virtual void SetUp() {
- ON_CALL(pusher_, StartServerPush(_, _, _, _)).WillByDefault(
- Return(mod_spdy::SpdyServerPushInterface::PUSH_STARTED));
- apr_table_setn(request_->headers_in, mod_spdy::http::kHost,
- "www.example.com");
- }
-
- protected:
- void WriteBrigade(mod_spdy::ServerPushFilter* filter) {
- EXPECT_EQ(APR_SUCCESS, filter->Write(ap_filter_, brigade_));
- }
-
- const char* status_header_name() const {
- return (spdy_version_ < mod_spdy::spdy::SPDY_VERSION_3 ?
- mod_spdy::spdy::kSpdy2Status : mod_spdy::spdy::kSpdy3Status);
- }
-
- const char* version_header_name() const {
- return (spdy_version_ < mod_spdy::spdy::SPDY_VERSION_3 ?
- mod_spdy::spdy::kSpdy2Version : mod_spdy::spdy::kSpdy3Version);
- }
-
- const mod_spdy::spdy::SpdyVersion spdy_version_;
- mod_spdy::SpdyFramePriorityQueue output_queue_;
- mod_spdy::SharedFlowControlWindow shared_window_;
- MockSpdyServerPushInterface pusher_;
- mod_spdy::LocalPool local_;
- conn_rec* const connection_;
- request_rec* const request_;
- ap_filter_t* const ap_filter_;
- apr_bucket_alloc_t* const bucket_alloc_;
- apr_bucket_brigade* const brigade_;
-};
-
-TEST_P(ServerPushFilterTest, SimpleXAssociatedContent) {
- const net::SpdyStreamId stream_id = 3;
- const net::SpdyStreamId associated_stream_id = 0;
- const int32 initial_server_push_depth = 0;
- const net::SpdyPriority priority = 1;
- const mod_spdy::SpdyServerConfig server_cfg;
- mod_spdy::SpdyStream stream(
- spdy_version_, stream_id, associated_stream_id,
- initial_server_push_depth, priority, net::kSpdyStreamInitialWindowSize,
- &output_queue_, &shared_window_, &pusher_);
- mod_spdy::ServerPushFilter server_push_filter(&stream, request_, &server_cfg);
-
- net::SpdyHeaderBlock headers1;
- headers1[mod_spdy::spdy::kSpdy3Host] = "www.example.com";
- headers1[mod_spdy::spdy::kSpdy3Method] = "GET";
- headers1[mod_spdy::spdy::kSpdy3Path] = "/foo/bar.css?q=12";
- headers1[mod_spdy::spdy::kSpdy3Scheme] = "https";
- headers1[mod_spdy::spdy::kSpdy3Version] = "HTTP/1.1";
- headers1[mod_spdy::http::kReferer] = kRefererUrl;
- EXPECT_CALL(pusher_, StartServerPush(
- Eq(stream_id), Eq(initial_server_push_depth + 1), Eq(2u), Eq(headers1)));
-
- net::SpdyHeaderBlock headers2;
- headers2[mod_spdy::spdy::kSpdy3Host] = "cdn.example.com:8080";
- headers2[mod_spdy::spdy::kSpdy3Method] = "GET";
- headers2[mod_spdy::spdy::kSpdy3Path] = "/images/foo.png";
- headers2[mod_spdy::spdy::kSpdy3Scheme] = "https";
- headers2[mod_spdy::spdy::kSpdy3Version] = "HTTP/1.1";
- headers2[mod_spdy::http::kReferer] = kRefererUrl;
- EXPECT_CALL(pusher_, StartServerPush(
- Eq(stream_id), Eq(initial_server_push_depth + 1), Eq(7u), Eq(headers2)));
-
- net::SpdyHeaderBlock headers3;
- headers3[mod_spdy::spdy::kSpdy3Host] = "www.example.com";
- headers3[mod_spdy::spdy::kSpdy3Method] = "GET";
- headers3[mod_spdy::spdy::kSpdy3Path] = "/scripts/awesome.js";
- headers3[mod_spdy::spdy::kSpdy3Scheme] = "https";
- headers3[mod_spdy::spdy::kSpdy3Version] = "HTTP/1.1";
- headers3[mod_spdy::http::kReferer] = kRefererUrl;
- EXPECT_CALL(pusher_, StartServerPush(
- Eq(stream_id), Eq(initial_server_push_depth + 1), Eq(0u), Eq(headers3)));
-
- apr_table_setn(request_->headers_out, mod_spdy::http::kXAssociatedContent,
- "\"https://www.example.com/foo/bar.css?q=12\":2,"
- "\"https://cdn.example.com:8080/images/foo.png\","
- "\"/scripts/awesome.js\":0");
- WriteBrigade(&server_push_filter);
- // The X-Associated-Content header should get removed.
- EXPECT_TRUE(apr_table_get(request_->headers_out,
- mod_spdy::http::kXAssociatedContent) == NULL);
-}
-
-// Test that if there are multiple X-Associated-Content headers in the APR
-// table, we heed (and then remove) all of them.
-TEST_P(ServerPushFilterTest, MultipleXAssociatedContentHeaders) {
- const net::SpdyStreamId stream_id = 13;
- const net::SpdyStreamId associated_stream_id = 0;
- const int32 initial_server_push_depth = 0;
- const net::SpdyPriority priority = 1;
- const mod_spdy::SpdyServerConfig server_cfg;
- mod_spdy::SpdyStream stream(
- spdy_version_, stream_id, associated_stream_id,
- initial_server_push_depth, priority, net::kSpdyStreamInitialWindowSize,
- &output_queue_, &shared_window_, &pusher_);
- mod_spdy::ServerPushFilter server_push_filter(&stream, request_, &server_cfg);
- const net::SpdyPriority lowest =
- mod_spdy::LowestSpdyPriorityForVersion(stream.spdy_version());
-
- testing::Sequence s1, s2, s3, s4, s5;
-
- EXPECT_CALL(pusher_, StartServerPush(
- Eq(stream_id), Eq(initial_server_push_depth + 1), Eq(2u),
- Contains(Pair(mod_spdy::spdy::kSpdy3Path, "/x1.png")))).InSequence(s1);
- EXPECT_CALL(pusher_, StartServerPush(
- Eq(stream_id), Eq(initial_server_push_depth + 1), Eq(0u),
- Contains(Pair(mod_spdy::spdy::kSpdy3Path, "/x2.png")))).InSequence(s1);
-
- EXPECT_CALL(pusher_, StartServerPush(
- Eq(stream_id), Eq(initial_server_push_depth + 1), Eq(lowest),
- Contains(Pair(mod_spdy::spdy::kSpdy3Path, "/x3.png")))).InSequence(s2);
-
- EXPECT_CALL(pusher_, StartServerPush(
- Eq(stream_id), Eq(initial_server_push_depth + 1), Eq(3u),
- Contains(Pair(mod_spdy::spdy::kSpdy3Path, "/x4.png")))).InSequence(s3);
- EXPECT_CALL(pusher_, StartServerPush(
- Eq(stream_id), Eq(initial_server_push_depth + 1), Eq(lowest),
- Contains(Pair(mod_spdy::spdy::kSpdy3Path, "/x5.png")))).InSequence(s3);
- EXPECT_CALL(pusher_, StartServerPush(
- Eq(stream_id), Eq(initial_server_push_depth + 1), Eq(1u),
- Contains(Pair(mod_spdy::spdy::kSpdy3Path, "/x6.png")))).InSequence(s3);
-
- EXPECT_CALL(pusher_, StartServerPush(
- Eq(stream_id), Eq(initial_server_push_depth + 1), Eq(2u),
- Contains(Pair(mod_spdy::spdy::kSpdy3Path, "/x7.png")))).InSequence(s4);
-
- EXPECT_CALL(pusher_, StartServerPush(
- Eq(stream_id), Eq(initial_server_push_depth + 1), Eq(lowest),
- Contains(Pair(mod_spdy::spdy::kSpdy3Path, "/x8.png")))).InSequence(s5);
-
- // Add multiple X-Associated-Content headers to both headers_out and
- // err_headers_out.
- apr_table_addn(request_->headers_out, mod_spdy::http::kXAssociatedContent,
- "\"/x1.png\":2, \"/x2.png\":0");
- apr_table_addn(request_->headers_out, mod_spdy::http::kXAssociatedContent,
- "\"/x3.png\"");
- apr_table_addn(request_->headers_out, mod_spdy::http::kXAssociatedContent,
- "\"/x4.png\":3, \"/x5.png\", \"/x6.png\":1");
- apr_table_addn(request_->err_headers_out, mod_spdy::http::kXAssociatedContent,
- "\"/x7.png\" : 2");
- apr_table_addn(request_->err_headers_out, mod_spdy::http::kXAssociatedContent,
- "\"/x8.png\"");
-
- WriteBrigade(&server_push_filter);
- // All the X-Associated-Content headers should get removed.
- EXPECT_TRUE(apr_table_get(request_->headers_out,
- mod_spdy::http::kXAssociatedContent) == NULL);
- EXPECT_TRUE(apr_table_get(request_->err_headers_out,
- mod_spdy::http::kXAssociatedContent) == NULL);
-}
-
-// Test that header key matching is case-insensitive.
-TEST_P(ServerPushFilterTest, CaseInsensitive) {
- const net::SpdyStreamId stream_id = 13;
- const net::SpdyStreamId associated_stream_id = 0;
- const int32 initial_server_push_depth = 0;
- const net::SpdyPriority priority = 1;
- const mod_spdy::SpdyServerConfig server_cfg;
- mod_spdy::SpdyStream stream(
- spdy_version_, stream_id, associated_stream_id,
- initial_server_push_depth, priority, net::kSpdyStreamInitialWindowSize,
- &output_queue_, &shared_window_, &pusher_);
- mod_spdy::ServerPushFilter server_push_filter(&stream, request_, &server_cfg);
-
- EXPECT_CALL(pusher_, StartServerPush(Eq(stream_id), _, _, Contains(
- Pair(mod_spdy::spdy::kSpdy3Path, "/x1.png"))));
- EXPECT_CALL(pusher_, StartServerPush(Eq(stream_id), _, _, Contains(
- Pair(mod_spdy::spdy::kSpdy3Path, "/x2.png"))));
- EXPECT_CALL(pusher_, StartServerPush(Eq(stream_id), _, _, Contains(
- Pair(mod_spdy::spdy::kSpdy3Path, "/x3.png"))));
-
- apr_table_addn(request_->headers_out, "X-Associated-Content", "\"/x1.png\"");
- apr_table_addn(request_->headers_out, "X-ASSOCIATED-CONTENT", "\"/x2.png\"");
- apr_table_addn(request_->headers_out, "x-AsSoCiAtEd-cOnTeNt", "\"/x3.png\"");
-
- WriteBrigade(&server_push_filter);
- // All three X-Associated-Content headers should get removed, despite their
- // weird capitalization. (Note that apr_table_get is itself
- // case-insensitive, but we explicitly check all the variations here anyway,
- // just to be sure.)
- EXPECT_TRUE(apr_table_get(request_->headers_out,
- mod_spdy::http::kXAssociatedContent) == NULL);
- EXPECT_TRUE(apr_table_get(request_->headers_out,
- "X-Associated-Content") == NULL);
- EXPECT_TRUE(apr_table_get(request_->headers_out,
- "X-ASSOCIATED-CONTENT") == NULL);
- EXPECT_TRUE(apr_table_get(request_->headers_out,
- "x-AsSoCiAtEd-cOnTeNt") == NULL);
-}
-
-TEST_P(ServerPushFilterTest, CopyApplicableHeaders) {
- const net::SpdyStreamId stream_id = 7;
- const net::SpdyStreamId associated_stream_id = 0;
- const int32 initial_server_push_depth = 0;
- const net::SpdyPriority priority = 0;
- const mod_spdy::SpdyServerConfig server_cfg;
- mod_spdy::SpdyStream stream(
- spdy_version_, stream_id, associated_stream_id,
- initial_server_push_depth, priority, net::kSpdyStreamInitialWindowSize,
- &output_queue_, &shared_window_, &pusher_);
- mod_spdy::ServerPushFilter server_push_filter(&stream, request_, &server_cfg);
-
- // Set some extra headers on the original request (which was evidentally a
- // POST). The Accept-Language header should get copied over for the push,
- // but the Content-Length header obviously should not.
- apr_table_setn(request_->headers_in, "accept-language", "en-US");
- apr_table_setn(request_->headers_in, "content-length", "200");
-
- net::SpdyHeaderBlock headers1;
- headers1[mod_spdy::spdy::kSpdy3Host] = "www.example.com";
- headers1[mod_spdy::spdy::kSpdy3Method] = "GET";
- headers1[mod_spdy::spdy::kSpdy3Path] = "/foo/bar.css";
- headers1[mod_spdy::spdy::kSpdy3Scheme] = "https";
- headers1[mod_spdy::spdy::kSpdy3Version] = "HTTP/1.1";
- headers1[mod_spdy::http::kReferer] = kRefererUrl;
- headers1["accept-language"] = "en-US";
- EXPECT_CALL(pusher_, StartServerPush(
- Eq(stream_id), Eq(initial_server_push_depth + 1), Eq(2u), Eq(headers1)));
-
- apr_table_setn(request_->headers_out, mod_spdy::http::kXAssociatedContent,
- " \"https://www.example.com/foo/bar.css\" : 2 ");
- WriteBrigade(&server_push_filter);
-}
-
-TEST_P(ServerPushFilterTest, StopPushingAfterPushError) {
- const net::SpdyStreamId stream_id = 3;
- const net::SpdyStreamId associated_stream_id = 0;
- const int32 initial_server_push_depth = 0;
- const net::SpdyPriority priority = 1;
- const mod_spdy::SpdyServerConfig server_cfg;
- mod_spdy::SpdyStream stream(
- spdy_version_, stream_id, associated_stream_id,
- initial_server_push_depth, priority, net::kSpdyStreamInitialWindowSize,
- &output_queue_, &shared_window_, &pusher_);
- mod_spdy::ServerPushFilter server_push_filter(&stream, request_, &server_cfg);
-
- // When the filter tries to push the first resource, we reply that pushes are
- // no longer possible on this connection. The filter should not attempt any
- // more pushes, even though more were specified.
- EXPECT_CALL(pusher_, StartServerPush(
- Eq(stream_id),
- Eq(initial_server_push_depth + 1),
- Eq(2u), _)).WillOnce(
- Return(mod_spdy::SpdyServerPushInterface::CANNOT_PUSH_EVER_AGAIN));
-
- apr_table_setn(request_->headers_out, mod_spdy::http::kXAssociatedContent,
- "\"https://www.example.com/foo/bar.css?q=12\":2,"
- "\"cdn.example.com:8080/images/foo.png\","
- "\"/scripts/awesome.js\":0");
- WriteBrigade(&server_push_filter);
- // The X-Associated-Content header should still get removed, though.
- EXPECT_TRUE(apr_table_get(request_->headers_out,
- mod_spdy::http::kXAssociatedContent) == NULL);
-}
-
-TEST_P(ServerPushFilterTest, StopPushingAfterParseError) {
- const net::SpdyStreamId stream_id = 3;
- const net::SpdyStreamId associated_stream_id = 0;
- const int32 initial_server_push_depth = 0;
- const net::SpdyPriority priority = 1;
- const mod_spdy::SpdyServerConfig server_cfg;
- mod_spdy::SpdyStream stream(
- spdy_version_, stream_id, associated_stream_id,
- initial_server_push_depth, priority, net::kSpdyStreamInitialWindowSize,
- &output_queue_, &shared_window_, &pusher_);
- mod_spdy::ServerPushFilter server_push_filter(&stream, request_, &server_cfg);
-
- // The filter should push the first resource, but then stop when it gets to
- // the parse error.
- EXPECT_CALL(pusher_, StartServerPush(
- Eq(stream_id), Eq(initial_server_push_depth + 1), Eq(2u), _));
-
- apr_table_setn(request_->headers_out, mod_spdy::http::kXAssociatedContent,
- "\"https://www.example.com/foo/bar.css?q=12\":2,"
- "oops.iforgot.to/quote/this/url.js,"
- "\"/scripts/awesome.js\":0");
- WriteBrigade(&server_push_filter);
- // The X-Associated-Content header should still get removed, though.
- EXPECT_TRUE(apr_table_get(request_->headers_out,
- mod_spdy::http::kXAssociatedContent) == NULL);
-}
-
-TEST_P(ServerPushFilterTest, SkipInvalidQuotedUrl) {
- const net::SpdyStreamId stream_id = 3;
- const net::SpdyStreamId associated_stream_id = 0;
- const int32 initial_server_push_depth = 0;
- const net::SpdyPriority priority = 1;
- const mod_spdy::SpdyServerConfig server_cfg;
- mod_spdy::SpdyStream stream(
- spdy_version_, stream_id, associated_stream_id,
- initial_server_push_depth, priority, net::kSpdyStreamInitialWindowSize,
- &output_queue_, &shared_window_, &pusher_);
- mod_spdy::ServerPushFilter server_push_filter(&stream, request_, &server_cfg);
-
- // The filter should push the first and third resources, but skip the second
- // one because its quoted URL is invalid.
- EXPECT_CALL(pusher_, StartServerPush(
- Eq(stream_id), Eq(initial_server_push_depth + 1), Eq(2u), _));
- EXPECT_CALL(pusher_, StartServerPush(
- Eq(stream_id), Eq(initial_server_push_depth + 1), Eq(0u), _));
-
- apr_table_setn(request_->headers_out, mod_spdy::http::kXAssociatedContent,
- " \"https://www.example.com/foo/bar.css?q=12\" : 2, "
- "\"https://this.is:not/a valid URL!\":1, "
- "\"/scripts/awesome.js\":0 ");
- WriteBrigade(&server_push_filter);
- // The X-Associated-Content header should still get removed, though.
- EXPECT_TRUE(apr_table_get(request_->headers_out,
- mod_spdy::http::kXAssociatedContent) == NULL);
-}
-
-TEST_P(ServerPushFilterTest, MaxServerPushDepthLimit) {
- const net::SpdyStreamId stream_id = 2;
- const net::SpdyStreamId associated_stream_id = 5;
- const int32 initial_server_push_depth = 0;
- const net::SpdyPriority priority = 1;
- mod_spdy::SpdyServerConfig server_cfg;
-
- server_cfg.set_max_server_push_depth(0);
- mod_spdy::SpdyStream stream(
- spdy_version_, stream_id, associated_stream_id,
- initial_server_push_depth, priority, net::kSpdyStreamInitialWindowSize,
- &output_queue_, &shared_window_, &pusher_);
- mod_spdy::ServerPushFilter server_push_filter(&stream, request_, &server_cfg);
-
- // We should not get any calls to StartServerPush, because we do not allow
- // server-pushed resources to push any more resources.
- EXPECT_CALL(pusher_, StartServerPush(_,_,_,_)).Times(0);
-
- apr_table_setn(request_->headers_out, mod_spdy::http::kXAssociatedContent,
- "\"https://www.example.com/foo/bar.css?q=12\":2,"
- "\"cdn.example.com:8080/images/foo.png\","
- "\"/scripts/awesome.js\":0");
- WriteBrigade(&server_push_filter);
- // The X-Associated-Content header should still get removed, though.
- EXPECT_TRUE(apr_table_get(request_->headers_out,
- mod_spdy::http::kXAssociatedContent) == NULL);
-
-
- // Now increase our max_server_push_depth, but also our
- // initial_server_push_depth. We expect the same result.
- const int32 initial_server_push_depth_2 = 5;
- mod_spdy::SpdyServerConfig server_cfg_2;
- server_cfg.set_max_server_push_depth(5);
- mod_spdy::SpdyStream stream_2(
- spdy_version_, stream_id, associated_stream_id,
- initial_server_push_depth_2, priority, net::kSpdyStreamInitialWindowSize,
- &output_queue_, &shared_window_, &pusher_);
- mod_spdy::ServerPushFilter server_push_filter_2(
- &stream_2, request_, &server_cfg_2);
-
- // We should not get any calls to StartServerPush, because we do not allow
- // server-pushed resources to push any more resources.
- EXPECT_CALL(pusher_, StartServerPush(_,_,_,_)).Times(0);
-
- apr_table_setn(request_->headers_out, mod_spdy::http::kXAssociatedContent,
- "\"https://www.example.com/foo/bar.css?q=12\":2,"
- "\"cdn.example.com:8080/images/foo.png\","
- "\"/scripts/awesome.js\":0");
- WriteBrigade(&server_push_filter_2);
- // The X-Associated-mContent header should still get removed, though.
- EXPECT_TRUE(apr_table_get(request_->headers_out,
- mod_spdy::http::kXAssociatedContent) == NULL);
-}
-
-// Run server push tests only over SPDY v3.
-INSTANTIATE_TEST_CASE_P(Spdy3, ServerPushFilterTest, testing::Values(
- mod_spdy::spdy::SPDY_VERSION_3, mod_spdy::spdy::SPDY_VERSION_3_1));
-
-// Create a type alias so that we can instantiate some of our
-// SpdySessionTest-based tests using a different set of parameters.
-typedef ServerPushFilterTest ServerPushFilterSpdy2Test;
-
-TEST_P(ServerPushFilterSpdy2Test, NoPushesForSpdy2) {
- const net::SpdyStreamId stream_id = 3;
- const net::SpdyStreamId associated_stream_id = 0;
- const int32 initial_server_push_depth = 0;
- const net::SpdyPriority priority = 1;
- const mod_spdy::SpdyServerConfig server_cfg;
- mod_spdy::SpdyStream stream(
- spdy_version_, stream_id, associated_stream_id,
- initial_server_push_depth, priority, net::kSpdyStreamInitialWindowSize,
- &output_queue_, &shared_window_, &pusher_);
- mod_spdy::ServerPushFilter server_push_filter(&stream, request_, &server_cfg);
-
- // We should not get any calls to StartServerPush when we're on SPDY/2.
-
- apr_table_setn(request_->headers_out, mod_spdy::http::kXAssociatedContent,
- "\"https://www.example.com/foo/bar.css?q=12\":2,"
- "\"cdn.example.com:8080/images/foo.png\","
- "\"/scripts/awesome.js\":0");
- WriteBrigade(&server_push_filter);
- // The X-Associated-Content header should still get removed, though.
- EXPECT_TRUE(apr_table_get(request_->headers_out,
- mod_spdy::http::kXAssociatedContent) == NULL);
-}
-
-INSTANTIATE_TEST_CASE_P(Spdy2, ServerPushFilterSpdy2Test, testing::Values(
- mod_spdy::spdy::SPDY_VERSION_2));
-
-} // namespace
+++ /dev/null
-// 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.
-
-#include "mod_spdy/apache/filters/spdy_to_http_filter.h"
-
-#include <map>
-#include <string>
-
-#include "base/logging.h"
-#include "base/memory/scoped_ptr.h"
-#include "base/strings/string_piece.h"
-#include "base/strings/stringprintf.h"
-#include "mod_spdy/common/spdy_stream.h"
-#include "mod_spdy/common/spdy_to_http_converter.h"
-#include "net/spdy/spdy_frame_builder.h"
-#include "net/spdy/spdy_framer.h"
-#include "net/spdy/spdy_protocol.h"
-
-namespace {
-
-// If, during an AP_MODE_GETLINE read, we pull in this much data (or more)
-// without seeing a linebreak, just give up and return what we have.
-const size_t kGetlineThreshold = 4096;
-
-} // namespace
-
-namespace mod_spdy {
-
-SpdyToHttpFilter::SpdyToHttpFilter(SpdyStream* stream)
- : stream_(stream),
- visitor_(&data_buffer_),
- converter_(stream_->spdy_version(), &visitor_),
- next_read_start_(0) {
- DCHECK(stream_ != NULL);
-}
-
-SpdyToHttpFilter::~SpdyToHttpFilter() {}
-
-// Macro to check if the SPDY stream has been aborted; if so, mark the
-// connection object as having been aborted and return APR_ECONNABORTED.
-// Hopefully, this will convince Apache to shut down processing for this
-// (slave) connection, thus allowing this stream's thread to complete and exit.
-//
-// As an extra measure, we also insert an EOS bucket into the brigade before
-// returning. This idea comes from ssl_io_filter_input() in ssl_engine_io.c in
-// mod_ssl, which does so with the following comment: "Ok, if we aborted, we
-// ARE at the EOS. We also have aborted. This 'double protection' is probably
-// redundant, but also effective against just about anything."
-#define RETURN_IF_STREAM_ABORT(filter, brigade) \
- do { \
- if ((filter)->c->aborted || stream_->is_aborted()) { \
- (filter)->c->aborted = true; \
- APR_BRIGADE_INSERT_TAIL( \
- (brigade), apr_bucket_eos_create((filter)->c->bucket_alloc)); \
- return APR_ECONNABORTED; \
- } \
- } while (false)
-
-apr_status_t SpdyToHttpFilter::Read(ap_filter_t *filter,
- apr_bucket_brigade *brigade,
- ap_input_mode_t mode,
- apr_read_type_e block,
- apr_off_t readbytes) {
- // Turn readbytes into a size_t to avoid the need for static_casts below. To
- // avoid any surprises (in cases where apr_off_t is signed), clamp it to a
- // non-negative value first.
- const size_t max_bytes = std::max(static_cast<apr_off_t>(0), readbytes);
-
- // This is a NETWORK-level filter, so there shouldn't be any filter after us.
- if (filter->next != NULL) {
- LOG(WARNING) << "SpdyToHttpFilter is not the last filter in the chain "
- << "(it is followed by " << filter->next->frec->name << ")";
- }
-
- // Clear any buffer data that was already returned on a previous invocation
- // of this filter.
- if (next_read_start_ > 0) {
- data_buffer_.erase(0, next_read_start_);
- next_read_start_ = 0;
- }
-
- // We don't need to do anything for AP_MODE_INIT. (We check this case before
- // checking for EOF, becuase that's what ap_core_input_filter() in
- // core_filters.c does.)
- if (mode == AP_MODE_INIT) {
- return APR_SUCCESS;
- }
-
- // If there will never be any more data on this stream, return EOF. (That's
- // what ap_core_input_filter() in core_filters.c does.)
- if (end_of_stream_reached() && data_buffer_.empty()) {
- return APR_EOF;
- }
-
- // Check if this SPDY stream has been aborted, and if so, quit. We will also
- // check for aborts just after each time we call GetNextFrame (that's a good
- // time to check, since a stream abort can interrupt a blocking call to
- // GetNextFrame).
- RETURN_IF_STREAM_ABORT(filter, brigade);
-
- // Keep track of how much data, if any, we should place into the brigade.
- size_t bytes_read = 0;
-
- // For AP_MODE_READBYTES and AP_MODE_SPECULATIVE, we try to read the quantity
- // of bytes we are asked for. For AP_MODE_EXHAUSTIVE, we read as much as
- // possible.
- if (mode == AP_MODE_READBYTES || mode == AP_MODE_SPECULATIVE ||
- mode == AP_MODE_EXHAUSTIVE) {
- // Try to get as much data as we were asked for.
- while (max_bytes > data_buffer_.size() || mode == AP_MODE_EXHAUSTIVE) {
- const bool got_frame = GetNextFrame(block);
- RETURN_IF_STREAM_ABORT(filter, brigade);
- if (!got_frame) {
- break;
- }
- }
-
- // Return however much data we read, but no more than they asked for.
- bytes_read = data_buffer_.size();
- if (mode != AP_MODE_EXHAUSTIVE && max_bytes < bytes_read) {
- bytes_read = max_bytes;
- }
- }
- // For AP_MODE_GETLINE, try to return a full text line of data.
- else if (mode == AP_MODE_GETLINE) {
- // Try to find the first linebreak in the remaining data stream.
- size_t linebreak = std::string::npos;
- size_t start = 0;
- while (true) {
- linebreak = data_buffer_.find('\n', start);
- // Stop if we find a linebreak, or if we've pulled too much data already.
- if (linebreak != std::string::npos ||
- data_buffer_.size() >= kGetlineThreshold) {
- break;
- }
- // Remember where we left off so we don't have to re-scan the whole
- // buffer on the next iteration.
- start = data_buffer_.size();
- // We haven't seen a linebreak yet, so try to get more data.
- const bool got_frame = GetNextFrame(block);
- RETURN_IF_STREAM_ABORT(filter, brigade);
- if (!got_frame) {
- break;
- }
- }
-
- // If we found a linebreak, return data up to and including that linebreak.
- // Otherwise, just send whatever we were able to get.
- bytes_read = (linebreak == std::string::npos ?
- data_buffer_.size() : linebreak + 1);
- }
- // We don't support AP_MODE_EATCRLF. Doing so would be tricky, and probably
- // totally pointless. But if we ever decide to implement it, see
- // http://mail-archives.apache.org/mod_mbox/httpd-dev/200504.mbox/%3C1e86e5df78f13fcc9af02b3f5d749b33@ricilake.net%3E
- // for more information on its subtle semantics.
- else {
- DCHECK(mode == AP_MODE_EATCRLF);
- VLOG(2) << "Unsupported read mode (" << mode << ") on stream "
- << stream_->stream_id();
- return APR_ENOTIMPL;
- }
-
- // Keep track of whether we were able to put any buckets into the brigade.
- bool success = false;
-
- // If we managed to read any data, put it into the brigade. We use a
- // transient bucket (as opposed to a heap bucket) to avoid an extra string
- // copy.
- if (bytes_read > 0) {
- APR_BRIGADE_INSERT_TAIL(brigade, apr_bucket_transient_create(
- data_buffer_.data(), bytes_read, brigade->bucket_alloc));
- success = true;
- }
-
- // If this is the last bit of data from this stream, send an EOS bucket.
- if (end_of_stream_reached() && bytes_read == data_buffer_.size()) {
- APR_BRIGADE_INSERT_TAIL(brigade, apr_bucket_eos_create(
- brigade->bucket_alloc));
- success = true;
- }
-
- // If this read failed and this was a non-blocking read, invite the caller to
- // try again.
- if (!success && block == APR_NONBLOCK_READ) {
- return APR_EAGAIN;
- }
-
- // Unless this is a speculative read, we should skip past the bytes we read
- // next time this filter is invoked. We don't want to erase those bytes
- // yet, though, so that we can return them to the previous filter in a
- // transient bucket.
- if (mode != AP_MODE_SPECULATIVE) {
- next_read_start_ = bytes_read;
- }
-
- return APR_SUCCESS;
-}
-
-SpdyToHttpFilter::DecodeFrameVisitor::DecodeFrameVisitor(
- SpdyToHttpFilter* filter)
- : filter_(filter), success_(false) {
- DCHECK(filter_);
-}
-
-void SpdyToHttpFilter::DecodeFrameVisitor::VisitSynStream(
- const net::SpdySynStreamIR& frame) {
- success_ = filter_->DecodeSynStreamFrame(frame);
-}
-void SpdyToHttpFilter::DecodeFrameVisitor::VisitSynReply(
- const net::SpdySynReplyIR& frame) { BadFrameType("SYN_REPLY"); }
-void SpdyToHttpFilter::DecodeFrameVisitor::VisitRstStream(
- const net::SpdyRstStreamIR& frame) { BadFrameType("RST_STREAM"); }
-void SpdyToHttpFilter::DecodeFrameVisitor::VisitSettings(
- const net::SpdySettingsIR& frame) { BadFrameType("SETTINGS"); }
-void SpdyToHttpFilter::DecodeFrameVisitor::VisitPing(
- const net::SpdyPingIR& frame) { BadFrameType("PING"); }
-void SpdyToHttpFilter::DecodeFrameVisitor::VisitGoAway(
- const net::SpdyGoAwayIR& frame) { BadFrameType("GOAWAY"); }
-void SpdyToHttpFilter::DecodeFrameVisitor::VisitHeaders(
- const net::SpdyHeadersIR& frame) {
- success_ = filter_->DecodeHeadersFrame(frame);
-}
-void SpdyToHttpFilter::DecodeFrameVisitor::VisitWindowUpdate(
- const net::SpdyWindowUpdateIR& frame) { BadFrameType("WINDOW_UPDATE"); }
-void SpdyToHttpFilter::DecodeFrameVisitor::VisitCredential(
- const net::SpdyCredentialIR& frame) { BadFrameType("CREDENTIAL"); }
-void SpdyToHttpFilter::DecodeFrameVisitor::VisitBlocked(
- const net::SpdyBlockedIR& frame) { BadFrameType("BLOCKED"); }
-void SpdyToHttpFilter::DecodeFrameVisitor::VisitPushPromise(
- const net::SpdyPushPromiseIR& frame) { BadFrameType("PUSH_PROMISE"); }
-void SpdyToHttpFilter::DecodeFrameVisitor::VisitData(
- const net::SpdyDataIR& frame) {
- success_ = filter_->DecodeDataFrame(frame);
-}
-
-void SpdyToHttpFilter::DecodeFrameVisitor::BadFrameType(
- const char* frame_type) {
- LOG(DFATAL) << "Master connection sent a " << frame_type
- << " frame to stream " << filter_->stream_->stream_id();
- filter_->AbortStream(net::RST_STREAM_INTERNAL_ERROR);
- success_ = false;
-}
-
-bool SpdyToHttpFilter::GetNextFrame(apr_read_type_e block) {
- if (end_of_stream_reached()) {
- return false;
- }
-
- // Try to get the next SPDY frame from the stream.
- scoped_ptr<net::SpdyFrameIR> frame;
- {
- net::SpdyFrameIR* frame_ptr = NULL;
- if (!stream_->GetInputFrame(block == APR_BLOCK_READ, &frame_ptr)) {
- DCHECK(frame_ptr == NULL);
- return false;
- }
- frame.reset(frame_ptr);
- }
- DCHECK(frame.get() != NULL);
-
- // Decode the frame into HTTP and append to the data buffer.
- DecodeFrameVisitor visitor(this);
- frame->Visit(&visitor);
- return visitor.success();
-}
-
-bool SpdyToHttpFilter::DecodeSynStreamFrame(
- const net::SpdySynStreamIR& frame) {
- const SpdyToHttpConverter::Status status =
- converter_.ConvertSynStreamFrame(frame);
- switch (status) {
- case SpdyToHttpConverter::SPDY_CONVERTER_SUCCESS:
- return true;
- case SpdyToHttpConverter::EXTRA_SYN_STREAM:
- // If we get multiple SYN_STREAM frames for a stream, we must abort
- // with PROTOCOL_ERROR (SPDY draft 2 section 2.7.1).
- LOG(ERROR) << "Client sent extra SYN_STREAM frame on stream "
- << stream_->stream_id();
- AbortStream(net::RST_STREAM_PROTOCOL_ERROR);
- return false;
- case SpdyToHttpConverter::INVALID_HEADER_BLOCK:
- LOG(ERROR) << "Invalid SYN_STREAM header block on stream "
- << stream_->stream_id();
- AbortStream(net::RST_STREAM_PROTOCOL_ERROR);
- return false;
- case SpdyToHttpConverter::BAD_REQUEST:
- // TODO(mdsteeele): According to the SPDY spec, we're supposed to return
- // an HTTP 400 (Bad Request) reply in this case (SPDY draft 3 section
- // 3.2.1). We need to do some refactoring to make that possible.
- LOG(ERROR) << "Could not generate request line from SYN_STREAM frame"
- << " in stream " << stream_->stream_id();
- AbortStream(net::RST_STREAM_REFUSED_STREAM);
- return false;
- default:
- // No other outcome should be possible.
- LOG(DFATAL) << "Got " << SpdyToHttpConverter::StatusString(status)
- << " from ConvertSynStreamFrame on stream "
- << stream_->stream_id();
- AbortStream(net::RST_STREAM_INTERNAL_ERROR);
- return false;
- }
-}
-
-bool SpdyToHttpFilter::DecodeHeadersFrame(const net::SpdyHeadersIR& frame) {
- const SpdyToHttpConverter::Status status =
- converter_.ConvertHeadersFrame(frame);
- switch (status) {
- case SpdyToHttpConverter::SPDY_CONVERTER_SUCCESS:
- return true;
- case SpdyToHttpConverter::FRAME_AFTER_FIN:
- AbortStream(net::RST_STREAM_INVALID_STREAM);
- return false;
- case SpdyToHttpConverter::INVALID_HEADER_BLOCK:
- LOG(ERROR) << "Invalid HEADERS header block on stream "
- << stream_->stream_id();
- AbortStream(net::RST_STREAM_PROTOCOL_ERROR);
- return false;
- default:
- // No other outcome should be possible.
- LOG(DFATAL) << "Got " << SpdyToHttpConverter::StatusString(status)
- << " from ConvertHeadersFrame on stream "
- << stream_->stream_id();
- AbortStream(net::RST_STREAM_INTERNAL_ERROR);
- return false;
- }
-}
-
-bool SpdyToHttpFilter::DecodeDataFrame(const net::SpdyDataIR& frame) {
- const SpdyToHttpConverter::Status status =
- converter_.ConvertDataFrame(frame);
- switch (status) {
- case SpdyToHttpConverter::SPDY_CONVERTER_SUCCESS:
- // TODO(mdsteele): This isn't really the ideal place for this -- we
- // shouldn't send the WINDOW_UPDATE until we're about to return the
- // data to the previous filter, so that we're aren't buffering an
- // unbounded amount of data in this filter. The trouble is that once
- // we convert the frames, everything goes into data_buffer_ and we
- // forget which of it is leading/trailing headers and which of it is
- // request data, so it'll take a little work to know when to send the
- // WINDOW_UPDATE frames. For now, just doing it here is good enough.
- stream_->OnInputDataConsumed(frame.data().size());
- return true;
- case SpdyToHttpConverter::FRAME_AFTER_FIN:
- // If the stream is no longer open, we must send a RST_STREAM with
- // INVALID_STREAM (SPDY draft 3 section 2.2.2).
- AbortStream(net::RST_STREAM_INVALID_STREAM);
- return false;
- default:
- // No other outcome should be possible.
- LOG(DFATAL) << "Got " << SpdyToHttpConverter::StatusString(status)
- << " from ConvertDataFrame on stream "
- << stream_->stream_id();
- AbortStream(net::RST_STREAM_INTERNAL_ERROR);
- return false;
- }
-}
-
-void SpdyToHttpFilter::AbortStream(net::SpdyRstStreamStatus status) {
- stream_->AbortWithRstStream(status);
-}
-
-} // namespace mod_spdy
+++ /dev/null
-// 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.
-
-#ifndef MOD_SPDY_APACHE_FILTERS_SPDY_TO_HTTP_FILTER_H_
-#define MOD_SPDY_APACHE_FILTERS_SPDY_TO_HTTP_FILTER_H_
-
-#include <string>
-
-#include "apr_buckets.h"
-#include "util_filter.h"
-
-#include "base/basictypes.h"
-#include "mod_spdy/common/http_string_builder.h"
-#include "mod_spdy/common/spdy_to_http_converter.h"
-#include "net/spdy/spdy_protocol.h"
-
-namespace mod_spdy {
-
-class SpdyStream;
-
-// An Apache filter for pulling SPDY frames (for a single SPDY stream) from the
-// input queue of a SpdyStream object and converting them into equivalent HTTP
-// data to be processed by Apache. This is intended to be the outermost filter
-// in the input chain of one of our slave connections, essentially taking the
-// place of the network socket.
-class SpdyToHttpFilter {
- public:
- explicit SpdyToHttpFilter(SpdyStream* stream);
- ~SpdyToHttpFilter();
-
- apr_status_t Read(ap_filter_t* filter,
- apr_bucket_brigade* brigade,
- ap_input_mode_t mode,
- apr_read_type_e block,
- apr_off_t readbytes);
-
- private:
- friend class DecodeFrameVisitor;
- class DecodeFrameVisitor : public net::SpdyFrameVisitor {
- public:
- explicit DecodeFrameVisitor(SpdyToHttpFilter* filter);
- virtual ~DecodeFrameVisitor() {}
-
- bool success() { return success_; }
-
- virtual void VisitSynStream(const net::SpdySynStreamIR& frame);
- virtual void VisitSynReply(const net::SpdySynReplyIR& frame);
- virtual void VisitRstStream(const net::SpdyRstStreamIR& frame);
- virtual void VisitSettings(const net::SpdySettingsIR& frame);
- virtual void VisitPing(const net::SpdyPingIR& frame);
- virtual void VisitGoAway(const net::SpdyGoAwayIR& frame);
- virtual void VisitHeaders(const net::SpdyHeadersIR& frame);
- virtual void VisitWindowUpdate(const net::SpdyWindowUpdateIR& frame);
- virtual void VisitCredential(const net::SpdyCredentialIR& frame);
- virtual void VisitBlocked(const net::SpdyBlockedIR& frame);
- virtual void VisitPushPromise(const net::SpdyPushPromiseIR& frame);
- virtual void VisitData(const net::SpdyDataIR& frame);
-
- private:
- void BadFrameType(const char* frame_type);
-
- SpdyToHttpFilter* filter_;
- bool success_;
-
- DISALLOW_COPY_AND_ASSIGN(DecodeFrameVisitor);
- };
-
- // Return true if we've received a FLAG_FIN (i.e. EOS has been reached).
- bool end_of_stream_reached() const { return visitor_.is_complete(); }
-
- // Try to get the next SPDY frame on this stream, convert it into HTTP, and
- // append the resulting data to data_buffer_. If the block argument is
- // APR_BLOCK_READ, this function will block until a frame comes in (or the
- // stream is closed).
- bool GetNextFrame(apr_read_type_e block);
-
- // Pass the given frame to the SpdyToHttpConverter, and deal with the return
- // code appropriately.
- bool DecodeSynStreamFrame(const net::SpdySynStreamIR& frame);
- bool DecodeHeadersFrame(const net::SpdyHeadersIR& frame);
- bool DecodeDataFrame(const net::SpdyDataIR& frame);
-
- // Send a RST_STREAM frame and abort the stream.
- void AbortStream(net::SpdyRstStreamStatus status);
-
- SpdyStream* const stream_;
- std::string data_buffer_;
- HttpStringBuilder visitor_;
- SpdyToHttpConverter converter_;
- size_t next_read_start_;
-
- DISALLOW_COPY_AND_ASSIGN(SpdyToHttpFilter);
-};
-
-} // namespace mod_spdy
-
-#endif // MOD_SPDY_APACHE_FILTERS_SPDY_TO_HTTP_FILTER_H_
+++ /dev/null
-// 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.
-
-#include "mod_spdy/apache/filters/spdy_to_http_filter.h"
-
-#include <string>
-
-#include "httpd.h"
-#include "apr_buckets.h"
-#include "apr_tables.h"
-#include "util_filter.h"
-
-#include "base/memory/scoped_ptr.h"
-#include "base/strings/string_piece.h"
-#include "mod_spdy/apache/pool_util.h"
-#include "mod_spdy/common/protocol_util.h"
-#include "mod_spdy/common/shared_flow_control_window.h"
-#include "mod_spdy/common/spdy_frame_priority_queue.h"
-#include "mod_spdy/common/spdy_stream.h"
-#include "mod_spdy/common/testing/spdy_frame_matchers.h"
-#include "net/spdy/spdy_protocol.h"
-#include "testing/gmock/include/gmock/gmock.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace {
-
-class MockSpdyServerPushInterface : public mod_spdy::SpdyServerPushInterface {
- public:
- MOCK_METHOD4(StartServerPush,
- mod_spdy::SpdyServerPushInterface::PushStatus(
- net::SpdyStreamId associated_stream_id,
- int32 server_push_depth,
- net::SpdyPriority priority,
- const net::SpdyNameValueBlock& request_headers));
-};
-
-class SpdyToHttpFilterTest :
- public testing::TestWithParam<mod_spdy::spdy::SpdyVersion> {
- public:
- SpdyToHttpFilterTest()
- : spdy_version_(GetParam()),
- stream_id_(1),
- priority_(0u),
- shared_window_(net::kSpdyStreamInitialWindowSize,
- net::kSpdyStreamInitialWindowSize),
- stream_(spdy_version_, stream_id_, 0, 0, priority_,
- net::kSpdyStreamInitialWindowSize, &output_queue_,
- &shared_window_, &pusher_),
- spdy_to_http_filter_(&stream_) {
- bucket_alloc_ = apr_bucket_alloc_create(local_.pool());
- connection_ = static_cast<conn_rec*>(
- apr_pcalloc(local_.pool(), sizeof(conn_rec)));
- connection_->pool = local_.pool();
- connection_->bucket_alloc = bucket_alloc_;
- ap_filter_ = static_cast<ap_filter_t*>(
- apr_pcalloc(local_.pool(), sizeof(ap_filter_t)));
- ap_filter_->c = connection_;
- brigade_ = apr_brigade_create(local_.pool(), bucket_alloc_);
- }
-
- protected:
- void PostSynStreamFrame(bool fin, const net::SpdyNameValueBlock& headers) {
- scoped_ptr<net::SpdySynStreamIR> frame(
- new net::SpdySynStreamIR(stream_id_));
- frame->set_priority(priority_);
- frame->set_fin(fin);
- frame->GetMutableNameValueBlock()->insert(headers.begin(), headers.end());
- stream_.PostInputFrame(frame.release());
- }
-
- void PostHeadersFrame(bool fin, const net::SpdyNameValueBlock& headers) {
- scoped_ptr<net::SpdyHeadersIR> frame(new net::SpdyHeadersIR(stream_id_));
- frame->set_fin(fin);
- frame->GetMutableNameValueBlock()->insert(headers.begin(), headers.end());
- stream_.PostInputFrame(frame.release());
- }
-
- void PostDataFrame(bool fin, const base::StringPiece& payload) {
- scoped_ptr<net::SpdyDataIR> frame(
- new net::SpdyDataIR(stream_id_, payload));
- frame->set_fin(fin);
- EXPECT_TRUE(shared_window_.OnReceiveInputData(payload.size()));
- stream_.PostInputFrame(frame.release());
- }
-
- apr_status_t Read(ap_input_mode_t mode, apr_read_type_e block,
- apr_off_t readbytes) {
- return spdy_to_http_filter_.Read(ap_filter_, brigade_,
- mode, block, readbytes);
- }
-
- void ExpectTransientBucket(const std::string& expected) {
- ASSERT_FALSE(APR_BRIGADE_EMPTY(brigade_))
- << "Expected TRANSIENT bucket, but brigade is empty.";
- apr_bucket* bucket = APR_BRIGADE_FIRST(brigade_);
- ASSERT_TRUE(APR_BUCKET_IS_TRANSIENT(bucket))
- << "Expected TRANSIENT bucket, but found " << bucket->type->name
- << " bucket.";
- const char* data = NULL;
- apr_size_t size = 0;
- ASSERT_EQ(APR_SUCCESS, apr_bucket_read(
- bucket, &data, &size, APR_NONBLOCK_READ));
- EXPECT_EQ(expected, std::string(data, size));
- apr_bucket_delete(bucket);
- }
-
- void ExpectEosBucket() {
- ASSERT_FALSE(APR_BRIGADE_EMPTY(brigade_))
- << "Expected EOS bucket, but brigade is empty.";
- apr_bucket* bucket = APR_BRIGADE_FIRST(brigade_);
- ASSERT_TRUE(APR_BUCKET_IS_EOS(bucket))
- << "Expected EOS bucket, but found " << bucket->type->name
- << " bucket.";
- apr_bucket_delete(bucket);
- }
-
- void ExpectEndOfBrigade() {
- ASSERT_TRUE(APR_BRIGADE_EMPTY(brigade_))
- << "Expected brigade to be empty, but found "
- << APR_BRIGADE_FIRST(brigade_)->type->name << " bucket.";
- ASSERT_EQ(APR_SUCCESS, apr_brigade_cleanup(brigade_));
- }
-
- void ExpectRstStream(net::SpdyRstStreamStatus status) {
- net::SpdyFrameIR* raw_frame;
- ASSERT_TRUE(output_queue_.Pop(&raw_frame))
- << "Expected RST_STREAM frame, but output queue is empty.";
- scoped_ptr<net::SpdyFrameIR> frame(raw_frame);
- EXPECT_THAT(*frame, mod_spdy::testing::IsRstStream(stream_id_, status));
- }
-
- void ExpectNoMoreOutputFrames() {
- EXPECT_TRUE(output_queue_.IsEmpty());
- }
-
- bool is_spdy2() const { return GetParam() < mod_spdy::spdy::SPDY_VERSION_3; }
-
- const char* host_header_name() const {
- return is_spdy2() ? mod_spdy::http::kHost : mod_spdy::spdy::kSpdy3Host;
- }
- const char* method_header_name() const {
- return (is_spdy2() ? mod_spdy::spdy::kSpdy2Method :
- mod_spdy::spdy::kSpdy3Method);
- }
- const char* path_header_name() const {
- return (is_spdy2() ? mod_spdy::spdy::kSpdy2Url :
- mod_spdy::spdy::kSpdy3Path);
- }
- const char* scheme_header_name() const {
- return (is_spdy2() ? mod_spdy::spdy::kSpdy2Scheme :
- mod_spdy::spdy::kSpdy3Scheme);
- }
- const char* version_header_name() const {
- return (is_spdy2() ? mod_spdy::spdy::kSpdy2Version :
- mod_spdy::spdy::kSpdy3Version);
- }
-
- const mod_spdy::spdy::SpdyVersion spdy_version_;
- const net::SpdyStreamId stream_id_;
- const net::SpdyPriority priority_;
- mod_spdy::SpdyFramePriorityQueue output_queue_;
- mod_spdy::SharedFlowControlWindow shared_window_;
- MockSpdyServerPushInterface pusher_;
- mod_spdy::SpdyStream stream_;
- mod_spdy::SpdyToHttpFilter spdy_to_http_filter_;
-
- mod_spdy::LocalPool local_;
- apr_bucket_alloc_t* bucket_alloc_;
- conn_rec* connection_;
- ap_filter_t* ap_filter_;
- apr_bucket_brigade* brigade_;
-};
-
-TEST_P(SpdyToHttpFilterTest, SimpleGetRequest) {
- // Perform an INIT. It should succeed, with no effect.
- ASSERT_EQ(APR_SUCCESS, Read(AP_MODE_INIT, APR_BLOCK_READ, 1337));
- ExpectEndOfBrigade();
-
- // Invoke the fitler in non-blocking GETLINE mode. We shouldn't get anything
- // yet, because we haven't sent any frames from the client yet.
- ASSERT_TRUE(APR_STATUS_IS_EAGAIN(
- Read(AP_MODE_GETLINE, APR_NONBLOCK_READ, 0)));
- ExpectEndOfBrigade();
-
- // Send a SYN_STREAM frame from the client, with FLAG_FIN set.
- net::SpdyNameValueBlock headers;
- headers[host_header_name()] = "www.example.com";
- headers[method_header_name()] = "GET";
- headers["referer"] = "https://www.example.com/index.html";
- headers[scheme_header_name()] = "https";
- headers[path_header_name()] = "/foo/bar/index.html";
- headers["user-agent"] = "ModSpdyUnitTest/1.0";
- headers[version_header_name()] = "HTTP/1.1";
- headers["x-do-not-track"] = "1";
- PostSynStreamFrame(true, headers);
-
- // Invoke the filter in blocking GETLINE mode. We should get back just the
- // HTTP request line.
- ASSERT_EQ(APR_SUCCESS, Read(AP_MODE_GETLINE, APR_BLOCK_READ, 0));
- ExpectTransientBucket("GET /foo/bar/index.html HTTP/1.1\r\n");
- ExpectEndOfBrigade();
-
- // Now do a SPECULATIVE read. We should get back a few bytes.
- ASSERT_EQ(APR_SUCCESS, Read(AP_MODE_SPECULATIVE, APR_NONBLOCK_READ, 8));
- ExpectTransientBucket("host: ww");
- ExpectEndOfBrigade();
-
- // Now do another GETLINE read. We should get back the first header line,
- // including the data we just read speculatively.
- ASSERT_EQ(APR_SUCCESS, Read(AP_MODE_GETLINE, APR_NONBLOCK_READ, 0));
- ExpectTransientBucket("host: www.example.com\r\n");
- ExpectEndOfBrigade();
-
- // Do a READBYTES read. We should get back a few bytes.
- ASSERT_EQ(APR_SUCCESS, Read(AP_MODE_READBYTES, APR_NONBLOCK_READ, 12));
- ExpectTransientBucket("referer: htt");
- ExpectEndOfBrigade();
-
- // Do another GETLINE read. We should get back the rest of the header line,
- // *not* including the data we just read.
- ASSERT_EQ(APR_SUCCESS, Read(AP_MODE_GETLINE, APR_NONBLOCK_READ, 0));
- ExpectTransientBucket("ps://www.example.com/index.html\r\n");
- ExpectEndOfBrigade();
-
- // Finally, do an EXHAUSTIVE read. We should get back everything that
- // remains, terminating with an EOS bucket.
- ASSERT_EQ(APR_SUCCESS, Read(AP_MODE_EXHAUSTIVE, APR_NONBLOCK_READ, 0));
- ExpectTransientBucket("user-agent: ModSpdyUnitTest/1.0\r\n"
- "x-do-not-track: 1\r\n"
- "accept-encoding: gzip,deflate\r\n"
- "\r\n");
- ExpectEosBucket();
- ExpectEndOfBrigade();
- ExpectNoMoreOutputFrames();
-
- // There's no more data left; attempting another read should result in EOF.
- ASSERT_TRUE(APR_STATUS_IS_EOF(
- Read(AP_MODE_READBYTES, APR_NONBLOCK_READ, 4)));
-}
-
-TEST_P(SpdyToHttpFilterTest, SimplePostRequest) {
- // Send a SYN_STREAM frame from the client.
- net::SpdyNameValueBlock headers;
- headers[host_header_name()] = "www.example.com";
- headers[method_header_name()] = "POST";
- headers["referer"] = "https://www.example.com/index.html";
- headers[scheme_header_name()] = "https";
- headers[path_header_name()] = "/erase/the/whole/database.cgi";
- headers["user-agent"] = "ModSpdyUnitTest/1.0";
- headers[version_header_name()] = "HTTP/1.1";
- PostSynStreamFrame(false, headers);
-
- // Do a nonblocking READBYTES read. We ask for lots of bytes, but since it's
- // nonblocking we should immediately get back what's available so far.
- ASSERT_EQ(APR_SUCCESS, Read(AP_MODE_READBYTES, APR_NONBLOCK_READ, 4096));
- ExpectTransientBucket("POST /erase/the/whole/database.cgi HTTP/1.1\r\n"
- "host: www.example.com\r\n"
- "referer: https://www.example.com/index.html\r\n"
- "user-agent: ModSpdyUnitTest/1.0\r\n");
- ExpectEndOfBrigade();
-
- // There's nothing more available yet, so a nonblocking read should fail.
- ASSERT_TRUE(APR_STATUS_IS_EAGAIN(
- Read(AP_MODE_READBYTES, APR_NONBLOCK_READ, 4)));
- ExpectEndOfBrigade();
- ExpectNoMoreOutputFrames();
-
- // Send some DATA frames.
- PostDataFrame(false, "Hello, world!\nPlease erase ");
- PostDataFrame(false, "the whole database ");
- PostDataFrame(true, "immediately.\nThanks!\n");
-
- // Now read in the data a bit at a time.
- ASSERT_EQ(APR_SUCCESS, Read(AP_MODE_GETLINE, APR_NONBLOCK_READ, 0));
- ExpectTransientBucket("transfer-encoding: chunked\r\n");
- ExpectEndOfBrigade();
- ASSERT_EQ(APR_SUCCESS, Read(AP_MODE_GETLINE, APR_NONBLOCK_READ, 0));
- ExpectTransientBucket("accept-encoding: gzip,deflate\r\n");
- ExpectEndOfBrigade();
- ASSERT_EQ(APR_SUCCESS, Read(AP_MODE_GETLINE, APR_NONBLOCK_READ, 0));
- ExpectTransientBucket("\r\n");
- ExpectEndOfBrigade();
- ASSERT_EQ(APR_SUCCESS, Read(AP_MODE_GETLINE, APR_NONBLOCK_READ, 0));
- ExpectTransientBucket("1B\r\n");
- ExpectEndOfBrigade();
- ASSERT_EQ(APR_SUCCESS, Read(AP_MODE_READBYTES, APR_NONBLOCK_READ, 24));
- ExpectTransientBucket("Hello, world!\nPlease era");
- ExpectEndOfBrigade();
- ExpectNoMoreOutputFrames();
- ASSERT_EQ(APR_SUCCESS, Read(AP_MODE_SPECULATIVE, APR_NONBLOCK_READ, 15));
- ExpectTransientBucket("se \r\n13\r\nthe wh");
- ExpectEndOfBrigade();
- ExpectNoMoreOutputFrames();
- ASSERT_EQ(APR_SUCCESS, Read(AP_MODE_READBYTES, APR_NONBLOCK_READ, 36));
- ExpectTransientBucket("se \r\n13\r\nthe whole database \r\n15\r\nim");
- ExpectEndOfBrigade();
- ExpectNoMoreOutputFrames();
- ASSERT_EQ(APR_SUCCESS, Read(AP_MODE_READBYTES, APR_NONBLOCK_READ, 21));
- ExpectTransientBucket("mediately.\nThanks!\n\r\n");
- ExpectEndOfBrigade();
- ASSERT_EQ(APR_SUCCESS, Read(AP_MODE_GETLINE, APR_NONBLOCK_READ, 0));
- ExpectTransientBucket("0\r\n");
- ExpectEndOfBrigade();
- ASSERT_EQ(APR_SUCCESS, Read(AP_MODE_GETLINE, APR_NONBLOCK_READ, 0));
- ExpectTransientBucket("\r\n");
- ExpectEosBucket();
- ExpectEndOfBrigade();
- ExpectNoMoreOutputFrames();
-
- // There's no more data left; attempting another read should result in EOF.
- ASSERT_TRUE(APR_STATUS_IS_EOF(Read(AP_MODE_GETLINE, APR_BLOCK_READ, 0)));
-}
-
-TEST_P(SpdyToHttpFilterTest, PostRequestWithHeadersFrames) {
- // Send a SYN_STREAM frame from the client.
- net::SpdyNameValueBlock headers;
- headers[host_header_name()] = "www.example.net";
- headers[method_header_name()] = "POST";
- headers["referer"] = "https://www.example.net/index.html";
- headers[scheme_header_name()] = "https";
- headers[path_header_name()] = "/erase/the/whole/database.cgi";
- headers["user-agent"] = "ModSpdyUnitTest/1.0";
- headers[version_header_name()] = "HTTP/1.1";
- PostSynStreamFrame(false, headers);
-
- // Send some DATA and HEADERS frames. The HEADERS frames should get buffered
- // and placed at the end of the HTTP request body as trailing headers.
- PostDataFrame(false, "Please erase ");
- net::SpdyNameValueBlock headers2;
- headers2["x-super-cool"] = "foo";
- PostHeadersFrame(false, headers2);
- PostDataFrame(false, "everything ");
- net::SpdyNameValueBlock headers3;
- headers3["x-awesome"] = "quux";
- PostHeadersFrame(false, headers3);
- PostDataFrame(true, "immediately!!\n");
-
- // Read in all the data.
- ASSERT_EQ(APR_SUCCESS, Read(AP_MODE_EXHAUSTIVE, APR_NONBLOCK_READ, 0));
- ExpectTransientBucket("POST /erase/the/whole/database.cgi HTTP/1.1\r\n"
- "host: www.example.net\r\n"
- "referer: https://www.example.net/index.html\r\n"
- "user-agent: ModSpdyUnitTest/1.0\r\n"
- "transfer-encoding: chunked\r\n"
- "accept-encoding: gzip,deflate\r\n"
- "\r\n"
- "D\r\n"
- "Please erase \r\n"
- "B\r\n"
- "everything \r\n"
- "E\r\n"
- "immediately!!\n\r\n"
- "0\r\n"
- "x-awesome: quux\r\n"
- "x-super-cool: foo\r\n"
- "\r\n");
- ExpectEosBucket();
- ExpectEndOfBrigade();
- ExpectNoMoreOutputFrames();
-}
-
-TEST_P(SpdyToHttpFilterTest, GetRequestWithHeadersRightAfterSynStream) {
- // Send a SYN_STREAM frame with some of the headers.
- net::SpdyNameValueBlock headers;
- headers[host_header_name()] = "www.example.org";
- headers[method_header_name()] = "GET";
- headers["referer"] = "https://www.example.org/foo/bar.html";
- headers[scheme_header_name()] = "https";
- headers[path_header_name()] = "/index.html";
- headers[version_header_name()] = "HTTP/1.1";
- PostSynStreamFrame(false, headers);
-
- // Read in everything that's available so far.
- ASSERT_EQ(APR_SUCCESS, Read(AP_MODE_EXHAUSTIVE, APR_NONBLOCK_READ, 0));
- ExpectTransientBucket("GET /index.html HTTP/1.1\r\n"
- "host: www.example.org\r\n"
- "referer: https://www.example.org/foo/bar.html\r\n");
- ExpectEndOfBrigade();
-
- // Send a HEADERS frame with the rest of the headers.
- net::SpdyNameValueBlock headers2;
- headers2["accept-encoding"] = "deflate, gzip";
- headers2["user-agent"] = "ModSpdyUnitTest/1.0";
- PostHeadersFrame(true, headers2);
-
- // Read in the rest of the request.
- ASSERT_EQ(APR_SUCCESS, Read(AP_MODE_EXHAUSTIVE, APR_NONBLOCK_READ, 0));
- ExpectTransientBucket("accept-encoding: deflate, gzip\r\n"
- "user-agent: ModSpdyUnitTest/1.0\r\n"
- "\r\n");
- ExpectEosBucket();
- ExpectEndOfBrigade();
- ExpectNoMoreOutputFrames();
-}
-
-TEST_P(SpdyToHttpFilterTest, PostRequestWithHeadersRightAfterSynStream) {
- // Send a SYN_STREAM frame from the client.
- net::SpdyNameValueBlock headers;
- headers[host_header_name()] = "www.example.org";
- headers[method_header_name()] = "POST";
- headers["referer"] = "https://www.example.org/index.html";
- headers[scheme_header_name()] = "https";
- headers[path_header_name()] = "/delete/everything.py";
- headers[version_header_name()] = "HTTP/1.1";
- headers["x-zzzz"] = "4Z";
- PostSynStreamFrame(false, headers);
-
- // Send a HEADERS frame before sending any data frames.
- net::SpdyNameValueBlock headers2;
- headers2["user-agent"] = "ModSpdyUnitTest/1.0";
- PostHeadersFrame(false, headers2);
-
- // Now send a couple DATA frames and a final HEADERS frame.
- PostDataFrame(false, "Please erase everything immediately");
- PostDataFrame(false, ", thanks!\n");
- net::SpdyNameValueBlock headers3;
- headers3["x-qqq"] = "3Q";
- PostHeadersFrame(true, headers3);
-
- // Read in all the data. The first HEADERS frame should get put in before
- // the data, and the last HEADERS frame should get put in after the data.
- ASSERT_EQ(APR_SUCCESS, Read(AP_MODE_EXHAUSTIVE, APR_NONBLOCK_READ, 0));
- ExpectTransientBucket("POST /delete/everything.py HTTP/1.1\r\n"
- "host: www.example.org\r\n"
- "referer: https://www.example.org/index.html\r\n"
- "x-zzzz: 4Z\r\n"
- "user-agent: ModSpdyUnitTest/1.0\r\n"
- "transfer-encoding: chunked\r\n"
- "accept-encoding: gzip,deflate\r\n"
- "\r\n"
- "23\r\n"
- "Please erase everything immediately\r\n"
- "A\r\n"
- ", thanks!\n\r\n"
- "0\r\n"
- "x-qqq: 3Q\r\n"
- "\r\n");
- ExpectEosBucket();
- ExpectEndOfBrigade();
- ExpectNoMoreOutputFrames();
-}
-
-TEST_P(SpdyToHttpFilterTest, PostRequestWithEmptyDataFrameInMiddle) {
- // Send a SYN_STREAM frame from the client.
- net::SpdyNameValueBlock headers;
- headers[host_header_name()] = "www.example.org";
- headers[method_header_name()] = "POST";
- headers["referer"] = "https://www.example.org/index.html";
- headers[scheme_header_name()] = "https";
- headers[path_header_name()] = "/do/some/stuff.py";
- headers[version_header_name()] = "HTTP/1.1";
- PostSynStreamFrame(false, headers);
-
- // Now send a few DATA frames, with a zero-length data frame in the middle.
- PostDataFrame(false, "Please do");
- PostDataFrame(false, " some ");
- PostDataFrame(false, "");
- PostDataFrame(true, "stuff.\n");
-
- // Read in all the data. The empty data frame should be ignored.
- ASSERT_EQ(APR_SUCCESS, Read(AP_MODE_EXHAUSTIVE, APR_NONBLOCK_READ, 0));
- ExpectTransientBucket("POST /do/some/stuff.py HTTP/1.1\r\n"
- "host: www.example.org\r\n"
- "referer: https://www.example.org/index.html\r\n"
- "transfer-encoding: chunked\r\n"
- "accept-encoding: gzip,deflate\r\n"
- "\r\n"
- "9\r\n"
- "Please do\r\n"
- "6\r\n"
- " some \r\n"
- "7\r\n"
- "stuff.\n\r\n"
- "0\r\n"
- "\r\n");
- ExpectEosBucket();
- ExpectEndOfBrigade();
- ExpectNoMoreOutputFrames();
-}
-
-TEST_P(SpdyToHttpFilterTest, PostRequestWithEmptyDataFrameAtEnd) {
- // Send a SYN_STREAM frame from the client.
- net::SpdyNameValueBlock headers;
- headers[host_header_name()] = "www.example.org";
- headers[method_header_name()] = "POST";
- headers["referer"] = "https://www.example.org/index.html";
- headers[scheme_header_name()] = "https";
- headers[path_header_name()] = "/do/some/stuff.py";
- headers[version_header_name()] = "HTTP/1.1";
- PostSynStreamFrame(false, headers);
-
- // Now send a few DATA frames, with a zero-length data frame at the end.
- PostDataFrame(false, "Please do");
- PostDataFrame(false, " some ");
- PostDataFrame(false, "stuff.\n");
- PostDataFrame(true, "");
-
- // Read in all the data. The empty data frame should be ignored (except for
- // its FLAG_FIN).
- ASSERT_EQ(APR_SUCCESS, Read(AP_MODE_EXHAUSTIVE, APR_NONBLOCK_READ, 0));
- ExpectTransientBucket("POST /do/some/stuff.py HTTP/1.1\r\n"
- "host: www.example.org\r\n"
- "referer: https://www.example.org/index.html\r\n"
- "transfer-encoding: chunked\r\n"
- "accept-encoding: gzip,deflate\r\n"
- "\r\n"
- "9\r\n"
- "Please do\r\n"
- "6\r\n"
- " some \r\n"
- "7\r\n"
- "stuff.\n\r\n"
- "0\r\n"
- "\r\n");
- ExpectEosBucket();
- ExpectEndOfBrigade();
- ExpectNoMoreOutputFrames();
-}
-
-TEST_P(SpdyToHttpFilterTest, PostRequestWithContentLength) {
- // Send a SYN_STREAM frame from the client.
- net::SpdyNameValueBlock headers;
- headers[host_header_name()] = "www.example.org";
- headers[method_header_name()] = "POST";
- headers["referer"] = "https://www.example.org/index.html";
- headers[scheme_header_name()] = "https";
- headers[path_header_name()] = "/do/some/stuff.py";
- headers[version_header_name()] = "HTTP/1.1";
- PostSynStreamFrame(false, headers);
-
- // Send a few more headers before sending data, including a content-length.
- net::SpdyNameValueBlock headers2;
- headers2["content-length"] = "22";
- headers2["user-agent"] = "ModSpdyUnitTest/1.0";
- PostHeadersFrame(false, headers2);
-
- // Now send a few DATA frames.
- PostDataFrame(false, "Please do");
- PostDataFrame(false, " some ");
- PostDataFrame(true, "stuff.\n");
-
- // Read in all the data. Because we supplied a content-length, chunked
- // encoding should not be used (to support modules that don't work with
- // chunked requests).
- ASSERT_EQ(APR_SUCCESS, Read(AP_MODE_EXHAUSTIVE, APR_NONBLOCK_READ, 0));
- ExpectTransientBucket("POST /do/some/stuff.py HTTP/1.1\r\n"
- "host: www.example.org\r\n"
- "referer: https://www.example.org/index.html\r\n"
- "content-length: 22\r\n"
- "user-agent: ModSpdyUnitTest/1.0\r\n"
- "accept-encoding: gzip,deflate\r\n"
- "\r\n"
- "Please do some stuff.\n");
- ExpectEosBucket();
- ExpectEndOfBrigade();
- ExpectNoMoreOutputFrames();
-}
-
-TEST_P(SpdyToHttpFilterTest, PostRequestWithContentLengthAndTrailingHeaders) {
- // Send a SYN_STREAM frame from the client, including a content-length.
- net::SpdyNameValueBlock headers;
- headers["content-length"] = "22";
- headers[host_header_name()] = "www.example.org";
- headers[method_header_name()] = "POST";
- headers["referer"] = "https://www.example.org/index.html";
- headers[scheme_header_name()] = "https";
- headers[path_header_name()] = "/do/some/stuff.py";
- headers[version_header_name()] = "HTTP/1.1";
- PostSynStreamFrame(false, headers);
-
- // Now send a few DATA frames.
- PostDataFrame(false, "Please do");
- PostDataFrame(false, " some ");
- PostDataFrame(false, "stuff.\n");
-
- // Finish with a HEADERS frame.
- net::SpdyNameValueBlock headers2;
- headers2["x-metadata"] = "foobar";
- headers2["x-whatever"] = "quux";
- PostHeadersFrame(true, headers2);
-
- // Read in all the data. Because we supplied a content-length, chunked
- // encoding should not be used, and as an unfortunate consequence, we must
- // therefore ignore the trailing headers (justified in that, at least in
- // HTTP, they're generally only used for ignorable metadata; in fact, they're
- // not generally used at all).
- ASSERT_EQ(APR_SUCCESS, Read(AP_MODE_EXHAUSTIVE, APR_NONBLOCK_READ, 0));
- // One (usually irrelevant) quirk of our implementation is that the host
- // header appears in a slightly different place for SPDY v2 and SPDY v3.
- // This is beacuse in SPDY v3 the host header is ":host", which sorts
- // earlier, and which we transform into the HTTP header "host".
- if (is_spdy2()) {
- ExpectTransientBucket("POST /do/some/stuff.py HTTP/1.1\r\n"
- "content-length: 22\r\n"
- "host: www.example.org\r\n"
- "referer: https://www.example.org/index.html\r\n"
- "accept-encoding: gzip,deflate\r\n"
- "\r\n"
- "Please do some stuff.\n");
- } else {
- ExpectTransientBucket("POST /do/some/stuff.py HTTP/1.1\r\n"
- "host: www.example.org\r\n"
- "content-length: 22\r\n"
- "referer: https://www.example.org/index.html\r\n"
- "accept-encoding: gzip,deflate\r\n"
- "\r\n"
- "Please do some stuff.\n");
- }
- ExpectEosBucket();
- ExpectEndOfBrigade();
- ExpectNoMoreOutputFrames();
-}
-
-TEST_P(SpdyToHttpFilterTest, ExtraSynStream) {
- // Send a SYN_STREAM frame from the client.
- net::SpdyNameValueBlock headers;
- headers[host_header_name()] = "www.example.com";
- headers[method_header_name()] = "POST";
- headers["referer"] = "https://www.example.com/index.html";
- headers[scheme_header_name()] = "https";
- headers[path_header_name()] = "/erase/the/whole/database.cgi";
- headers["user-agent"] = "ModSpdyUnitTest/1.0";
- headers[version_header_name()] = "HTTP/1.1";
- PostSynStreamFrame(false, headers);
-
- // Read in all available data.
- ASSERT_EQ(APR_SUCCESS, Read(AP_MODE_EXHAUSTIVE, APR_NONBLOCK_READ, 0));
- ExpectTransientBucket("POST /erase/the/whole/database.cgi HTTP/1.1\r\n"
- "host: www.example.com\r\n"
- "referer: https://www.example.com/index.html\r\n"
- "user-agent: ModSpdyUnitTest/1.0\r\n");
- ExpectEndOfBrigade();
-
- // Now send another SYN_STREAM for the same stream_id, which is illegal.
- PostSynStreamFrame(false, headers);
- // If we try to read more data, we'll get nothing.
- ASSERT_TRUE(APR_STATUS_IS_ECONNABORTED(
- Read(AP_MODE_EXHAUSTIVE, APR_NONBLOCK_READ, 0)));
- ExpectEosBucket();
- ExpectEndOfBrigade();
- // The stream should have been aborted.
- ExpectRstStream(net::RST_STREAM_PROTOCOL_ERROR);
- ExpectNoMoreOutputFrames();
- EXPECT_TRUE(stream_.is_aborted());
-}
-
-// Run each test over both SPDY v2 and SPDY v3.
-INSTANTIATE_TEST_CASE_P(Spdy2And3, SpdyToHttpFilterTest, testing::Values(
- mod_spdy::spdy::SPDY_VERSION_2, mod_spdy::spdy::SPDY_VERSION_3,
- mod_spdy::spdy::SPDY_VERSION_3_1));
-
-} // namespace
+++ /dev/null
-/* 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.
- */
-// Contains IdPool, a class for managing 16-bit process-global IDs.
-
-#include "mod_spdy/apache/id_pool.h"
-
-#include <vector>
-#include <set>
-
-#include "base/basictypes.h"
-#include "base/logging.h"
-
-namespace mod_spdy {
-
-IdPool* IdPool::g_instance = NULL;
-const uint16 IdPool::kOverFlowId;
-
-IdPool::IdPool()
- : next_never_used_(0) /* So it gets incremented to 1 in ::Alloc */ {
-}
-
-IdPool::~IdPool() {
-}
-
-void IdPool::CreateInstance() {
- DCHECK(g_instance == NULL);
- g_instance = new IdPool();
-}
-
-void IdPool::DestroyInstance() {
- DCHECK(g_instance != NULL);
- delete g_instance;
- g_instance = NULL;
-}
-
-uint16 IdPool::Alloc() {
- base::AutoLock lock(mutex_);
- if (!free_list_.empty()) {
- uint16 id = free_list_.back();
- free_list_.pop_back();
- alloc_set_.insert(id);
- return id;
- }
-
- // We do not use 0 or kOverFlowId normally..
- if (alloc_set_.size() == (0x10000 - 2)) {
- LOG(WARNING) << "Out of slave fetch IDs, things may break";
- return kOverFlowId;
- }
-
- // Freelist is empty, but we haven't yet used some ID, so return it.
- ++next_never_used_;
- DCHECK(next_never_used_ != kOverFlowId);
- DCHECK(alloc_set_.find(next_never_used_) == alloc_set_.end());
- alloc_set_.insert(next_never_used_);
- return next_never_used_;
-}
-
-void IdPool::Free(uint16 id) {
- if (id == kOverFlowId) {
- return;
- }
-
- base::AutoLock lock(mutex_);
- DCHECK(alloc_set_.find(id) != alloc_set_.end());
- alloc_set_.erase(id);
- free_list_.push_back(id);
-}
-
-} // namespace mod_spdy
+++ /dev/null
-/* 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.
- */
-
-#ifndef MOD_SPDY_APACHE_ID_POOL_H_
-#define MOD_SPDY_APACHE_ID_POOL_H_
-
-#include <vector>
-#include <set>
-
-#include "base/basictypes.h"
-#include "base/synchronization/lock.h"
-
-namespace mod_spdy {
-
-// A class for managing non-zero 16-bit process-global IDs.
-class IdPool {
- public:
- static const uint16 kOverFlowId = 0xFFFF;
-
- // Returns the one and only instance of the IdPool. Note that one must
- // be created with CreateInstance().
- static IdPool* Instance() { return g_instance; }
-
- // Call this before threading starts to initialize the instance pointer.
- static void CreateInstance();
-
- // Call this once you're done with the pool object to delete it.
- static void DestroyInstance();
-
- // Allocates a new, distinct, non-zero ID. 2^16-2 possible values may be
- // returned; if more than that are needed simultaneously (without being
- // Free()d) kOverFlowId will always be returned.
- uint16 Alloc();
-
- // Release an ID that's no longer in use, making it available for further
- // calls to Alloc().
- void Free(uint16 id);
-
- private:
- IdPool();
- ~IdPool();
-
- static IdPool* g_instance;
-
- base::Lock mutex_;
- std::vector<uint16> free_list_; // IDs known to be free
- std::set<uint16> alloc_set_; // IDs currently in use
- uint16 next_never_used_; // Next ID we have never returned from Alloc,
- // for use when the free list is empty.
-
- DISALLOW_COPY_AND_ASSIGN(IdPool);
-};
-
-} // namespace mod_spdy
-
-#endif /* MOD_SPDY_APACHE_ID_POOL_H_ */
+++ /dev/null
-// 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.
-
-#include "mod_spdy/apache/id_pool.h"
-
-#include <set>
-
-#include "base/basictypes.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace {
-
-using mod_spdy::IdPool;
-
-TEST(IdPoolTest, Lifetime) {
- EXPECT_EQ(NULL, IdPool::Instance());
- IdPool::CreateInstance();
- EXPECT_TRUE(IdPool::Instance() != NULL);
- IdPool::DestroyInstance();
- EXPECT_EQ(NULL, IdPool::Instance());
-}
-
-TEST(IdPoolTest, BasicAllocation) {
- IdPool::CreateInstance();
- IdPool* instance = IdPool::Instance();
- uint16 id_1 = instance->Alloc();
- uint16 id_2 = instance->Alloc();
- uint16 id_3 = instance->Alloc();
- EXPECT_NE(0, id_1);
- EXPECT_NE(0, id_2);
- EXPECT_NE(0, id_3);
- EXPECT_NE(id_1, id_2);
- EXPECT_NE(id_1, id_3);
- EXPECT_NE(id_2, id_3);
- instance->Free(id_1);
- instance->Free(id_2);
- instance->Free(id_3);
- IdPool::DestroyInstance();
-}
-
-TEST(IdPoolTest, AllocatingMany) {
- // We should be able to allocate 2^16-2 unique ids.
- IdPool::CreateInstance();
- IdPool* instance = IdPool::Instance();
-
- std::set<uint16> in_use;
- for (int run = 0; run < 0xFFFE; ++run) {
- uint16 new_id = instance->Alloc();
- EXPECT_NE(0, new_id);
- EXPECT_NE(IdPool::kOverFlowId, new_id);
- EXPECT_TRUE(in_use.find(new_id) == in_use.end());
- in_use.insert(new_id);
- }
-
- // All attempts after this point should return kOverFlowId.
- for (int run = 0; run < 100; ++run) {
- EXPECT_EQ(IdPool::kOverFlowId, instance->Alloc());
- }
-
- // Trying to free the overflow ID is harmless.
- instance->Free(IdPool::kOverFlowId);
-
- // Now delete half of them.
- int deleted = 0;
- std::set<uint16>::iterator i = in_use.begin();
- while (deleted != 0xFFFE / 2) {
- ASSERT_TRUE(i != in_use.end());
- instance->Free(*i);
- ++deleted;
- in_use.erase(i);
- i = in_use.begin();
- }
-
- // Should now be able to allocate that many again.
- for (int run = 0; run < 0xFFFE / 2; ++run) {
- uint16 new_id = instance->Alloc();
- EXPECT_NE(0, new_id);
- EXPECT_NE(IdPool::kOverFlowId, new_id);
- EXPECT_TRUE(in_use.find(new_id) == in_use.end());
- in_use.insert(new_id);
- }
-
- IdPool::DestroyInstance();
-}
-
-} // namespace
+++ /dev/null
-// 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.
-
-#include "mod_spdy/apache/log_message_handler.h"
-
-#include <limits>
-#include <string>
-
-#include "httpd.h"
-// When HAVE_SYSLOG is defined, apache http_log.h will include syslog.h, which
-// #defined LOG_* as numbers. This conflicts with what we are using those here.
-#undef HAVE_SYSLOG
-#include "http_log.h"
-
-#include "base/debug/debugger.h"
-#include "base/debug/stack_trace.h"
-#include "base/logging.h"
-#include "base/threading/thread_local.h"
-#include "mod_spdy/apache/pool_util.h"
-#include "mod_spdy/common/spdy_stream.h"
-#include "mod_spdy/common/version.h"
-
-// Make sure we don't attempt to use LOG macros here, since doing so
-// would cause us to go into an infinite log loop.
-#undef LOG
-#define LOG USING_LOG_HERE_WOULD_CAUSE_INFINITE_RECURSION
-
-namespace {
-
-class LogHandler;
-
-const char* const kLogMessagePrefix =
- "[mod_spdy/" MOD_SPDY_VERSION_STRING "-" LASTCHANGE_STRING "] ";
-
-apr_pool_t* log_pool = NULL;
-base::ThreadLocalPointer<LogHandler>* gThreadLocalLogHandler = NULL;
-
-const int kMaxInt = std::numeric_limits<int>::max();
-int log_level_cutoff = kMaxInt;
-
-class LogHandler {
- public:
- explicit LogHandler(LogHandler* parent) : parent_(parent) {}
- virtual ~LogHandler() {}
- virtual void Log(int log_level, const std::string& message) = 0;
- LogHandler* parent() const { return parent_; }
- private:
- LogHandler* parent_;
- DISALLOW_COPY_AND_ASSIGN(LogHandler);
-};
-
-// Log a message with the given LogHandler; if the LogHandler is NULL, fall
-// back to using ap_log_perror.
-void LogWithHandler(LogHandler* handler, int log_level,
- const std::string& message) {
- if (handler != NULL) {
- handler->Log(log_level, message);
- } else {
- // ap_log_perror only prints messages with a severity of at least NOTICE,
- // so if we're falling back to ap_log_perror (which should be rare) then
- // force the log_level to a verbosity of NOTICE or lower.
- COMPILE_ASSERT(APLOG_DEBUG > APLOG_NOTICE,
- higher_verbosity_is_higher_number);
- ap_log_perror(APLOG_MARK, std::min(log_level, APLOG_NOTICE), APR_SUCCESS,
- log_pool, "%s", message.c_str());
- }
-}
-
-void PopLogHandler() {
- CHECK(gThreadLocalLogHandler);
- LogHandler* handler = gThreadLocalLogHandler->Get();
- CHECK(handler);
- gThreadLocalLogHandler->Set(handler->parent());
- delete handler;
-}
-
-class ServerLogHandler : public LogHandler {
- public:
- ServerLogHandler(LogHandler* parent, server_rec* server)
- : LogHandler(parent), server_(server) {}
- virtual void Log(int log_level, const std::string& message) {
- ap_log_error(APLOG_MARK, log_level, APR_SUCCESS, server_,
- "%s", message.c_str());
- }
- private:
- server_rec* const server_;
- DISALLOW_COPY_AND_ASSIGN(ServerLogHandler);
-};
-
-class ConnectionLogHandler : public LogHandler {
- public:
- ConnectionLogHandler(LogHandler* parent, conn_rec* connection)
- : LogHandler(parent), connection_(connection) {}
- virtual void Log(int log_level, const std::string& message) {
- ap_log_cerror(APLOG_MARK, log_level, APR_SUCCESS, connection_,
- "%s", message.c_str());
- }
- private:
- conn_rec* const connection_;
- DISALLOW_COPY_AND_ASSIGN(ConnectionLogHandler);
-};
-
-class StreamLogHandler : public LogHandler {
- public:
- StreamLogHandler(LogHandler* parent, conn_rec* connection,
- const mod_spdy::SpdyStream* stream)
- : LogHandler(parent), connection_(connection), stream_(stream) {}
- virtual void Log(int log_level, const std::string& message) {
- ap_log_cerror(APLOG_MARK, log_level, APR_SUCCESS, connection_,
- "[stream %d] %s", static_cast<int>(stream_->stream_id()),
- message.c_str());
- }
- private:
- conn_rec* const connection_;
- const mod_spdy::SpdyStream* const stream_;
- DISALLOW_COPY_AND_ASSIGN(StreamLogHandler);
-};
-
-int GetApacheLogLevel(int severity) {
- switch (severity) {
- case logging::LOG_INFO:
- return APLOG_INFO;
- case logging::LOG_WARNING:
- return APLOG_WARNING;
- case logging::LOG_ERROR:
- return APLOG_ERR;
- case logging::LOG_ERROR_REPORT:
- return APLOG_CRIT;
- case logging::LOG_FATAL:
- return APLOG_ALERT;
- default: // For VLOG()s
- return APLOG_DEBUG;
- }
-}
-
-bool LogMessageHandler(int severity, const char* file, int line,
- size_t message_start, const std::string& str) {
- const int this_log_level = GetApacheLogLevel(severity);
-
- std::string message(kLogMessagePrefix);
- message.append(str);
- if (severity == logging::LOG_FATAL) {
- if (base::debug::BeingDebugged()) {
- base::debug::BreakDebugger();
- } else {
- base::debug::StackTrace trace;
- std::ostringstream stream;
- trace.OutputToStream(&stream);
- message.append(stream.str());
- }
- }
-
- // Trim the newline off the end of the message string.
- size_t last_msg_character_index = message.length() - 1;
- if (message[last_msg_character_index] == '\n') {
- message.resize(last_msg_character_index);
- }
-
- if (this_log_level <= log_level_cutoff || log_level_cutoff == kMaxInt) {
- LogWithHandler(gThreadLocalLogHandler->Get(), this_log_level, message);
- }
-
- if (severity == logging::LOG_FATAL) {
- // Crash the process to generate a dump.
- base::debug::BreakDebugger();
- }
-
- return true;
-}
-
-// Include PID and TID in each log message.
-bool kShowProcessId = true;
-bool kShowThreadId = true;
-
-// Disabled since this information is already included in the apache
-// log line.
-bool kShowTimestamp = false;
-
-// Disabled by default due to CPU cost. Enable to see high-resolution
-// timestamps in the logs.
-bool kShowTickcount = false;
-
-} // namespace
-
-namespace mod_spdy {
-
-ScopedServerLogHandler::ScopedServerLogHandler(server_rec* server) {
- CHECK(gThreadLocalLogHandler);
- gThreadLocalLogHandler->Set(new ServerLogHandler(
- gThreadLocalLogHandler->Get(), server));
-}
-
-ScopedServerLogHandler::~ScopedServerLogHandler() {
- PopLogHandler();
-}
-
-ScopedConnectionLogHandler::ScopedConnectionLogHandler(conn_rec* connection) {
- CHECK(gThreadLocalLogHandler);
- gThreadLocalLogHandler->Set(new ConnectionLogHandler(
- gThreadLocalLogHandler->Get(), connection));
-}
-
-ScopedConnectionLogHandler::~ScopedConnectionLogHandler() {
- PopLogHandler();
-}
-
-ScopedStreamLogHandler::ScopedStreamLogHandler(conn_rec* slave_connection,
- const SpdyStream* stream) {
- CHECK(gThreadLocalLogHandler);
- gThreadLocalLogHandler->Set(new StreamLogHandler(
- gThreadLocalLogHandler->Get(), slave_connection, stream));
-}
-
-ScopedStreamLogHandler::~ScopedStreamLogHandler() {
- PopLogHandler();
-}
-
-void InstallLogMessageHandler(apr_pool_t* pool) {
- log_pool = pool;
- gThreadLocalLogHandler = new base::ThreadLocalPointer<LogHandler>();
- PoolRegisterDelete(pool, gThreadLocalLogHandler);
- logging::SetLogItems(kShowProcessId,
- kShowThreadId,
- kShowTimestamp,
- kShowTickcount);
- logging::SetLogMessageHandler(&LogMessageHandler);
-}
-
-void SetLoggingLevel(int apache_log_level, int vlog_level) {
- switch (apache_log_level) {
- case APLOG_EMERG:
- case APLOG_ALERT:
- logging::SetMinLogLevel(logging::LOG_FATAL);
- break;
- case APLOG_CRIT:
- logging::SetMinLogLevel(logging::LOG_ERROR_REPORT);
- break;
- case APLOG_ERR:
- logging::SetMinLogLevel(logging::LOG_ERROR);
- break;
- case APLOG_WARNING:
- logging::SetMinLogLevel(logging::LOG_WARNING);
- break;
- case APLOG_NOTICE:
- case APLOG_INFO:
- case APLOG_DEBUG:
- default:
- logging::SetMinLogLevel(std::min(logging::LOG_INFO, -vlog_level));
- break;
- }
-}
-
-} // namespace mod_spdy
+++ /dev/null
-// 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.
-
-#ifndef MOD_SPDY_APACHE_LOG_MESSAGE_HANDLER_H_
-#define MOD_SPDY_APACHE_LOG_MESSAGE_HANDLER_H_
-
-#include <string>
-
-#include "httpd.h"
-#include "apr_pools.h"
-
-#include "base/basictypes.h"
-
-namespace mod_spdy {
-
-class SpdyStream;
-
-// Stack-allocate to install a server-specific log handler for the duration of
-// the current scope (on the current thread only). For example:
-//
-// void SomeApacheHookFunction(server_rec* server) {
-// ScopedServerLogHandler handler(server);
-// ...call various other functions here...
-// }
-//
-// The log handler will be in effect until the end of the block, but only for
-// this thread (even if this thread spawns other threads in the meantime).
-// Establishing this server-specific log handler allows LOG() macros within
-// called functions to produce better messages.
-class ScopedServerLogHandler {
- public:
- explicit ScopedServerLogHandler(server_rec* server);
- ~ScopedServerLogHandler();
- private:
- DISALLOW_COPY_AND_ASSIGN(ScopedServerLogHandler);
-};
-
-// Stack-allocate to install a connection-specific log handler for the duration
-// of the current scope (on the current thread only). See the doc comment for
-// ScopedServerLogHandler above for an example.
-class ScopedConnectionLogHandler {
- public:
- explicit ScopedConnectionLogHandler(conn_rec* connection);
- ~ScopedConnectionLogHandler();
- private:
- DISALLOW_COPY_AND_ASSIGN(ScopedConnectionLogHandler);
-};
-
-// Stack-allocate to install a stream-specific log handler for the duration of
-// the current scope (on the current thread only). See the doc comment for
-// ScopedServerLogHandler above for an example.
-class ScopedStreamLogHandler {
- public:
- explicit ScopedStreamLogHandler(conn_rec* slave_connection,
- const SpdyStream* stream);
- ~ScopedStreamLogHandler();
- private:
- DISALLOW_COPY_AND_ASSIGN(ScopedStreamLogHandler);
-};
-
-// Install a log message handler that routes LOG() messages to the
-// apache error log. Should be called once, at server startup.
-void InstallLogMessageHandler(apr_pool_t* pool);
-
-// Set the logging level for LOG() messages, based on the Apache log level and
-// the VLOG-level specified in the server config. Note that the VLOG level
-// will be ignored unless the Apache log verbosity is at NOTICE or higher.
-// Should be called once for each child process, at process startup.
-void SetLoggingLevel(int apache_log_level, int vlog_level);
-
-} // namespace mod_spdy
-
-#endif // MOD_SPDY_APACHE_LOG_MESSAGE_HANDLER_H_
+++ /dev/null
-// 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.
-
-#include "mod_spdy/apache/master_connection_context.h"
-
-#include "base/logging.h"
-#include "mod_spdy/common/protocol_util.h"
-#include "mod_spdy/common/spdy_stream.h"
-
-namespace mod_spdy {
-
-MasterConnectionContext::MasterConnectionContext(bool using_ssl)
- : using_ssl_(using_ssl),
- npn_state_(NOT_DONE_YET),
- assume_spdy_(false),
- spdy_version_(spdy::SPDY_VERSION_NONE) {}
-
-MasterConnectionContext::~MasterConnectionContext() {}
-
-bool MasterConnectionContext::is_using_spdy() const {
- const bool using_spdy = (npn_state_ == USING_SPDY || assume_spdy_);
- return using_spdy;
-}
-
-MasterConnectionContext::NpnState MasterConnectionContext::npn_state() const {
- return npn_state_;
-}
-
-void MasterConnectionContext::set_npn_state(NpnState state) {
- npn_state_ = state;
-}
-
-bool MasterConnectionContext::is_assuming_spdy() const {
- return assume_spdy_;
-}
-
-void MasterConnectionContext::set_assume_spdy(bool assume) {
- assume_spdy_ = assume;
-}
-
-spdy::SpdyVersion MasterConnectionContext::spdy_version() const {
- DCHECK(is_using_spdy());
- DCHECK_NE(spdy::SPDY_VERSION_NONE, spdy_version_);
- return spdy_version_;
-}
-
-void MasterConnectionContext::set_spdy_version(
- spdy::SpdyVersion spdy_version) {
- DCHECK(is_using_spdy());
- DCHECK_EQ(spdy::SPDY_VERSION_NONE, spdy_version_);
- DCHECK_NE(spdy::SPDY_VERSION_NONE, spdy_version);
- spdy_version_ = spdy_version;
-}
-
-} // namespace mod_spdy
+++ /dev/null
-// 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.
-
-#ifndef MOD_SPDY_APACHE_MASTER_CONNECTION_CONTEXT_H_
-#define MOD_SPDY_APACHE_MASTER_CONNECTION_CONTEXT_H_
-
-#include <string>
-
-#include "base/basictypes.h"
-#include "base/memory/scoped_ptr.h"
-#include "mod_spdy/common/protocol_util.h"
-
-namespace mod_spdy {
-
-class SpdyStream;
-
-// Shared context object for a SPDY connection to the outside world.
-class MasterConnectionContext {
- public:
- // Create a context object for a master connection (one to the outside world,
- // not for talking to Apache).
- explicit MasterConnectionContext(bool using_ssl);
- ~MasterConnectionContext();
-
- // Return true if the connection to the user is over SSL. This is almost
- // always true, but may be false if we've been set to use SPDY for non-SSL
- // connections (for debugging).
- bool is_using_ssl() const { return using_ssl_; }
-
- // Return true if we are using SPDY for this connection, which is the case if
- // either 1) SPDY was chosen by NPN, or 2) we are assuming SPDY regardless of
- // NPN.
- bool is_using_spdy() const;
-
- enum NpnState {
- // NOT_DONE_YET: NPN has not yet completed.
- NOT_DONE_YET,
- // USING_SPDY: We have agreed with the client to use SPDY for this
- // connection.
- USING_SPDY,
- // NOT_USING_SPDY: We have decided not to use SPDY for this connection.
- NOT_USING_SPDY
- };
-
- // Get the NPN state of this connection. Unless you actually care about NPN
- // itself, you probably don't want to use this method to check if SPDY is
- // being used; instead, use is_using_spdy().
- NpnState npn_state() const;
-
- // Set the NPN state of this connection.
- void set_npn_state(NpnState state);
-
- // If true, we are simply _assuming_ SPDY, regardless of the outcome of NPN.
- bool is_assuming_spdy() const;
-
- // Set whether we are assuming SPDY for this connection (regardless of NPN).
- void set_assume_spdy(bool assume);
-
- // Return the SPDY version number we will be using. Requires that
- // is_using_spdy() is true and that the version number has already been set.
- spdy::SpdyVersion spdy_version() const;
-
- // Set the SPDY version number we will be using. Requires that
- // is_using_spdy() is true, and set_spdy_version hasn't already been called.
- void set_spdy_version(spdy::SpdyVersion spdy_version);
-
- private:
- const bool using_ssl_;
- NpnState npn_state_;
- bool assume_spdy_;
- spdy::SpdyVersion spdy_version_;
-
- DISALLOW_COPY_AND_ASSIGN(MasterConnectionContext);
-};
-
-} // namespace mod_spdy
-
-#endif // MOD_SPDY_APACHE_MASTER_CONNECTION_CONTEXT_H_
+++ /dev/null
-// 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.
-
-#include "mod_spdy/apache/pool_util.h"
-
-#include <string>
-
-#include "apr_errno.h"
-
-#include "base/basictypes.h"
-
-namespace mod_spdy {
-
-std::string AprStatusString(apr_status_t status) {
- char buffer[120];
- apr_strerror(status, buffer, arraysize(buffer));
- return std::string(buffer);
-}
-
-} // namespace mod_spdy
+++ /dev/null
-// 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.
-
-#ifndef MOD_SPDY_APACHE_POOL_UTIL_H_
-#define MOD_SPDY_APACHE_POOL_UTIL_H_
-
-#include <string>
-
-#include "apr_pools.h"
-#include "base/logging.h"
-
-namespace mod_spdy {
-
-/**
- * Wrapper object that creates a new apr_pool_t and then destroys it when
- * deleted (handy for creating a local apr_pool_t on the stack).
- *
- * Example usage:
- *
- * apr_status_t SomeFunction() {
- * LocalPool local;
- * char* buffer = apr_palloc(local.pool(), 1024);
- * // Do stuff with buffer; it will dealloc when we leave this scope.
- * return APR_SUCCESS;
- * }
- */
-class LocalPool {
- public:
- LocalPool() : pool_(NULL) {
- // apr_pool_create() only fails if we run out of memory. However, we make
- // no effort elsewhere in this codebase to deal with running out of memory,
- // so there's no sense in dealing with it here. Instead, just assert that
- // pool creation succeeds.
- const apr_status_t status = apr_pool_create(&pool_, NULL);
- CHECK(status == APR_SUCCESS);
- CHECK(pool_ != NULL);
- }
-
- ~LocalPool() {
- apr_pool_destroy(pool_);
- }
-
- apr_pool_t* pool() const { return pool_; }
-
- private:
- apr_pool_t* pool_;
-
- DISALLOW_COPY_AND_ASSIGN(LocalPool);
-};
-
-// Helper function for PoolRegisterDelete.
-template <class T>
-apr_status_t DeletionFunction(void* object) {
- delete static_cast<T*>(object);
- return APR_SUCCESS;
-}
-
-// Register a C++ object to be deleted with a pool.
-template <class T>
-void PoolRegisterDelete(apr_pool_t* pool, T* object) {
- // Note that the "child cleanup" argument below doesn't apply to us, so we
- // use apr_pool_cleanup_null, which is a no-op cleanup function.
- apr_pool_cleanup_register(pool, object,
- DeletionFunction<T>, // cleanup function
- apr_pool_cleanup_null); // child cleanup
-}
-
-// Un-register a C++ object from deletion with a pool. Essentially, this
-// undoes a previous call to PoolRegisterDelete with the same pool and object.
-template <class T>
-void PoolUnregisterDelete(apr_pool_t* pool, T* object) {
- apr_pool_cleanup_kill(pool, object, DeletionFunction<T>);
-}
-
-// Return a string describing the given APR status code.
-std::string AprStatusString(apr_status_t status);
-
-} // namespace mod_spdy
-
-#endif // MOD_SPDY_APACHE_POOL_UTIL_H_
+++ /dev/null
-// 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.
-
-#include "mod_spdy/apache/pool_util.h"
-
-#include "base/basictypes.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace {
-
-// Class to help us detect when it is deleted.
-class SetOnDelete {
- public:
- SetOnDelete(int value, int* ptr) : value_(value), ptr_(ptr) {}
- ~SetOnDelete() { *ptr_ = value_; }
- private:
- const int value_;
- int* const ptr_;
- DISALLOW_COPY_AND_ASSIGN(SetOnDelete);
-};
-
-TEST(PoolUtilTest, LocalPoolRegisterDelete) {
- int value = 3;
- {
- mod_spdy::LocalPool local;
- SetOnDelete* setter = new SetOnDelete(5, &value);
- mod_spdy::PoolRegisterDelete(local.pool(), setter);
- ASSERT_EQ(3, value);
- }
- ASSERT_EQ(5, value);
-}
-
-TEST(PoolUtilTest, LocalPoolUnregisterDelete) {
- int value = 2;
- SetOnDelete* setter = new SetOnDelete(7, &value);
- {
- mod_spdy::LocalPool local;
- mod_spdy::PoolRegisterDelete(local.pool(), setter);
- ASSERT_EQ(2, value);
- mod_spdy::PoolUnregisterDelete(local.pool(), setter);
- ASSERT_EQ(2, value);
- }
- ASSERT_EQ(2, value);
- delete setter;
- ASSERT_EQ(7, value);
-}
-
-} // namespace
+++ /dev/null
-// 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.
-
-#include "mod_spdy/apache/slave_connection.h"
-
-#include "apr_strings.h"
-// Temporarily define CORE_PRIVATE so we can see the declarations for
-// ap_create_conn_config (in http_config.h), ap_process_connection (in
-// http_connection.h), and core_module (in http_core.h).
-#define CORE_PRIVATE
-#include "httpd.h"
-#include "http_config.h"
-#include "http_connection.h"
-#include "http_core.h"
-#undef CORE_PRIVATE
-
-#include "base/basictypes.h"
-#include "base/logging.h"
-#include "mod_spdy/apache/config_util.h"
-#include "mod_spdy/apache/id_pool.h"
-#include "mod_spdy/apache/log_message_handler.h"
-#include "mod_spdy/apache/master_connection_context.h"
-#include "mod_spdy/apache/slave_connection_context.h"
-#include "mod_spdy/apache/sockaddr_util.h"
-#include "mod_spdy/apache/ssl_util.h"
-
-namespace mod_spdy {
-
-SlaveConnectionFactory::SlaveConnectionFactory(conn_rec* master_connection) {
- // If the parent connection is using mod_spdy, we can extract relevant info
- // on whether we're using it there.
- if (HasMasterConnectionContext(master_connection)) {
- MasterConnectionContext* master_context =
- GetMasterConnectionContext(master_connection);
- is_using_ssl_ = master_context->is_using_ssl();
- spdy_version_ = (master_context->is_using_spdy() ?
- master_context->spdy_version() :
- spdy::SPDY_VERSION_NONE);
- } else {
- is_using_ssl_ = IsUsingSslForConnection(master_connection);
- spdy_version_ = spdy::SPDY_VERSION_NONE;
- }
-
- base_server_ = master_connection->base_server;
- local_addr_ = DeepCopySockAddr(master_connection->local_addr, pool_.pool());
- local_ip_ = apr_pstrdup(pool_.pool(), master_connection->local_ip);
- remote_addr_ = DeepCopySockAddr(master_connection->remote_addr, pool_.pool());
- remote_ip_ = apr_pstrdup(pool_.pool(), master_connection->remote_ip);
- master_connection_id_ = master_connection->id;
-}
-
-SlaveConnectionFactory::~SlaveConnectionFactory() {
- // Nothing to do --- pool_ dtor will clean everything up.
-}
-
-SlaveConnection* SlaveConnectionFactory::Create() {
- return new SlaveConnection(this);
-}
-
-SlaveConnection::SlaveConnection(SlaveConnectionFactory* factory) {
- apr_pool_t* pool = pool_.pool();
-
- slave_connection_ =
- static_cast<conn_rec*>(apr_pcalloc(pool, sizeof(conn_rec)));
-
- // Initialize what fields of the connection object we can (the rest are
- // zeroed out by apr_pcalloc). In particular, we should set at least those
- // fields set by core_create_conn() in core.c in Apache.
- // -> id will be set once we are actually running the connection, in
- // ::Run().
- slave_connection_->clogging_input_filters = 0;
- slave_connection_->sbh = NULL;
- // We will manage this connection and all the associated resources with the
- // pool we just created.
- slave_connection_->pool = pool;
- slave_connection_->bucket_alloc = apr_bucket_alloc_create(pool);
- slave_connection_->conn_config = ap_create_conn_config(pool);
- slave_connection_->notes = apr_table_make(pool, 5);
- // Use the same server settings and client address for the slave connection
- // as for the master connection --- the factory saved them for us.
- slave_connection_->base_server = factory->base_server_;
- slave_connection_->local_addr = factory->local_addr_;
- slave_connection_->local_ip = factory->local_ip_;
- slave_connection_->remote_addr = factory->remote_addr_;
- slave_connection_->remote_ip = factory->remote_ip_;
-
- // One of the other things we will need in slave_connection is a
- // connection id. One of the bits of info we will need for it is the
- // id of the master connection. We save it here, and use it inside ::Run().
- master_connection_id_ = factory->master_connection_id_;
-
- // We're supposed to pass a socket object to ap_process_connection below, but
- // there's no meaningful object to pass for this slave connection, because
- // we're not really talking to the network. Our pre-connection hook will
- // prevent the core filters, which talk to the socket, from being inserted,
- // so they won't notice anyway; nonetheless, we can't pass NULL to
- // ap_process_connection because that can cause some other modules to
- // segfault if they try to muck with the socket's settings. So, we'll just
- // allocate our own socket object for those modules to mess with. This is a
- // kludge, but it seems to work.
- slave_socket_ = NULL;
- apr_status_t status = apr_socket_create(
- &slave_socket_, APR_INET, SOCK_STREAM, APR_PROTO_TCP, pool);
- DCHECK(status == APR_SUCCESS);
- DCHECK(slave_socket_ != NULL);
-
- // In our context object for this connection, mark this connection as being
- // a slave. Our pre-connection and process-connection hooks will notice
- // this, and act accordingly, when they are called for the slave
- // connection.
- SlaveConnectionContext* slave_context =
- CreateSlaveConnectionContext(slave_connection_);
-
- // Now store the SSL and SPDY info.
- slave_context->set_is_using_ssl(factory->is_using_ssl_);
- slave_context->set_spdy_version(factory->spdy_version_);
-}
-
-SlaveConnection::~SlaveConnection() {
- // pool_ destructor will take care of everything.
-}
-
-SlaveConnectionContext* SlaveConnection::GetSlaveConnectionContext() {
- return mod_spdy::GetSlaveConnectionContext(slave_connection_);
-}
-
-void SlaveConnection::Run() {
- // Pick a globally-unique ID for the slave connection; this must be unique
- // at any given time. Normally the MPM is responsible for assigning these,
- // and each MPM does it differently, so we're cheating in a dangerous way by
- // trying to assign one here. However, most MPMs seem to do it in a similar
- // way: for non-threaded MPMs (e.g. Prefork, WinNT), the ID is just the
- // child ID, which is a small nonnegative integer (i.e. an array index into
- // the list of active child processes); for threaded MPMs (e.g. Worker,
- // Event) the ID is typically ((child_index * thread_limit) + thread_index),
- // which will again be a positive integer, most likely (but not necessarily,
- // if thread_limit is set absurdly high) smallish.
- //
- // Therefore, the approach that we take is to concatenate the Apache
- // connection ID for the master connection with a small integer from IDPool
- // that's unique within the process, and, to avoid conflicts with
- // MPM-assigned connection IDs, we make our slave connection ID negative.
- // We only have so many bits to work with
- // (especially if long is only four bytes instead of eight), so we could
- // potentially run into trouble if the master connection ID gets very large
- // or we have too many active tasks simultaneously (i.e. more than 2^16).
- // So, this approach definitely isn't any kind of robust; but it will
- // probably usually work. It would, of course, be great to replace this
- // with a better strategy, if we find one.
- //
- // TODO(mdsteele): We could also consider using an #if here to widen the
- // masks and the shift distance on systems where sizeof(long)==8.
- // We might as well use those extra bits if we have them.
- COMPILE_ASSERT(sizeof(long) >= 4, long_is_at_least_32_bits);
- const uint16 in_process_id = IdPool::Instance()->Alloc();
- const long slave_connectionid =
- -(((master_connection_id_ & 0x7fffL) << 16) | in_process_id);
- slave_connection_->id = slave_connectionid;
-
- // Normally, the core pre-connection hook sets the core module's connection
- // context to the socket passed to ap_process_connection; certain other
- // modules, such as mod_reqtimeout, read the core module's connection
- // context directly so as to read this socket's settings. However, we
- // purposely don't allow the core pre-connection hook to run, because we
- // don't want the core connection filters to be inserted. So, to avoid
- // breaking other modules, we take it upon oursevles to set the core
- // module's connection context to the socket we are passing to
- // ap_process_connection. This is ugly, but seems to work.
- ap_set_module_config(slave_connection_->conn_config,
- &core_module, slave_socket_);
-
- // Invoke Apache's usual processing pipeline. This will block until the
- // connection is complete.
- ap_process_connection(slave_connection_, slave_socket_);
-
- IdPool::Instance()->Free(in_process_id);
-}
-
-} // namespace mod_spdy
+++ /dev/null
-/* 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.
- */
-
-#ifndef MOD_SPDY_APACHE_SLAVE_CONNECTION_H_
-#define MOD_SPDY_APACHE_SLAVE_CONNECTION_H_
-
-#include "base/basictypes.h"
-#include "mod_spdy/apache/pool_util.h"
-#include "mod_spdy/common/protocol_util.h"
-
-struct apr_sockaddr_t;
-struct apr_socket_t;
-struct conn_rec;
-struct server_rec;
-
-namespace mod_spdy {
-
-class SlaveConnection;
-class SlaveConnectionContext;
-
-// SlaveConnectionFactory + SlaveConnection helps execute requests within
-// the current Apache process, with the request and response both going to
-// some other code and not an external client talking over TCP.
-//
-// SlaveConnectionFactory + SlaveConnection help create a fake Apache conn_rec
-// object and run it. That conn_rec will have a SlaveConnectionContext
-// attached to it, which various hooks in mod_spdy.cc will recognize and handle
-// specially. In particular, they will arrange to have the I/O for connection
-// routed to and from the input & output filters set on the
-// SlaveConnectionContext.
-class SlaveConnectionFactory {
- public:
- // Prepares the factory to create slave connections with endpoint, SPDY and
- // SSL information matching that of the master_connection.
- //
- // Does not retain any pointers to data from master_connection, so may be
- // used after master_connection is destroyed.
- explicit SlaveConnectionFactory(conn_rec* master_connection);
-
- ~SlaveConnectionFactory();
-
- // Creates a slave connection matching the settings in the constructor.
- // You should attach I/O filters on its GetSlaveConnectionContext() before
- // calling Run().
- //
- // The resulted object lives on the C++ heap, and must be deleted.
- SlaveConnection* Create();
-
- private:
- friend class SlaveConnection;
-
- // Saved information from master_connection
- bool is_using_ssl_;
- spdy::SpdyVersion spdy_version_;
- server_rec* base_server_;
- LocalPool pool_;
- // All of these are in pool_:
- apr_sockaddr_t* local_addr_;
- char* local_ip_;
- apr_sockaddr_t* remote_addr_;
- char* remote_ip_;
- long master_connection_id_;
-
- DISALLOW_COPY_AND_ASSIGN(SlaveConnectionFactory);
-};
-
-class SlaveConnection {
- public:
- ~SlaveConnection();
-
- // Returns the Apache conn_rec object this manages.
- conn_rec* apache_connection() { return slave_connection_; }
-
- // Returns the underlying SlaveConnectionContext, which lets you query
- // information about the connection and hook in I/O filters.
- //
- // This is the same as GetSlaveConnectionContext(apache_connection()), and
- // can thus be accessed via the conn_rec* as well.
- SlaveConnectionContext* GetSlaveConnectionContext();
-
- // Executes the requests associated with this connection, taking a request
- // from the input filter set on the SlaveConnectionContext(), and directing
- // the response to the output filter. Note that this is a blocking operation.
- void Run();
-
- private:
- SlaveConnection(SlaveConnectionFactory* factory);
- friend class SlaveConnectionFactory;
-
- LocalPool pool_;
- conn_rec* slave_connection_; // owned by pool_
- apr_socket_t* slave_socket_; // owned by pool_
- long master_connection_id_;
-
- DISALLOW_COPY_AND_ASSIGN(SlaveConnection);
-};
-
-} // namespace mod_spdy
-
-#endif /* MOD_SPDY_APACHE_SLAVE_CONNECTION_H_ */
+++ /dev/null
-/* 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.
- */
-
-#include "mod_spdy/apache/slave_connection_api.h"
-
-#include "base/memory/scoped_ptr.h"
-#include "mod_spdy/apache/slave_connection.h"
-#include "mod_spdy/apache/slave_connection_context.h"
-
-using mod_spdy::SlaveConnection;
-using mod_spdy::SlaveConnectionContext;
-using mod_spdy::SlaveConnectionFactory;
-
-struct spdy_slave_connection_factory {
- explicit spdy_slave_connection_factory(SlaveConnectionFactory* impl)
- : impl(impl) {}
- scoped_ptr<SlaveConnectionFactory> impl;
-};
-
-struct spdy_slave_connection {
- explicit spdy_slave_connection(SlaveConnection* impl)
- : impl(impl) {}
- scoped_ptr<SlaveConnection> impl;
-};
-
-spdy_slave_connection_factory* spdy_create_slave_connection_factory(
- conn_rec* master_connection) {
- return new spdy_slave_connection_factory(
- new SlaveConnectionFactory(master_connection));
-}
-
-void spdy_destroy_slave_connection_factory(
- spdy_slave_connection_factory* factory) {
- delete factory;
-}
-
-spdy_slave_connection* spdy_create_slave_connection(
- spdy_slave_connection_factory* factory,
- ap_filter_rec_t* input_filter,
- void* input_filter_ctx,
- ap_filter_rec_t* output_filter,
- void* output_filter_ctx) {
- spdy_slave_connection* wrapper =
- new spdy_slave_connection(factory->impl->Create());
-
- SlaveConnectionContext* ctx = wrapper->impl->GetSlaveConnectionContext();
- ctx->SetInputFilter(input_filter, input_filter_ctx);
- ctx->SetOutputFilter(output_filter, output_filter_ctx);
-
- return wrapper;
-}
-
-void spdy_run_slave_connection(spdy_slave_connection* conn) {
- conn->impl->Run();
-}
-
-void spdy_destroy_slave_connection(spdy_slave_connection* conn) {
- delete conn;
-}
-
-void ModSpdyExportSlaveConnectionFunctions() {
- APR_REGISTER_OPTIONAL_FN(spdy_create_slave_connection_factory);
- APR_REGISTER_OPTIONAL_FN(spdy_destroy_slave_connection_factory);
- APR_REGISTER_OPTIONAL_FN(spdy_create_slave_connection);
- APR_REGISTER_OPTIONAL_FN(spdy_run_slave_connection);
- APR_REGISTER_OPTIONAL_FN(spdy_destroy_slave_connection);
-}
+++ /dev/null
-/* 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.
- */
-
-/* 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_APACHE_SLAVE_CONNECTION_API_H_
-#define MOD_SPDY_APACHE_SLAVE_CONNECTION_API_H_
-
-#include "httpd.h"
-#include "apr_optional.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-struct ap_filter_rec_t;
-
-struct spdy_slave_connection_factory;
-struct spdy_slave_connection;
-
-/** Creates a factory object that can be used to make in-process pseudo-fetches
- * with the same origin and target hosts as in master_connection
- */
-APR_DECLARE_OPTIONAL_FN(
- struct spdy_slave_connection_factory*,
- spdy_create_slave_connection_factory, (conn_rec* master_connection));
-
-/** Destroys a factory object. */
-APR_DECLARE_OPTIONAL_FN(
- void, spdy_destroy_slave_connection_factory,
- (struct spdy_slave_connection_factory* factory));
-
-/** Asks mod_spdy to help with fetching a request on a slave connection.
- * The input_filter must produce the request, and output_filter must
- * handle the response. May return NULL if functionality is not available.
- * The request will not be run until spdy_run_slave_connection() is invoked.
- */
-APR_DECLARE_OPTIONAL_FN(
- struct spdy_slave_connection*,
- spdy_create_slave_connection, (
- struct spdy_slave_connection_factory* factory,
- struct ap_filter_rec_t* input_filter,
- void* input_filter_ctx,
- struct ap_filter_rec_t* output_filter,
- void* output_filter_ctx));
-
-/** Actually performs the fetch on the object. Blocks, perhaps for a significant
- * amount of time. */
-APR_DECLARE_OPTIONAL_FN(
- void, spdy_run_slave_connection, (struct spdy_slave_connection* conn));
-
-/** Cleans up the connection object. Must not be in active use. */
-APR_DECLARE_OPTIONAL_FN(
- void, spdy_destroy_slave_connection, (struct spdy_slave_connection*));
-
-/* Used by mod_spdy to setup the exports. Not exported itself */
-void ModSpdyExportSlaveConnectionFunctions(void);
-
-#ifdef __cplusplus
-} /* extern "C" */
-#endif
-
-#endif /* MOD_SPDY_APACHE_SLAVE_CONNECTION_API_H_ */
+++ /dev/null
-// 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.
-
-#include "mod_spdy/apache/slave_connection_context.h"
-
-#include "base/logging.h"
-#include "mod_spdy/common/spdy_stream.h"
-
-namespace mod_spdy {
-
-SlaveConnectionContext::SlaveConnectionContext()
- : using_ssl_(false),
- spdy_version_(spdy::SPDY_VERSION_NONE),
- slave_stream_(NULL),
- output_filter_handle_(NULL),
- output_filter_context_(NULL),
- input_filter_handle_(NULL),
- input_filter_context_(NULL) {
-}
-
-SlaveConnectionContext::~SlaveConnectionContext() {}
-
-void SlaveConnectionContext::SetOutputFilter(
- ap_filter_rec_t* handle, void* context) {
- output_filter_handle_ = handle;
- output_filter_context_ = context;
-}
-
-void SlaveConnectionContext::SetInputFilter(
- ap_filter_rec_t* handle, void* context) {
- input_filter_handle_ = handle;
- input_filter_context_ = context;
-}
-
-} // namespace mod_spdy
+++ /dev/null
-// 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.
-
-#ifndef MOD_SPDY_APACHE_SLAVE_CONNECTION_CONTEXT_H_
-#define MOD_SPDY_APACHE_SLAVE_CONNECTION_CONTEXT_H_
-
-#include <string>
-
-#include "base/basictypes.h"
-#include "base/memory/scoped_ptr.h"
-#include "mod_spdy/common/protocol_util.h"
-
-struct ap_filter_rec_t;
-
-namespace mod_spdy {
-
-class SpdyStream;
-
-// Context for a 'slave' connection in mod_spdy, used to represent a fetch
-// of a given URL from within Apache (as opposed to outgoing SPDY session to
-// the client, which has a ConnectionContext).
-class SlaveConnectionContext {
- public:
- SlaveConnectionContext();
- ~SlaveConnectionContext();
-
- // Return true if the connection to the user is over SSL. This is almost
- // always true, but may be false if we've been set to use SPDY for non-SSL
- // connections (for debugging). Note that for a slave connection, this
- // refers to whether the master network connection is using SSL.
- bool is_using_ssl() const { return using_ssl_; }
- void set_is_using_ssl(bool ssl_on) { using_ssl_ = ssl_on; }
-
- // Return the SpdyStream object associated with this slave connection.
- // Note that this may be NULL in case mod_spdy is acting on behalf of
- // another module. Not owned.
- SpdyStream* slave_stream() const { return slave_stream_; }
- void set_slave_stream(SpdyStream* stream) { slave_stream_ = stream; }
-
- // Return the SPDY version will be using, or SPDY_VERSION_NONE if we're not
- // using SPDY.
- spdy::SpdyVersion spdy_version() const { return spdy_version_; }
- void set_spdy_version(spdy::SpdyVersion version) { spdy_version_ = version; }
-
- // See SlaveConnection documentation for description of these.
- void SetOutputFilter(ap_filter_rec_t* handle, void* context);
- void SetInputFilter(ap_filter_rec_t* handle, void* context);
-
- ap_filter_rec_t* output_filter_handle() const {
- return output_filter_handle_;
- }
-
- void* output_filter_context() const {
- return output_filter_context_;
- }
-
- ap_filter_rec_t* input_filter_handle() const {
- return input_filter_handle_;
- }
-
- void* input_filter_context() const {
- return input_filter_context_;
- }
-
- private:
- // These are used to properly inform modules running on slave connections
- // on whether the connection should be treated as using SPDY and SSL.
- bool using_ssl_;
- spdy::SpdyVersion spdy_version_;
-
- // Used for SPDY push.
- SpdyStream* slave_stream_;
-
- // Filters to attach. These are set by clients of SlaveConnection
- // between creation and Run(), and read by mod_spdy's PreConnection hook,
- // where they are installed in Apache's filter chains.
- ap_filter_rec_t* output_filter_handle_;
- void* output_filter_context_;
-
- ap_filter_rec_t* input_filter_handle_;
- void* input_filter_context_;
-
- DISALLOW_COPY_AND_ASSIGN(SlaveConnectionContext);
-};
-
-} // namespace mod_spdy
-
-#endif // MOD_SPDY_APACHE_SLAVE_CONNECTION_CONTEXT_H_
+++ /dev/null
-// 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.
-
-#include "mod_spdy/apache/sockaddr_util.h"
-
-#include <cstddef> // for ptrdiff_t
-#include <cstring>
-
-#include "apr_strings.h"
-
-namespace mod_spdy {
-
-apr_sockaddr_t* DeepCopySockAddr(const apr_sockaddr_t* in, apr_pool_t* pool) {
- apr_sockaddr_t* out = static_cast<apr_sockaddr_t*>(
- apr_palloc(pool, sizeof(apr_sockaddr_t)));
- std::memcpy(out, in, sizeof(apr_sockaddr_t));
- out->pool = pool;
-
- if (in->hostname != NULL) {
- out->hostname = apr_pstrdup(pool, in->hostname);
- }
-
- if (in->servname != NULL) {
- out->servname = apr_pstrdup(pool, in->servname);
- }
-
- if (in->ipaddr_ptr != NULL) {
- // ipaddr_ptr points inside the struct, towards the bits containing
- // the actual IPv4/IPv6 address (e.g. to ->sa.sin.sin_addr or
- // ->sa.sin6.sin6_addr). We point to the same offset in 'out' as was used
- // in 'in'.
- ptrdiff_t ipaddr_ptr_offset =
- static_cast<char*>(in->ipaddr_ptr) - reinterpret_cast<const char*>(in);
- out->ipaddr_ptr = reinterpret_cast<char*>(out) + ipaddr_ptr_offset;
- }
-
- if (in->next != NULL) {
- out->next = DeepCopySockAddr(in->next, pool);
- }
-
- return out;
-}
-
-} // namespace mod_spdy
+++ /dev/null
-// 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.
-
-#ifndef MOD_SPDY_APACHE_SOCKADDR_UTIL_H_
-#define MOD_SPDY_APACHE_SOCKADDR_UTIL_H_
-
-#include "apr_pools.h"
-#include "apr_network_io.h"
-
-namespace mod_spdy {
-
-// Deep-copies the apr_sockaddr_t 'in', with the result being allocated in the
-// pool 'pool'.
-apr_sockaddr_t* DeepCopySockAddr(const apr_sockaddr_t* in, apr_pool_t* pool);
-
-} // namespace mod_spdy
-
-#endif // MOD_SPDY_APACHE_SOCKADDR_UTIL_H_
+++ /dev/null
-// 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.
-
-#include "mod_spdy/apache/sockaddr_util.h"
-
-#include "apr_strings.h"
-
-#include "base/basictypes.h"
-#include "mod_spdy/apache/pool_util.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace {
-
-void VerifySameAddr(apr_sockaddr_t* exp, apr_sockaddr_t* actual) {
- // apr_sockaddr_equal checks the actual IP (4 or 6) portion of the address,
- // and nothing else.
- EXPECT_NE(0, apr_sockaddr_equal(exp, actual));
-
- // Annoyingly this means we have to touch other fields directly.
- EXPECT_STREQ(exp->hostname, actual->hostname);
- EXPECT_STREQ(exp->servname, actual->servname);
- EXPECT_EQ(exp->port, actual->port);
- EXPECT_EQ(exp->salen, actual->salen);
- EXPECT_EQ(exp->ipaddr_len, actual->ipaddr_len);
- EXPECT_EQ(exp->addr_str_len, actual->addr_str_len);
-
- // next fields must both be either null or non-null.
- EXPECT_TRUE((exp->next == NULL) == (actual->next == NULL));
- if (exp->next != NULL) {
- VerifySameAddr(exp->next, actual->next);
- }
-}
-
-TEST(SockAddrUtilTest, CloneIpv4) {
- mod_spdy::LocalPool local, other;
-
- apr_sockaddr_t* original = NULL;
- ASSERT_EQ(APR_SUCCESS,
- apr_sockaddr_info_get(
- &original, "127.1.2.3", APR_INET, 80, 0, local.pool()));
- original->hostname = apr_pstrdup(local.pool(), "localhost");
- original->servname = apr_pstrdup(local.pool(), "http");
-
- apr_sockaddr_t* clone = mod_spdy::DeepCopySockAddr(original, other.pool());
- EXPECT_EQ(other.pool(), clone->pool);
- VerifySameAddr(original, clone);
-}
-
-TEST(SockAddrUtilTest, CloneIpv6) {
- mod_spdy::LocalPool local, other;
-
- // The IPv6 address below was that of example.com on 2012-07-20.
- apr_sockaddr_t* original = NULL;
- ASSERT_EQ(APR_SUCCESS,
- apr_sockaddr_info_get(
- &original, "2001:500:88:200::10", APR_INET6,
- 443, 0, local.pool()));
- original->hostname = apr_pstrdup(local.pool(), "example.com");
- original->servname = apr_pstrdup(local.pool(), "https");
-
- apr_sockaddr_t* clone = mod_spdy::DeepCopySockAddr(original, other.pool());
- EXPECT_EQ(other.pool(), clone->pool);
- VerifySameAddr(original, clone);
-}
-
-TEST(SockAddrUtilTest, Clone2Records) {
- // Test where ->next links an IpV4 record from IPv6 one.
- mod_spdy::LocalPool local, other;
-
- // Both addresses are of example.com as of 2012-07-20.
- apr_sockaddr_t* original = NULL;
- ASSERT_EQ(APR_SUCCESS,
- apr_sockaddr_info_get(
- &original, "2001:500:88:200::10", APR_INET6,
- 443, 0, local.pool()));
- original->hostname = apr_pstrdup(local.pool(), "example.com");
- original->servname = apr_pstrdup(local.pool(), "https");
-
- apr_sockaddr_t* original4 = NULL;
- ASSERT_EQ(APR_SUCCESS,
- apr_sockaddr_info_get(
- &original4, "192.0.43.10", APR_INET,
- 443, 0, local.pool()));
- original4->hostname = apr_pstrdup(local.pool(), "example.com");
- original4->servname = apr_pstrdup(local.pool(), "https");
- original->next = original4;
-
- apr_sockaddr_t* clone = mod_spdy::DeepCopySockAddr(original, other.pool());
- EXPECT_EQ(other.pool(), clone->pool);
- VerifySameAddr(original, clone);
-}
-
-} // namespace
+++ /dev/null
-// 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.
-
-#include "mod_spdy/apache/ssl_util.h"
-
-#include "apr_optional.h"
-#include "apr_optional_hooks.h"
-
-#include "base/logging.h"
-
-// This file contains some utility functions for communicating to mod_ssl.
-
-// Declaring mod_ssl's optional hooks here (so that we don't need mod_ssl.h).
-APR_DECLARE_OPTIONAL_FN(int, ssl_engine_disable, (conn_rec*));
-APR_DECLARE_OPTIONAL_FN(int, ssl_is_https, (conn_rec*));
-
-namespace mod_spdy {
-
-namespace {
-
-// These global variables store pointers to "optional functions" defined in
-// mod_ssl. See TAMB 10.1.2 for more about optional functions. These are
-// assigned just once, at start-up, so concurrency is not an issue.
-int (*gDisableSslForConnection)(conn_rec*) = NULL;
-int (*gIsUsingSslForConnection)(conn_rec*) = NULL;
-
-} // namespace
-
-void RetrieveModSslFunctions() {
- gDisableSslForConnection = APR_RETRIEVE_OPTIONAL_FN(ssl_engine_disable);
- gIsUsingSslForConnection = APR_RETRIEVE_OPTIONAL_FN(ssl_is_https);
- // If mod_ssl isn't installed, we'll get back NULL for these functions. Our
- // other hook functions will fail gracefully (i.e. do nothing) if these
- // functions are NULL, but if the user installed mod_spdy without mod_ssl and
- // expected it to do anything, we should warn them otherwise.
- //
- // Note: Alternatively, it may be that there's no mod_ssl, but mod_spdy has
- // been configured to assume SPDY for non-SSL connections, in which case this
- // warning is untrue. But there's no easy way to check the server config
- // from here, and normal users should never use that config option anyway
- // (it's for debugging), so I don't think the spurious warning is a big deal.
- if (gDisableSslForConnection == NULL &&
- gIsUsingSslForConnection == NULL) {
- LOG(WARNING) << "It seems that mod_spdy is installed but mod_ssl isn't. "
- << "Without SSL, the server cannot ever use SPDY.";
- }
- // Whether or not mod_ssl is installed, either both functions should be
- // non-NULL or both functions should be NULL. Otherwise, something is wrong
- // (like, maybe some kind of bizarre mutant mod_ssl is installed) and
- // mod_spdy probably won't work correctly.
- if ((gDisableSslForConnection == NULL) ^
- (gIsUsingSslForConnection == NULL)) {
- LOG(DFATAL) << "Some, but not all, of mod_ssl's optional functions are "
- << "available. What's going on?";
- }
-}
-
-bool DisableSslForConnection(conn_rec* connection) {
- return (gDisableSslForConnection != NULL) &&
- (gDisableSslForConnection(connection) != 0);
-}
-
-bool IsUsingSslForConnection(conn_rec* connection) {
- return (gIsUsingSslForConnection != NULL) &&
- (gIsUsingSslForConnection(connection) != 0);
-}
-
-} // namespace mod_spdy
+++ /dev/null
-// 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.
-
-#ifndef MOD_SPDY_APACHE_SSL_UTIL_H_
-#define MOD_SPDY_APACHE_SSL_UTIL_H_
-
-// This file contains some utility functions for communicating to mod_ssl.
-
-struct conn_rec;
-
-namespace mod_spdy {
-
-// This must be called from optional_fn_retrieve hook at startup before
-// using any of the methods below.
-void RetrieveModSslFunctions();
-
-// Disables SSL on a connection. Returns true if successful, false if failed
-// for some reason (such as the optional function not being available, or
-// mod_ssl indicating a problem).
-bool DisableSslForConnection(conn_rec* connection);
-
-// Returns true if the given connection is using SSL. Note that this answers
-// whether the connection is really using SSL rather than whether we should tell
-// others that it is. This distinction matters for slave connection belonging to
-// an SSL master --- we're not really using SSL for them (so this method
-// will return false), but will claim we are (since they'll be encrypted once
-// going to other outside world).
-bool IsUsingSslForConnection(conn_rec* connection);
-
-} // namespace mod_spdy
-
-#endif // MOD_SPDY_APACHE_SSL_UTIL_H_
+++ /dev/null
-// Copyright 2012 Google Inc. All Rights Reserved.
-//
-// 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.
-
-#include "httpd.h"
-#include "apr_buckets.h"
-#include "util_filter.h"
-
-// For unit tests, we don't link in Apache's util_filter.c, which defines the
-// below functions. To make our lives easier, we define dummy versions of them
-// here that simply report success.
-
-extern "C" {
-
-AP_DECLARE(apr_status_t) ap_pass_brigade(
- ap_filter_t* filter, apr_bucket_brigade* bucket) {
- return APR_SUCCESS;
-}
-
-AP_DECLARE(void) ap_remove_output_filter(ap_filter_t* filter) {}
-
-} // extern "C"
+++ /dev/null
-// Copyright 2011 Google Inc. All Rights Reserved.
-//
-// 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.
-
-#include <iostream>
-
-#include "apr_general.h"
-
-#include "base/basictypes.h"
-#include "base/logging.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace {
-
-// Class to ensure that APR gets initialized and torn down.
-class AprInitializer {
- public:
- AprInitializer() {
- const apr_status_t status = apr_initialize();
- CHECK(status == APR_SUCCESS) << "APR initialization failed.";
- }
- ~AprInitializer() {
- apr_terminate();
- }
- private:
- DISALLOW_COPY_AND_ASSIGN(AprInitializer);
-};
-
-} // namespace
-
-int main(int argc, char **argv) {
- std::cout << "Running main() from spdy_apache_test_main.cc\n";
- testing::InitGoogleTest(&argc, argv);
- AprInitializer apr_initializer;
- return RUN_ALL_TESTS();
-}
+++ /dev/null
-MAJOR=0
-MINOR=1
-BUILD=0
-PATCH=0
+++ /dev/null
-// 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.
-
-#include "mod_spdy/common/executor.h"
-
-namespace mod_spdy {
-
-Executor::Executor() {}
-
-Executor::~Executor() {}
-
-} // namespace mod_spdy
+++ /dev/null
-// 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.
-
-#ifndef MOD_SPDY_COMMON_EXECUTOR_H_
-#define MOD_SPDY_COMMON_EXECUTOR_H_
-
-#include "base/basictypes.h"
-#include "net/spdy/spdy_protocol.h"
-
-namespace net_instaweb { class Function; }
-
-namespace mod_spdy {
-
-// An interface for a service that can execute tasks. A thread pool (using
-// net_instaweb::QueuedWorkerPool or an apr_thread_pool_t) would be one obvious
-// implementation. In the future we may want to adjust this interface for use
-// in an event-driven environment (e.g. Nginx).
-class Executor {
- public:
- Executor();
- virtual ~Executor();
-
- // Add a new task to be run; the executor takes ownership of the task. The
- // priority argument hints at how important this task is to get done, but the
- // executor is free to ignore it. If Stop has already been called, the
- // executor may immediately cancel the task rather than running it.
- virtual void AddTask(net_instaweb::Function* task,
- net::SpdyPriority priority) = 0;
-
- // Stop the executor. Cancel all tasks that were pushed onto this executor
- // but that have not yet begun to run. Tasks that were already running will
- // continue to run, and this function must block until they have completed.
- // It must be safe to call this method more than once.
- virtual void Stop() = 0;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(Executor);
-};
-
-} // namespace mod_spdy
-
-#endif // MOD_SPDY_COMMON_EXECUTOR_H_
+++ /dev/null
-// 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.
-
-#include "mod_spdy/common/http_request_visitor_interface.h"
-
-namespace mod_spdy {
-
-HttpRequestVisitorInterface::HttpRequestVisitorInterface() {}
-HttpRequestVisitorInterface::~HttpRequestVisitorInterface() {}
-
-} // namespace mod_spdy
+++ /dev/null
-// 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.
-
-#ifndef MOD_SPDY_COMMON_HTTP_REQUEST_VISITOR_INTERFACE_H_
-#define MOD_SPDY_COMMON_HTTP_REQUEST_VISITOR_INTERFACE_H_
-
-#include "base/basictypes.h"
-#include "base/strings/string_piece.h"
-
-namespace mod_spdy {
-
-// Interface that gets called back as an HTTP stream is visited.
-class HttpRequestVisitorInterface {
- public:
- HttpRequestVisitorInterface();
- virtual ~HttpRequestVisitorInterface();
-
- // Called when an HTTP request line is visited. Indicates that a new HTTP
- // request is being visited.
- virtual void OnRequestLine(const base::StringPiece& method,
- const base::StringPiece& path,
- const base::StringPiece& version) = 0;
-
- // Called zero or more times, once for each leading (i.e. normal, not
- // trailing) HTTP header. This is called after OnRequestLine but before
- // OnLeadingHeadersComplete.
- virtual void OnLeadingHeader(const base::StringPiece& key,
- const base::StringPiece& value) = 0;
-
- // Called after the leading HTTP headers have been visited. This will be
- // called exactly once when the leading headers are done (even if there were
- // no leading headers).
- virtual void OnLeadingHeadersComplete() = 0;
-
- // Called zero or more times, after OnLeadingHeadersComplete. This method is
- // mutually exclusive with OnDataChunk and OnDataChunksComplete; either data
- // will be raw or chunked, but not both. If raw data is used, there cannot
- // be trailing headers; the raw data section will be terminated by the call
- // to OnComplete.
- virtual void OnRawData(const base::StringPiece& data) = 0;
-
- // Called zero or more times, after OnLeadingHeadersComplete, once for each
- // "chunk" of the HTTP body. This method is mutually exclusive with
- // OnRawData; either data will be raw or chunked, but not both.
- virtual void OnDataChunk(const base::StringPiece& data) = 0;
-
- // Called when there will be no more data chunks. There may still be
- // trailing headers, however. This method is mutually exclusive with
- // OnRawData; either data will be raw or chunked, but not both.
- virtual void OnDataChunksComplete() = 0;
-
- // Called zero or more times, once for each trailing header. This is called
- // after OnDataChunksComplete but before OnTrailingHeadersComplete. It
- // cannot be called if OnRawData was used.
- virtual void OnTrailingHeader(const base::StringPiece& key,
- const base::StringPiece& value) = 0;
-
- // Called after all the trailing HTTP headers have been visited. If there
- // were any trailing headers, this will definitely be called; if there were
- // no trailing headers, it is optional.
- virtual void OnTrailingHeadersComplete() = 0;
-
- // Called once when the HTTP request is totally done. This is called
- // immediately after one of OnLeadingHeadersComplete, OnRawData,
- // OnDataChunksComplete, or OnTrailingHeadersComplete. After this, no more
- // methods will be called.
- virtual void OnComplete() = 0;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(HttpRequestVisitorInterface);
-};
-
-} // namespace mod_spdy
-
-#endif // MOD_SPDY_COMMON_HTTP_REQUEST_VISITOR_INTERFACE_H_
+++ /dev/null
-// 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.
-
-#include "mod_spdy/common/http_response_parser.h"
-
-#include <string>
-
-#include "base/logging.h"
-#include "base/strings/string_number_conversions.h"
-#include "base/strings/string_piece.h"
-#include "base/strings/string_util.h"
-#include "mod_spdy/common/http_response_visitor_interface.h"
-#include "mod_spdy/common/protocol_util.h"
-
-namespace {
-
-// If the given position in the string is npos, then return the position of the
-// end of the string; otherwise, return the given position unchanged.
-size_t NposToEnd(const base::StringPiece& str, size_t pos) {
- return pos == base::StringPiece::npos ? str.size() : pos;
-}
-
-} // namespace
-
-namespace mod_spdy {
-
-HttpResponseParser::HttpResponseParser(HttpResponseVisitorInterface* visitor)
- : visitor_(visitor),
- state_(STATUS_LINE),
- body_type_(NO_BODY),
- remaining_bytes_(0) {}
-
-HttpResponseParser::~HttpResponseParser() {}
-
-bool HttpResponseParser::ProcessInput(const base::StringPiece& input_data) {
- // Keep track of the slice of data we are currently looking at. We will
- // modify this variable as we go.
- base::StringPiece data = input_data;
-
- size_t last_length = data.size() + 1;
- while (!data.empty()) {
- // Safety check to avoid infinite loops in case our code is buggy; the
- // slice of data we are looking at should get strictly smaller on every
- // iteration of this loop.
- if (data.size() >= last_length) {
- LOG(DFATAL) << "Potential infinite loop.";
- return false;
- }
- last_length = data.size();
-
- // Process the data based on our current parser state. Most of these
- // methods receive a pointer to `data` and will mutate it as they consume
- // bytes. We continue looping until the whole input_data is consumed.
- switch (state_) {
- case STATUS_LINE:
- if (!ProcessStatusLine(&data)) {
- return false;
- }
- break;
- case LEADING_HEADERS_CHECK_NEXT_LINE:
- if (!CheckStartOfHeaderLine(data)) {
- return false;
- }
- // fallthrough
- case LEADING_HEADERS:
- if (!ProcessLeadingHeaders(&data)) {
- return false;
- }
- break;
- case CHUNK_START:
- if (!ProcessChunkStart(&data)) {
- return false;
- }
- break;
- case BODY_DATA:
- if (!ProcessBodyData(&data)) {
- return false;
- }
- break;
- case CHUNK_ENDING:
- if (!ProcessChunkEnding(&data)) {
- return false;
- }
- break;
- case COMPLETE:
- DCHECK(buffer_.empty());
- return true;
- default:
- LOG(DFATAL) << "Invalid parser state: " << state_;
- return false;
- }
- }
- return true;
-}
-
-bool HttpResponseParser::ProcessStatusLine(base::StringPiece* data) {
- DCHECK(state_ == STATUS_LINE);
- const size_t linebreak = data->find("\r\n");
-
- // If we haven't reached the end of the line yet, buffer the data and quit.
- if (linebreak == base::StringPiece::npos) {
- data->AppendToString(&buffer_);
- *data = base::StringPiece();
- return true;
- }
-
- // Combine the data up to the linebreak with what we've buffered, and parse
- // the status line out of it.
- data->substr(0, linebreak).AppendToString(&buffer_);
- if (!ParseStatusLine(buffer_)) {
- return false;
- }
- buffer_.clear();
-
- // Chop off the linebreak and all data before it, and move on to parsing the
- // leading headers.
- *data = data->substr(linebreak + 2);
- state_ = LEADING_HEADERS;
- return true;
-}
-
-bool HttpResponseParser::CheckStartOfHeaderLine(const base::StringPiece& data){
- // This state is for when we have a complete header line buffered, and we
- // need to check the next line to see if it starts with leading whitespace.
- DCHECK(state_ == LEADING_HEADERS_CHECK_NEXT_LINE);
- DCHECK(!buffer_.empty());
- DCHECK(!data.empty());
-
- // If this line _doesn't_ start with whitespace, then the buffered line is a
- // complete header line, so we should parse it and clear the buffer.
- // Otherwise, this next line is a continuation of the header, so we need to
- // buffer more data.
- const char first = data[0];
- if (first != ' ' && first != '\t') {
- if (!ParseLeadingHeader(buffer_)) {
- return false;
- }
- buffer_.clear();
- }
-
- // Either way, we're ready to continuing parsing headers.
- state_ = LEADING_HEADERS;
- return true;
-}
-
-bool HttpResponseParser::ProcessLeadingHeaders(base::StringPiece* data) {
- DCHECK(state_ == LEADING_HEADERS);
- const size_t linebreak = data->find("\r\n");
-
- // If we haven't reached the end of the line yet, buffer the data and quit.
- if (linebreak == base::StringPiece::npos) {
- data->AppendToString(&buffer_);
- *data = base::StringPiece();
- return true;
- }
-
- // If we're not in the middle of a header line (buffer is empty) and the
- // linebreak comes at the very beginning, this must be the blank line that
- // signals the end of the leading headers. Skip the linebreak, switch states
- // depending on what headers we saw (Is there body data? Is it chunked?),
- // and return.
- if (linebreak == 0 && buffer_.empty()) {
- switch (body_type_) {
- case CHUNKED_BODY:
- state_ = CHUNK_START;
- break;
- case UNCHUNKED_BODY:
- state_ = BODY_DATA;
- break;
- case NO_BODY:
- state_ = COMPLETE;
- break;
- default:
- LOG(DFATAL) << "Invalid body type: " << body_type_;
- return false;
- }
- visitor_->OnLeadingHeadersComplete(state_ == COMPLETE);
- *data = data->substr(linebreak + 2);
- return true;
- }
-
- // We've reached the end of the line, but we need to check the next line to
- // see if it's a continuation of this header. Buffer up to the linebreak,
- // skip the linebreak itself, and set our state to check the next line.
- data->substr(0, linebreak).AppendToString(&buffer_);
- *data = data->substr(linebreak + 2);
- state_ = LEADING_HEADERS_CHECK_NEXT_LINE;
- return true;
-}
-
-bool HttpResponseParser::ProcessChunkStart(base::StringPiece* data) {
- DCHECK(state_ == CHUNK_START);
- const size_t linebreak = data->find("\r\n");
-
- // If we haven't reached the end of the line yet, buffer the data and quit.
- if (linebreak == base::StringPiece::npos) {
- data->AppendToString(&buffer_);
- *data = base::StringPiece();
- return true;
- }
-
- // Combine the data up to the linebreak with what we've buffered, and parse
- // the chunk length out of it.
- data->substr(0, linebreak).AppendToString(&buffer_);
- if (!ParseChunkStart(buffer_)) {
- return false;
- }
- buffer_.clear();
-
- // Skip the linebreak.
- *data = data->substr(linebreak + 2);
-
- // ParseChunkStart will put the size of the chunk into remaining_bytes_. If
- // the chunk size is zero, that means we've reached the end of the body data.
- // Otherwise, we now need to read the data in this chunk.
- if (remaining_bytes_ == 0) {
- state_ = COMPLETE;
- visitor_->OnData(base::StringPiece(), true);
- } else {
- state_ = BODY_DATA;
- }
- return true;
-}
-
-bool HttpResponseParser::ProcessBodyData(base::StringPiece* data) {
- DCHECK(state_ == BODY_DATA);
-
- // We never buffer anything when reading the body data. This minimizes how
- // much string copying we need to do for most responses.
- DCHECK(buffer_.empty());
-
- // If the available data is less that what remains of this chunk (if the data
- // is chunked) or of the whole body (if there was instead an explicit
- // content-length), then read in all the data we have and subtract from
- // remaining_bytes_.
- if (data->size() < remaining_bytes_) {
- visitor_->OnData(*data, false);
- remaining_bytes_ -= data->size();
- *data = base::StringPiece();
- }
- // Otherwise, we have enough data here to fulfill remaining_bytes_, so read
- // in that much data, and then switch states depending on whether we're using
- // chunking or not.
- else {
- if (body_type_ == CHUNKED_BODY) {
- state_ = CHUNK_ENDING;
- } else {
- DCHECK(body_type_ == UNCHUNKED_BODY);
- state_ = COMPLETE;
- }
- visitor_->OnData(data->substr(0, remaining_bytes_), state_ == COMPLETE);
- *data = data->substr(remaining_bytes_);
- remaining_bytes_ = 0;
- }
- return true;
-}
-
-bool HttpResponseParser::ProcessChunkEnding(base::StringPiece* data) {
- DCHECK(state_ == CHUNK_ENDING);
- // For whatever reason, HTTP requires each chunk to end with a CRLF. So,
- // make sure it's there, and then skip it, before moving on to read the next
- // chunk.
- if (!data->starts_with("\r\n")) {
- VLOG(1) << "Expected CRLF at end of chunk.";
- return false;
- }
- *data = data->substr(2);
- state_ = CHUNK_START;
- return true;
-}
-
-bool HttpResponseParser::ParseStatusLine(const base::StringPiece& text) {
- // An HTTP status line should look like:
- // <HTTP version> <single space> <status code> <single space> <status phrase>
- // For example, "HTTP/1.1 301 Moved permenantly".
- // We'll be a little more lenient just in case, and allow multiple spaces
- // between each part, and allow the phrase to be omitted.
- const size_t first_space = text.find(' ');
- if (first_space == base::StringPiece::npos) {
- VLOG(1) << "Bad status line: " << text;
- return false;
- }
- const size_t start_of_code = text.find_first_not_of(' ', first_space);
- if (start_of_code == base::StringPiece::npos) {
- VLOG(1) << "Bad status line: " << text;
- return false;
- }
- const size_t second_space = NposToEnd(text, text.find(' ', start_of_code));
- const size_t start_of_phrase =
- NposToEnd(text, text.find_first_not_of(' ', second_space));
-
- visitor_->OnStatusLine(
- text.substr(0, first_space),
- text.substr(start_of_code, second_space - start_of_code),
- text.substr(start_of_phrase));
- return true;
-}
-
-bool HttpResponseParser::ParseLeadingHeader(const base::StringPiece& text) {
- // Even for multiline headers, we strip out the CRLFs, so there shouldn't be
- // any left in the text that we're parsing.
- DCHECK(text.find("\r\n") == base::StringPiece::npos);
-
- // Find the colon separating the key from the value, and skip any leading
- // whitespace between the colon and the value.
- const size_t colon = text.find(':');
- if (colon == base::StringPiece::npos) {
- VLOG(1) << "Bad header line: " << text;
- return false;
- }
- const size_t value_start =
- NposToEnd(text, text.find_first_not_of(" \t", colon + 1));
-
- const base::StringPiece key = text.substr(0, colon);
- const base::StringPiece value = text.substr(value_start);
-
- // We need to check the Content-Length and Transfer-Encoding headers to know
- // if we're using chunking, and if not, how long the body is.
- if (LowerCaseEqualsASCII(key.begin(), key.end(), http::kTransferEncoding)) {
- if (value == http::kChunked) {
- body_type_ = CHUNKED_BODY;
- }
- } else if (body_type_ != CHUNKED_BODY &&
- LowerCaseEqualsASCII(key.begin(), key.end(),
- http::kContentLength)) {
- uint64 uint_value = 0u;
- if (base::StringToUint64(value, &uint_value) && uint_value > 0u) {
- remaining_bytes_ = uint_value;
- body_type_ = UNCHUNKED_BODY;
- } else {
- VLOG(1) << "Bad content-length: " << value;
- }
- }
-
- visitor_->OnLeadingHeader(key, value);
- return true;
-}
-
-bool HttpResponseParser::ParseChunkStart(const base::StringPiece& text) {
- // The line at the start of each chunk consists of the chunk length in
- // hexadecimal, potentially followed by chunk-extension metadata that we
- // don't care about anyway. So just parse out the hex number and ignore the
- // rest.
- const size_t length =
- NposToEnd(text, text.find_first_not_of("0123456789abcdefABCDEF"));
- int int_value = 0;
- if (!base::HexStringToInt(text.substr(0, length), &int_value) ||
- int_value < 0) {
- VLOG(1) << "Bad chunk line: " << text;
- return false;
- }
- remaining_bytes_ = static_cast<size_t>(int_value);
- return true;
-}
-
-} // namespace mod_spdy
+++ /dev/null
-// 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.
-
-#ifndef MOD_SPDY_COMMON_HTTP_RESPONSE_PARSER_H_
-#define MOD_SPDY_COMMON_HTTP_RESPONSE_PARSER_H_
-
-#include <string>
-
-#include "base/basictypes.h"
-#include "base/strings/string_piece.h"
-
-namespace mod_spdy {
-
-class HttpResponseVisitorInterface;
-
-// Parses incoming HTTP response data. Data is fed in piece by piece with the
-// ProcessInput method, and appropriate methods are called on the visitor.
-// There is no need to indicate the end of the input, as this is inferred from
-// the Content-Length or Transfer-Encoding headers. If the response uses
-// chunked encoding, the parser will de-chunk it. Note that all data after the
-// end of the response body, including trailing headers, will be completely
-// ignored.
-class HttpResponseParser {
- public:
- explicit HttpResponseParser(HttpResponseVisitorInterface* visitor);
- ~HttpResponseParser();
-
- // Return true on success, false on failure.
- bool ProcessInput(const base::StringPiece& input_data);
- bool ProcessInput(const char* data, size_t size) {
- return ProcessInput(base::StringPiece(data, size));
- }
-
- // For unit testing only: Get the remaining number of bytes expected (in the
- // whole response, if we used Content-Length, or just in the current chunk,
- // if we used Transfer-Encoding: chunked).
- uint64 GetRemainingBytesForTest() const { return remaining_bytes_; }
-
- private:
- enum ParserState {
- STATUS_LINE,
- LEADING_HEADERS,
- LEADING_HEADERS_CHECK_NEXT_LINE,
- CHUNK_START,
- BODY_DATA,
- CHUNK_ENDING,
- COMPLETE
- };
-
- enum BodyType {
- NO_BODY,
- UNCHUNKED_BODY,
- CHUNKED_BODY
- };
-
- bool ProcessStatusLine(base::StringPiece* data);
- bool CheckStartOfHeaderLine(const base::StringPiece& data);
- bool ProcessLeadingHeaders(base::StringPiece* data);
- bool ProcessChunkStart(base::StringPiece* data);
- bool ProcessBodyData(base::StringPiece* data);
- bool ProcessChunkEnding(base::StringPiece* data);
-
- bool ParseStatusLine(const base::StringPiece& text);
- bool ParseLeadingHeader(const base::StringPiece& text);
- bool ParseChunkStart(const base::StringPiece& text);
-
- HttpResponseVisitorInterface* const visitor_;
- ParserState state_;
- BodyType body_type_;
- uint64 remaining_bytes_;
- std::string buffer_;
-
- DISALLOW_COPY_AND_ASSIGN(HttpResponseParser);
-};
-
-} // namespace mod_spdy
-
-#endif // MOD_SPDY_COMMON_HTTP_RESPONSE_PARSER_H_
+++ /dev/null
-// Copyright 2011 Google Inc. All Rights Reserved.
-//
-// 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.
-
-#include "mod_spdy/common/http_response_parser.h"
-
-#include "base/strings/string_piece.h"
-#include "mod_spdy/common/http_response_visitor_interface.h"
-#include "testing/gmock/include/gmock/gmock.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-using mod_spdy::HttpResponseParser;
-using testing::Eq;
-using testing::InSequence;
-
-namespace {
-
-class MockHttpResponseVisitor: public mod_spdy::HttpResponseVisitorInterface {
- public:
- MOCK_METHOD3(OnStatusLine, void(const base::StringPiece&,
- const base::StringPiece&,
- const base::StringPiece&));
- MOCK_METHOD2(OnLeadingHeader, void(const base::StringPiece&,
- const base::StringPiece&));
- MOCK_METHOD1(OnLeadingHeadersComplete, void(bool));
- MOCK_METHOD2(OnData, void(const base::StringPiece&, bool));
-};
-
-class HttpResponseParserTest : public testing::Test {
- public:
- HttpResponseParserTest() : parser_(&visitor_) {}
-
- protected:
- MockHttpResponseVisitor visitor_;
- HttpResponseParser parser_;
-};
-
-TEST_F(HttpResponseParserTest, SimpleWithContentLength) {
- InSequence seq;
- EXPECT_CALL(visitor_, OnStatusLine(Eq("HTTP/1.1"), Eq("200"), Eq("OK")));
- EXPECT_CALL(visitor_, OnLeadingHeader(Eq("Content-Length"), Eq("14")));
- EXPECT_CALL(visitor_, OnLeadingHeader(Eq("Content-Type"), Eq("text/plain")));
- EXPECT_CALL(visitor_, OnLeadingHeader(Eq("X-Whatever"), Eq("foobar")));
- EXPECT_CALL(visitor_, OnLeadingHeadersComplete(Eq(false)));
- EXPECT_CALL(visitor_, OnData(Eq("Hello, world!\n"), Eq(true)));
-
- ASSERT_TRUE(parser_.ProcessInput(
- "HTTP/1.1 200 OK\r\n"
- "Content-Length: 14\r\n"
- "Content-Type: text/plain\r\n"
- "X-Whatever:foobar\r\n"
- "\r\n"
- "Hello, world!\n"
- "\r\n"));
-}
-
-TEST_F(HttpResponseParserTest, SimpleWithChunkedData) {
- InSequence seq;
- EXPECT_CALL(visitor_, OnStatusLine(Eq("HTTP/1.1"), Eq("200"), Eq("OK")));
- EXPECT_CALL(visitor_, OnLeadingHeader(
- Eq("Transfer-Encoding"), Eq("chunked")));
- EXPECT_CALL(visitor_, OnLeadingHeader(Eq("Content-Type"), Eq("text/plain")));
- EXPECT_CALL(visitor_, OnLeadingHeadersComplete(Eq(false)));
- EXPECT_CALL(visitor_, OnData(Eq("Hello, world!\n"), Eq(false)));
- EXPECT_CALL(visitor_, OnData(Eq("It sure is good to see you today."),
- Eq(false)));
- EXPECT_CALL(visitor_, OnData(Eq(""), Eq(true)));
-
- ASSERT_TRUE(parser_.ProcessInput(
- "HTTP/1.1 200 OK\r\n"
- "Transfer-Encoding: chunked\r\n"
- "Content-Type: text/plain\r\n"
- "\r\n"
- "E\r\n"
- "Hello, world!\n\r\n"
- "21; some-random-chunk-extension\r\n"
- "It sure is good to see you today.\r\n"
- "0\r\n"
- "\r\n"));
-}
-
-// Check that Transfer-Encoding: chunked supersedes Content-Length.
-TEST_F(HttpResponseParserTest, ContentLengthAndTransferEncoding) {
- InSequence seq;
- EXPECT_CALL(visitor_, OnStatusLine(Eq("HTTP/1.1"), Eq("200"), Eq("OK")));
- EXPECT_CALL(visitor_, OnLeadingHeader(Eq("Content-Length"), Eq("3")));
- EXPECT_CALL(visitor_, OnLeadingHeader(
- Eq("Transfer-Encoding"), Eq("chunked")));
- EXPECT_CALL(visitor_, OnLeadingHeadersComplete(Eq(false)));
- EXPECT_CALL(visitor_, OnData(Eq("Hello,"), Eq(false)));
- EXPECT_CALL(visitor_, OnData(Eq(" world!\n"), Eq(false)));
- EXPECT_CALL(visitor_, OnData(Eq(""), Eq(true)));
-
- ASSERT_TRUE(parser_.ProcessInput(
- "HTTP/1.1 200 OK\r\n"
- "Content-Length: 3\r\n"
- "Transfer-Encoding: chunked\r\n"
- "\r\n"
- "6\r\n"
- "Hello,\r\n"
- "8\r\n"
- " world!\n\r\n"
- "0\r\n"
- "\r\n"));
-}
-
-// Check that Transfer-Encoding: chunked supersedes Content-Length even if
-// Content-Length comes later.
-TEST_F(HttpResponseParserTest, TransferEncodingAndContentLength) {
- InSequence seq;
- EXPECT_CALL(visitor_, OnStatusLine(Eq("HTTP/1.1"), Eq("200"), Eq("OK")));
- EXPECT_CALL(visitor_, OnLeadingHeader(
- Eq("Transfer-Encoding"), Eq("chunked")));
- EXPECT_CALL(visitor_, OnLeadingHeader(Eq("Content-Length"), Eq("3")));
- EXPECT_CALL(visitor_, OnLeadingHeadersComplete(Eq(false)));
- EXPECT_CALL(visitor_, OnData(Eq("Hello,"), Eq(false)));
- EXPECT_CALL(visitor_, OnData(Eq(" world!\n"), Eq(false)));
- EXPECT_CALL(visitor_, OnData(Eq(""), Eq(true)));
-
- ASSERT_TRUE(parser_.ProcessInput(
- "HTTP/1.1 200 OK\r\n"
- "Transfer-Encoding: chunked\r\n"
- "Content-Length: 3\r\n"
- "\r\n"
- "6\r\n"
- "Hello,\r\n"
- "8\r\n"
- " world!\n\r\n"
- "0\r\n"
- "\r\n"));
-}
-
-TEST_F(HttpResponseParserTest, NoBodyData) {
- InSequence seq;
- EXPECT_CALL(visitor_, OnStatusLine(Eq("HTTP/1.1"), Eq("301"),
- Eq("Moved permenantly")));
- EXPECT_CALL(visitor_, OnLeadingHeader(Eq("X-Empty"), Eq("")));
- EXPECT_CALL(visitor_, OnLeadingHeader(Eq("Location"), Eq("/foo/bar.html")));
- EXPECT_CALL(visitor_, OnLeadingHeadersComplete(Eq(true)));
-
- ASSERT_TRUE(parser_.ProcessInput(
- "HTTP/1.1 301 Moved permenantly\r\n"
- "X-Empty:\r\n"
- "Location: /foo/bar.html\r\n"
- "\r\n"));
-}
-
-TEST_F(HttpResponseParserTest, NoStatusPhrase) {
- InSequence seq;
- EXPECT_CALL(visitor_, OnStatusLine(Eq("HTTP/1.1"), Eq("123"), Eq("")));
- EXPECT_CALL(visitor_, OnLeadingHeadersComplete(Eq(true)));
-
- ASSERT_TRUE(parser_.ProcessInput(
- "HTTP/1.1 123\r\n"
- "\r\n"));
-}
-
-TEST_F(HttpResponseParserTest, HeadersBrokenAcrossLines) {
- InSequence seq;
- EXPECT_CALL(visitor_, OnStatusLine(Eq("HTTP/1.1"), Eq("301"),
- Eq("Moved permenantly")));
- EXPECT_CALL(visitor_, OnLeadingHeader(
- Eq("X-NextLine"), Eq("Alas, this is legal HTTP.")));
- EXPECT_CALL(visitor_, OnLeadingHeader(Eq("Location"), Eq("/foo/bar.html")));
- EXPECT_CALL(visitor_, OnLeadingHeader(
- Eq("X-ThreeLines"), Eq("foo bar baz quux")));
- EXPECT_CALL(visitor_, OnLeadingHeadersComplete(Eq(true)));
-
- ASSERT_TRUE(parser_.ProcessInput(
- "HTTP/1.1 301 Moved permenantly\r\n"
- "X-NextLine:\r\n"
- "\tAlas, this is legal HTTP.\r\n"
- "Location: /foo/bar.html\r\n"
- "X-ThreeLines: foo\r\n"
- " bar baz \r\n"
- " quux\r\n"
- "\r\n"));
-}
-
-TEST_F(HttpResponseParserTest, DividedUpIntoPieces) {
- InSequence seq;
- EXPECT_CALL(visitor_, OnStatusLine(Eq("HTTP/1.1"), Eq("418"),
- Eq("I'm a teapot")));
- EXPECT_CALL(visitor_, OnLeadingHeader(
- Eq("tRaNsFeR-EnCoDiNg"), Eq("chunked")));
- EXPECT_CALL(visitor_, OnLeadingHeader(Eq("X-TwoLines"), Eq("foo bar")));
- EXPECT_CALL(visitor_, OnLeadingHeader(Eq("Content-Type"), Eq("text/plain")));
- EXPECT_CALL(visitor_, OnLeadingHeadersComplete(Eq(false)));
- EXPECT_CALL(visitor_, OnData(Eq("Hello,"), Eq(false)));
- EXPECT_CALL(visitor_, OnData(Eq(" world!\n"), Eq(false)));
- EXPECT_CALL(visitor_, OnData(Eq("It sure"), Eq(false)));
- EXPECT_CALL(visitor_, OnData(Eq(" is good to see you today."), Eq(false)));
- EXPECT_CALL(visitor_, OnData(Eq(""), Eq(true)));
-
- ASSERT_TRUE(parser_.ProcessInput("HTTP/1.1 418 I'm"));
- ASSERT_TRUE(parser_.ProcessInput(" a teapot\r\ntRaNsFeR-EnCoDiNg:"));
- ASSERT_TRUE(parser_.ProcessInput("chunked\r\n"));
- ASSERT_TRUE(parser_.ProcessInput("X-TwoLines:\tfoo "));
- ASSERT_TRUE(parser_.ProcessInput("\r\n"));
- ASSERT_TRUE(parser_.ProcessInput(" bar"));
- ASSERT_TRUE(parser_.ProcessInput("\r\nContent-Type: text/plain"));
- ASSERT_TRUE(parser_.ProcessInput("\r\n\r\nE"));
- ASSERT_TRUE(parser_.ProcessInput("\r\n"));
- ASSERT_TRUE(parser_.ProcessInput("Hello,"));
- ASSERT_TRUE(parser_.ProcessInput(" world!\n"));
- ASSERT_TRUE(parser_.ProcessInput("\r\n"));
- ASSERT_TRUE(parser_.ProcessInput("21; some-random-"));
- ASSERT_TRUE(parser_.ProcessInput("chunk-extension\r\nIt sure"));
- ASSERT_TRUE(parser_.ProcessInput(" is good to see you today.\r\n0"));
- ASSERT_TRUE(parser_.ProcessInput("0\r\n\r\n"));
-}
-
-// Test that we gracefully handle bogus content-lengths. We should effectively
-// ignore the header, assume that the response has no content, and ignore what
-// follows the headers.
-TEST_F(HttpResponseParserTest, BogusContentLength) {
- EXPECT_CALL(visitor_, OnStatusLine(Eq("HTTP/1.1"), Eq("200"), Eq("OK")));
- EXPECT_CALL(visitor_, OnLeadingHeader(Eq("Content-Length"), Eq("bogus")));
- EXPECT_CALL(visitor_, OnLeadingHeadersComplete(Eq(true)));
-
- ASSERT_TRUE(parser_.ProcessInput(
- "HTTP/1.1 200 OK\r\n"
- "Content-Length: bogus\r\n"
- "\r\n"
- "bogus bogus bogus\r\n"));
-}
-
-// Test that we gracefully handle over-large content-lengths. As with
-// unparsable Content-Length values, an overflow of the Content-Length value
-// should result in us ignoring it.
-TEST_F(HttpResponseParserTest, ContentLengthOverflow) {
- EXPECT_CALL(visitor_, OnStatusLine(Eq("HTTP/1.1"), Eq("200"), Eq("OK")));
- EXPECT_CALL(visitor_, OnLeadingHeader(
- Eq("Content-Length"), Eq("9999999999999999999999999999999999999")));
- EXPECT_CALL(visitor_, OnLeadingHeadersComplete(Eq(true)));
-
- ASSERT_TRUE(parser_.ProcessInput(
- "HTTP/1.1 200 OK\r\n"
- "Content-Length: 9999999999999999999999999999999999999\r\n"
- "\r\n"
- "bogus bogus bogus\r\n"));
-}
-
-// We should be able to handle pretty big content lengths without overflowing,
-// however! Otherwise, downloads of extremely large files may fail. Here, we
-// test (the beginning of) a response that will contain a 5TB of data.
-TEST_F(HttpResponseParserTest, LargeContentLength) {
- EXPECT_CALL(visitor_, OnStatusLine(Eq("HTTP/1.1"), Eq("200"), Eq("OK")));
- EXPECT_CALL(visitor_, OnLeadingHeader(
- Eq("Content-Length"), Eq("5497558138880")));
- EXPECT_CALL(visitor_, OnLeadingHeadersComplete(Eq(false)));
- EXPECT_CALL(visitor_, OnData(Eq("This is the beginning of 5TB of data."),
- Eq(false)));
-
- ASSERT_TRUE(parser_.ProcessInput(
- "HTTP/1.1 200 OK\r\n"
- "Content-Length: 5497558138880\r\n"
- "\r\n"
- "This is the beginning of 5TB of data."));
- ASSERT_EQ(5497558138843uLL, parser_.GetRemainingBytesForTest());
-}
-
-} // namespace
+++ /dev/null
-// 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.
-
-#include "mod_spdy/common/http_response_visitor_interface.h"
-
-namespace mod_spdy {
-
-HttpResponseVisitorInterface::HttpResponseVisitorInterface() {}
-HttpResponseVisitorInterface::~HttpResponseVisitorInterface() {}
-
-} // namespace mod_spdy
+++ /dev/null
-// 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.
-
-#ifndef MOD_SPDY_COMMON_HTTP_RESPONSE_VISITOR_INTERFACE_H_
-#define MOD_SPDY_COMMON_HTTP_RESPONSE_VISITOR_INTERFACE_H_
-
-#include "base/basictypes.h"
-#include "base/strings/string_piece.h"
-
-namespace mod_spdy {
-
-// Interface that gets called back as an HTTP response is visited.
-class HttpResponseVisitorInterface {
- public:
- HttpResponseVisitorInterface();
- virtual ~HttpResponseVisitorInterface();
-
- // Called when an HTTP response status line is visited. Indicates that a new
- // HTTP response is being visited.
- virtual void OnStatusLine(const base::StringPiece& version,
- const base::StringPiece& status_code,
- const base::StringPiece& status_phrase) = 0;
-
- // Called zero or more times, once for each leading (i.e. normal, not
- // trailing) HTTP header. This is called after OnStatusLine but before
- // OnLeadingHeadersComplete.
- virtual void OnLeadingHeader(const base::StringPiece& key,
- const base::StringPiece& value) = 0;
-
- // Called after the leading HTTP headers have been visited. This will be
- // called exactly once when the leading headers are done (even if there were
- // no leading headers). If the `fin` argument is true, the response is now
- // complete (i.e. it has no body) and no more methods will be called.
- virtual void OnLeadingHeadersComplete(bool fin) = 0;
-
- // Called zero or more times, after OnLeadingHeadersComplete. If the `fin`
- // argument is true, the response is now complete and no more methods will be
- // called.
- virtual void OnData(const base::StringPiece& data, bool fin) = 0;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(HttpResponseVisitorInterface);
-};
-
-} // namespace mod_spdy
-
-#endif // MOD_SPDY_COMMON_HTTP_RESPONSE_VISITOR_INTERFACE_H_
+++ /dev/null
-// 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.
-
-#include "mod_spdy/common/http_string_builder.h"
-
-#include <string>
-
-#include "base/logging.h"
-#include "base/strings/string_piece.h"
-#include "base/strings/stringprintf.h"
-
-namespace {
-
-void OnHeader(const base::StringPiece& key,
- const base::StringPiece& value,
- std::string* output) {
- key.AppendToString(output);
- output->append(": ");
- value.AppendToString(output);
- output->append("\r\n");
-}
-
-} // namespace
-
-namespace mod_spdy {
-
-HttpStringBuilder::HttpStringBuilder(std::string* str)
- : string_(str), state_(REQUEST_LINE) {
- CHECK(string_);
-}
-
-HttpStringBuilder::~HttpStringBuilder() {}
-
-void HttpStringBuilder::OnRequestLine(const base::StringPiece& method,
- const base::StringPiece& path,
- const base::StringPiece& version) {
- DCHECK(state_ == REQUEST_LINE);
- state_ = LEADING_HEADERS;
- method.AppendToString(string_);
- string_->push_back(' ');
- path.AppendToString(string_);
- string_->push_back(' ');
- version.AppendToString(string_);
- string_->append("\r\n");
-}
-
-void HttpStringBuilder::OnLeadingHeader(const base::StringPiece& key,
- const base::StringPiece& value) {
- DCHECK(state_ == LEADING_HEADERS);
- OnHeader(key, value, string_);
-}
-
-void HttpStringBuilder::OnLeadingHeadersComplete() {
- DCHECK(state_ == LEADING_HEADERS);
- state_ = LEADING_HEADERS_COMPLETE;
- string_->append("\r\n");
-}
-
-void HttpStringBuilder::OnRawData(const base::StringPiece& data) {
- DCHECK(state_ == LEADING_HEADERS_COMPLETE || state_ == RAW_DATA);
- state_ = RAW_DATA;
- data.AppendToString(string_);
-}
-
-void HttpStringBuilder::OnDataChunk(const base::StringPiece& data) {
- DCHECK(state_ == LEADING_HEADERS_COMPLETE || state_ == DATA_CHUNKS);
- state_ = DATA_CHUNKS;
- // Encode the data as an HTTP data chunk. See RFC 2616 section 3.6.1 for
- // details.
- base::StringAppendF(string_, "%lX\r\n",
- static_cast<unsigned long>(data.size()));
- data.AppendToString(string_);
- string_->append("\r\n");
-}
-
-void HttpStringBuilder::OnDataChunksComplete() {
- DCHECK(state_ == DATA_CHUNKS);
- state_ = DATA_CHUNKS_COMPLETE;
- // Indicate that there are no more HTTP data chunks coming. See RFC 2616
- // section 3.6.1 for details.
- string_->append("0\r\n");
-}
-
-void HttpStringBuilder::OnTrailingHeader(const base::StringPiece& key,
- const base::StringPiece& value) {
- DCHECK(state_ == DATA_CHUNKS_COMPLETE || state_ == TRAILING_HEADERS);
- state_ = TRAILING_HEADERS;
- OnHeader(key, value, string_);
-}
-
-void HttpStringBuilder::OnTrailingHeadersComplete() {
- DCHECK(state_ == TRAILING_HEADERS);
- state_ = TRAILING_HEADERS_COMPLETE;
- string_->append("\r\n");
-}
-
-void HttpStringBuilder::OnComplete() {
- DCHECK(state_ == LEADING_HEADERS_COMPLETE ||
- state_ == RAW_DATA ||
- state_ == DATA_CHUNKS_COMPLETE ||
- state_ == TRAILING_HEADERS_COMPLETE);
- if (state_ == DATA_CHUNKS_COMPLETE) {
- // In this case, there have been data chunks, but we haven't called
- // OnTrailingHeadersComplete because there were no trailing headers. We
- // still need an empty line to indicate the end of the request.
- string_->append("\r\n");
- }
- state_ = COMPLETE;
-}
-
-} // namespace mod_spdy
+++ /dev/null
-// 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.
-
-#ifndef MOD_SPDY_COMMON_HTTP_STRING_BUILDER_H_
-#define MOD_SPDY_COMMON_HTTP_STRING_BUILDER_H_
-
-#include <string>
-
-#include "base/basictypes.h"
-#include "mod_spdy/common/http_request_visitor_interface.h"
-
-namespace mod_spdy {
-
-// An HttpRequestVisitorInterface class that appends to a std::string.
-class HttpStringBuilder : public HttpRequestVisitorInterface {
- public:
- explicit HttpStringBuilder(std::string* str);
- virtual ~HttpStringBuilder();
-
- bool is_complete() const { return state_ == COMPLETE; }
-
- // HttpRequestVisitorInterface methods:
- virtual void OnRequestLine(const base::StringPiece& method,
- const base::StringPiece& path,
- const base::StringPiece& version);
- virtual void OnLeadingHeader(const base::StringPiece& key,
- const base::StringPiece& value);
- virtual void OnLeadingHeadersComplete();
- virtual void OnRawData(const base::StringPiece& data);
- virtual void OnDataChunk(const base::StringPiece& data);
- virtual void OnDataChunksComplete();
- virtual void OnTrailingHeader(const base::StringPiece& key,
- const base::StringPiece& value);
- virtual void OnTrailingHeadersComplete();
- virtual void OnComplete();
-
- private:
- enum State {
- REQUEST_LINE,
- LEADING_HEADERS,
- LEADING_HEADERS_COMPLETE,
- RAW_DATA,
- DATA_CHUNKS,
- DATA_CHUNKS_COMPLETE,
- TRAILING_HEADERS,
- TRAILING_HEADERS_COMPLETE,
- COMPLETE
- };
-
- std::string* const string_;
- State state_;
-
- DISALLOW_COPY_AND_ASSIGN(HttpStringBuilder);
-};
-
-} // namespace mod_spdy
-
-#endif // MOD_SPDY_COMMON_HTTP_STRING_BUILDER_H_
+++ /dev/null
-// 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.
-
-#include "mod_spdy/common/http_to_spdy_converter.h"
-
-#include <string>
-
-#include "base/basictypes.h"
-#include "base/logging.h"
-#include "base/strings/string_piece.h"
-#include "mod_spdy/common/http_response_visitor_interface.h"
-#include "mod_spdy/common/protocol_util.h"
-#include "net/spdy/spdy_protocol.h"
-
-namespace {
-
-// This is the number of bytes we want to send per data frame. We never send
-// data frames larger than this, but we might send smaller ones if we have to
-// flush early.
-// TODO The SPDY folks say that smallish (~4kB) data frames are good; however,
-// we should experiment later on to see what value here performs the best.
-const size_t kTargetDataFrameBytes = 4096;
-
-} // namespace
-
-namespace mod_spdy {
-
-class HttpToSpdyConverter::ConverterImpl : public HttpResponseVisitorInterface{
- public:
- ConverterImpl(spdy::SpdyVersion spdy_version, SpdyReceiver* receiver);
- virtual ~ConverterImpl();
-
- void Flush();
-
- // HttpResponseVisitorInterface methods:
- virtual void OnStatusLine(const base::StringPiece& version,
- const base::StringPiece& status_code,
- const base::StringPiece& status_phrase);
- virtual void OnLeadingHeader(const base::StringPiece& key,
- const base::StringPiece& value);
- virtual void OnLeadingHeadersComplete(bool fin);
- virtual void OnData(const base::StringPiece& data, bool fin);
-
- private:
- void SendDataIfNecessary(bool flush, bool fin);
- void SendDataFrame(const char* data, size_t size, bool flag_fin);
-
- const spdy::SpdyVersion spdy_version_;
- SpdyReceiver* const receiver_;
- net::SpdyHeaderBlock headers_;
- std::string data_buffer_;
- bool sent_flag_fin_;
-
- DISALLOW_COPY_AND_ASSIGN(ConverterImpl);
-};
-
-HttpToSpdyConverter::SpdyReceiver::SpdyReceiver() {}
-
-HttpToSpdyConverter::SpdyReceiver::~SpdyReceiver() {}
-
-HttpToSpdyConverter::HttpToSpdyConverter(spdy::SpdyVersion spdy_version,
- SpdyReceiver* receiver)
- : impl_(new ConverterImpl(spdy_version, receiver)),
- parser_(impl_.get()) {}
-
-HttpToSpdyConverter::~HttpToSpdyConverter() {}
-
-bool HttpToSpdyConverter::ProcessInput(base::StringPiece input_data) {
- return parser_.ProcessInput(input_data);
-}
-
-void HttpToSpdyConverter::Flush() {
- impl_->Flush();
-}
-
-HttpToSpdyConverter::ConverterImpl::ConverterImpl(
- spdy::SpdyVersion spdy_version, SpdyReceiver* receiver)
- : spdy_version_(spdy_version),
- receiver_(receiver),
- sent_flag_fin_(false) {
- DCHECK_NE(spdy::SPDY_VERSION_NONE, spdy_version);
- CHECK(receiver_);
-}
-
-HttpToSpdyConverter::ConverterImpl::~ConverterImpl() {}
-
-void HttpToSpdyConverter::ConverterImpl::Flush() {
- SendDataIfNecessary(true, // true = do flush
- false); // false = not fin yet
-}
-
-void HttpToSpdyConverter::ConverterImpl::OnStatusLine(
- const base::StringPiece& version,
- const base::StringPiece& status_code,
- const base::StringPiece& status_phrase) {
- DCHECK(headers_.empty());
- const bool spdy2 = spdy_version_ < spdy::SPDY_VERSION_3;
- headers_[spdy2 ? spdy::kSpdy2Version : spdy::kSpdy3Version] =
- version.as_string();
- headers_[spdy2 ? spdy::kSpdy2Status : spdy::kSpdy3Status] =
- status_code.as_string();
-}
-
-void HttpToSpdyConverter::ConverterImpl::OnLeadingHeader(
- const base::StringPiece& key,
- const base::StringPiece& value) {
- // Filter out headers that are invalid in SPDY.
- if (IsInvalidSpdyResponseHeader(key)) {
- return;
- }
- MergeInHeader(key, value, &headers_);
-}
-
-void HttpToSpdyConverter::ConverterImpl::OnLeadingHeadersComplete(bool fin) {
- if (sent_flag_fin_) {
- LOG(DFATAL) << "Trying to send headers after sending FLAG_FIN";
- return;
- }
- if (fin) {
- sent_flag_fin_ = true;
- }
- receiver_->ReceiveSynReply(&headers_, fin);
- headers_.clear();
-}
-
-void HttpToSpdyConverter::ConverterImpl::OnData(const base::StringPiece& data,
- bool fin) {
- data.AppendToString(&data_buffer_);
- SendDataIfNecessary(false, fin); // false = don't flush
-}
-
-void HttpToSpdyConverter::ConverterImpl::SendDataIfNecessary(bool flush,
- bool fin) {
- // If we have (strictly) more than one frame's worth of data waiting, send it
- // down the filter chain, kTargetDataFrameBytes bytes at a time. If we are
- // left with _exactly_ kTargetDataFrameBytes bytes of data, we'll deal with
- // that in the next code block (see the comment there to explain why).
- if (data_buffer_.size() > kTargetDataFrameBytes) {
- const char* start = data_buffer_.data();
- size_t size = data_buffer_.size();
- while (size > kTargetDataFrameBytes) {
- SendDataFrame(start, kTargetDataFrameBytes, false);
- start += kTargetDataFrameBytes;
- size -= kTargetDataFrameBytes;
- }
- data_buffer_.erase(0, data_buffer_.size() - size);
- }
- DCHECK(data_buffer_.size() <= kTargetDataFrameBytes);
-
- // We may still have some leftover data. We need to send another data frame
- // now (rather than waiting for a full kTargetDataFrameBytes) if:
- // 1) This is the end of the response,
- // 2) we're supposed to flush and the buffer is nonempty, or
- // 3) we still have a full data frame's worth in the buffer.
- //
- // Note that because of the previous code block, condition (3) will only be
- // true if we have exactly kTargetDataFrameBytes of data. However, dealing
- // with that case here instead of in the above block makes it easier to make
- // sure we correctly set FLAG_FIN on the final data frame, which is why the
- // above block uses a strict, > comparison rather than a non-strict, >=
- // comparison.
- if (fin || (flush && !data_buffer_.empty()) ||
- data_buffer_.size() >= kTargetDataFrameBytes) {
- SendDataFrame(data_buffer_.data(), data_buffer_.size(), fin);
- data_buffer_.clear();
- }
-}
-
-void HttpToSpdyConverter::ConverterImpl::SendDataFrame(
- const char* data, size_t size, bool flag_fin) {
- if (sent_flag_fin_) {
- LOG(DFATAL) << "Trying to send data after sending FLAG_FIN";
- return;
- }
- if (flag_fin) {
- sent_flag_fin_ = true;
- }
- receiver_->ReceiveData(base::StringPiece(data, size), flag_fin);
-}
-
-} // namespace mod_spdy
+++ /dev/null
-// 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.
-
-#ifndef MOD_SPDY_COMMON_HTTP_TO_SPDY_CONVERTER_H_
-#define MOD_SPDY_COMMON_HTTP_TO_SPDY_CONVERTER_H_
-
-#include <string>
-
-#include "base/basictypes.h"
-#include "base/memory/scoped_ptr.h"
-#include "base/strings/string_piece.h"
-#include "mod_spdy/common/http_response_parser.h"
-#include "mod_spdy/common/protocol_util.h"
-#include "net/spdy/spdy_framer.h" // for SpdyHeaderBlock
-
-namespace mod_spdy {
-
-// Parses incoming HTTP response data and converts it into equivalent SPDY
-// frame data.
-class HttpToSpdyConverter {
- public:
- // Interface for the class that will receive frame data from the converter.
- class SpdyReceiver {
- public:
- SpdyReceiver();
- virtual ~SpdyReceiver();
-
- // Receive a SYN_REPLY frame with the given headers. The callee is free to
- // mutate the headers map (e.g. to add an extra header) before forwarding
- // it on, but the pointer will not remain valid after this method returns.
- virtual void ReceiveSynReply(net::SpdyHeaderBlock* headers,
- bool flag_fin) = 0;
-
- // Receive a DATA frame with the given payload. The data pointer will not
- // remain valid after this method returns.
- virtual void ReceiveData(base::StringPiece data, bool flag_fin) = 0;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(SpdyReceiver);
- };
-
- // Create a converter that will send frame data to the given receiver. The
- // converter does *not* gain ownership of the receiver.
- HttpToSpdyConverter(spdy::SpdyVersion spdy_version, SpdyReceiver* receiver);
- ~HttpToSpdyConverter();
-
- // Parse and process the next chunk of input; return true on success, false
- // on failure.
- bool ProcessInput(base::StringPiece input_data);
- bool ProcessInput(const char* data, size_t size) {
- return ProcessInput(base::StringPiece(data, size));
- }
-
- // Flush out any buffered data.
- void Flush();
-
- private:
- class ConverterImpl;
- scoped_ptr<ConverterImpl> impl_;
- HttpResponseParser parser_;
-
- DISALLOW_COPY_AND_ASSIGN(HttpToSpdyConverter);
-};
-
-} // namespace mod_spdy
-
-#endif // MOD_SPDY_COMMON_HTTP_TO_SPDY_CONVERTER_H_
+++ /dev/null
-// Copyright 2011 Google Inc. All Rights Reserved.
-//
-// 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.
-
-#include "mod_spdy/common/http_to_spdy_converter.h"
-
-#include "base/strings/string_piece.h"
-#include "mod_spdy/common/protocol_util.h"
-#include "net/spdy/spdy_protocol.h"
-#include "testing/gmock/include/gmock/gmock.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-using testing::_;
-using testing::DeleteArg;
-using testing::Eq;
-using testing::InSequence;
-using testing::Pointee;
-
-namespace {
-
-class MockSpdyReceiver : public mod_spdy::HttpToSpdyConverter::SpdyReceiver {
- public:
- MOCK_METHOD2(ReceiveSynReply, void(net::SpdyHeaderBlock* headers,
- bool flag_fin));
- MOCK_METHOD2(ReceiveData, void(base::StringPiece data, bool flag_fin));
-};
-
-class HttpToSpdyConverterTest :
- public testing::TestWithParam<mod_spdy::spdy::SpdyVersion> {
- public:
- HttpToSpdyConverterTest() : converter_(GetParam(), &receiver_) {}
-
- protected:
- const char* status_header_name() const {
- return (GetParam() < mod_spdy::spdy::SPDY_VERSION_3 ?
- mod_spdy::spdy::kSpdy2Status :
- mod_spdy::spdy::kSpdy3Status);
- }
- const char* version_header_name() const {
- return (GetParam() < mod_spdy::spdy::SPDY_VERSION_3 ?
- mod_spdy::spdy::kSpdy2Version :
- mod_spdy::spdy::kSpdy3Version);
- }
-
- MockSpdyReceiver receiver_;
- mod_spdy::HttpToSpdyConverter converter_;
- net::SpdyHeaderBlock expected_headers_;
-};
-
-// Simple response with a small payload. We should get a SYN_REPLY and a DATA
-// frame.
-TEST_P(HttpToSpdyConverterTest, SimpleWithContentLength) {
- expected_headers_[status_header_name()] = "200";
- expected_headers_[version_header_name()] = "HTTP/1.1";
- expected_headers_[mod_spdy::http::kContentLength] = "14";
- expected_headers_[mod_spdy::http::kContentType] = "text/plain";
- expected_headers_["x-whatever"] = "foobar";
-
- InSequence seq;
- EXPECT_CALL(receiver_, ReceiveSynReply(Pointee(Eq(expected_headers_)),
- Eq(false)));
- EXPECT_CALL(receiver_, ReceiveData(Eq("Hello, world!\n"), Eq(true)));
-
- ASSERT_TRUE(converter_.ProcessInput(
- "HTTP/1.1 200 OK\r\n"
- "Content-Length: 14\r\n"
- "Content-Type: text/plain\r\n"
- "X-Whatever:foobar\r\n"
- "\r\n"
- "Hello, world!\n"
- "\r\n"));
-}
-
-// The data arrives in two chunks, but they're small, so we should consolidate
-// them into a single DATA frame.
-TEST_P(HttpToSpdyConverterTest, SimpleWithChunking) {
- expected_headers_[status_header_name()] = "200";
- expected_headers_[version_header_name()] = "HTTP/1.1";
- expected_headers_[mod_spdy::http::kContentType] = "text/plain";
-
- InSequence seq;
- EXPECT_CALL(receiver_, ReceiveSynReply(Pointee(Eq(expected_headers_)),
- Eq(false)));
- EXPECT_CALL(receiver_, ReceiveData(Eq("Hello, world!\n"), Eq(true)));
-
- ASSERT_TRUE(converter_.ProcessInput(
- "HTTP/1.1 200 OK\r\n"
- "Connection: Keep-Alive\r\n"
- "Content-Type: text/plain\r\n"
- "Keep-Alive: timeout=10, max=5\r\n"
- "Transfer-Encoding: chunked\r\n"
- "\r\n"
- "6\r\n"
- "Hello,\r\n"
- "8\r\n"
- " world!\n\r\n"
- "0\r\n"
- "\r\n"));
-}
-
-// Test that we don't get tripped up if there is garbage after the end of
-// a chunked message.
-TEST_P(HttpToSpdyConverterTest, ChunkedEncodingWithTrailingGarbage) {
- expected_headers_[status_header_name()] = "200";
- expected_headers_[version_header_name()] = "HTTP/1.1";
- expected_headers_[mod_spdy::http::kContentType] = "text/plain";
-
- InSequence seq;
- EXPECT_CALL(receiver_, ReceiveSynReply(Pointee(Eq(expected_headers_)),
- Eq(false)));
- EXPECT_CALL(receiver_, ReceiveData(Eq("Hello, world!\n"), Eq(true)));
-
- ASSERT_TRUE(converter_.ProcessInput(
- "HTTP/1.1 200 OK\r\n"
- "Content-Type: text/plain\r\n"
- "Transfer-Encoding: chunked\r\n"
- "\r\n"
- "E\r\n"
- "Hello, world!\n\r\n"
- "0\r\n"
- "0\r\n" // multiple last-chunks
- "\r\n\x1bGaRbAgE")); // and also some garbage bytes
-}
-
-// No response body, so we should get the FLAG_FIN on the SYN_REPLY, and no
-// DATA frames.
-TEST_P(HttpToSpdyConverterTest, NoResponseBody) {
- expected_headers_[status_header_name()] = "301";
- expected_headers_[version_header_name()] = "HTTP/1.1";
- expected_headers_["location"] = "https://www.example.com/";
-
- InSequence seq;
- EXPECT_CALL(receiver_, ReceiveSynReply(Pointee(Eq(expected_headers_)),
- Eq(true)));
-
- ASSERT_TRUE(converter_.ProcessInput(
- "HTTP/1.1 301 Moved permenantly\r\n"
- "Location: https://www.example.com/\r\n"
- "\r\n"));
-}
-
-// Simple response with a large payload. We should get a SYN_REPLY and
-// multiple DATA frames.
-TEST_P(HttpToSpdyConverterTest, BreakUpLargeDataIntoMultipleFrames) {
- expected_headers_[status_header_name()] = "200";
- expected_headers_[version_header_name()] = "HTTP/1.1";
- expected_headers_[mod_spdy::http::kContentLength] = "10000";
- expected_headers_[mod_spdy::http::kContentType] = "text/plain";
-
- InSequence seq;
- EXPECT_CALL(receiver_, ReceiveSynReply(Pointee(Eq(expected_headers_)),
- Eq(false)));
- EXPECT_CALL(receiver_, ReceiveData(Eq(std::string(4096, 'x')), Eq(false)));
- EXPECT_CALL(receiver_, ReceiveData(Eq(std::string(4096, 'x')), Eq(false)));
- EXPECT_CALL(receiver_, ReceiveData(Eq(std::string(1808, 'x')), Eq(true)));
-
- ASSERT_TRUE(converter_.ProcessInput(
- "HTTP/1.1 200 OK\r\n"
- "Content-Length: 10000\r\n"
- "Content-Type: text/plain\r\n"
- "\r\n" +
- std::string(10000, 'x') +
- "\r\n"));
-}
-
-// Test that we buffer data until we get the full frame.
-TEST_P(HttpToSpdyConverterTest, BufferUntilWeHaveACompleteFrame) {
- expected_headers_[status_header_name()] = "200";
- expected_headers_[version_header_name()] = "HTTP/1.1";
- expected_headers_[mod_spdy::http::kContentLength] = "4096";
- expected_headers_[mod_spdy::http::kContentType] = "text/plain";
-
- InSequence seq;
- // Send some of the headers. We shouldn't get anything out yet.
- ASSERT_TRUE(converter_.ProcessInput(
- "HTTP/1.1 200 OK\r\n"
- "Content-Length: 4096\r\n"));
- // Send the rest of the headers, and some of the data. We should get the
- // SYN_REPLY now, but no data yet.
- EXPECT_CALL(receiver_, ReceiveSynReply(Pointee(Eq(expected_headers_)),
- Eq(false)));
- ASSERT_TRUE(converter_.ProcessInput(
- "Content-Type: text/plain\r\n"
- "\r\n" +
- std::string(2000, 'x')));
- // Send some more data, but still not enough for a full frame.
- ASSERT_TRUE(converter_.ProcessInput(std::string(2000, 'x')));
- // Send the last of the data. We should finally get the one DATA frame.
- EXPECT_CALL(receiver_, ReceiveData(Eq(std::string(4096, 'x')), Eq(true)));
- ASSERT_TRUE(converter_.ProcessInput(std::string(96, 'x')));
-}
-
-// Test that we flush the buffer when told.
-TEST_P(HttpToSpdyConverterTest, RespectFlushes) {
- expected_headers_[status_header_name()] = "200";
- expected_headers_[version_header_name()] = "HTTP/1.1";
- expected_headers_[mod_spdy::http::kContentLength] = "4096";
- expected_headers_[mod_spdy::http::kContentType] = "text/plain";
-
- InSequence seq;
- // Send the headers and some of the data (not enough for a full frame). We
- // should get the headers out, but no data yet.
- EXPECT_CALL(receiver_, ReceiveSynReply(Pointee(Eq(expected_headers_)),
- Eq(false)));
- ASSERT_TRUE(converter_.ProcessInput(
- "HTTP/1.1 200 OK\r\n"
- "Content-Length: 4096\r\n"
- "Content-Type: text/plain\r\n"
- "\r\n" +
- std::string(2000, 'x')));
- // Perform a flush. We should get the data sent so far.
- EXPECT_CALL(receiver_, ReceiveData(Eq(std::string(2000, 'x')), Eq(false)));
- converter_.Flush();
- // Send the rest of the data. We should get out a second DATA frame, with
- // FLAG_FIN set.
- EXPECT_CALL(receiver_, ReceiveData(Eq(std::string(2096, 'y')), Eq(true)));
- ASSERT_TRUE(converter_.ProcessInput(std::string(2096, 'y')));
-}
-
-// Test that we flush the buffer when told.
-TEST_P(HttpToSpdyConverterTest, FlushAfterEndDoesNothing) {
- expected_headers_[status_header_name()] = "200";
- expected_headers_[version_header_name()] = "HTTP/1.1";
- expected_headers_[mod_spdy::http::kContentLength] = "6";
- expected_headers_[mod_spdy::http::kContentType] = "text/plain";
-
- InSequence seq;
- EXPECT_CALL(receiver_, ReceiveSynReply(Pointee(Eq(expected_headers_)),
- Eq(false)));
- EXPECT_CALL(receiver_, ReceiveData(Eq("foobar"), Eq(true)));
- ASSERT_TRUE(converter_.ProcessInput(
- "HTTP/1.1 200 OK\r\n"
- "Content-Length: 6\r\n"
- "Content-Type: text/plain\r\n"
- "\r\n"
- "foobar"));
- // Flushing after we're done (even multiple times) should be permitted, but
- // should do nothing.
- converter_.Flush();
- converter_.Flush();
- converter_.Flush();
-}
-
-// Run each test over both SPDY v2 and SPDY v3.
-INSTANTIATE_TEST_CASE_P(Spdy2And3, HttpToSpdyConverterTest, testing::Values(
- mod_spdy::spdy::SPDY_VERSION_2, mod_spdy::spdy::SPDY_VERSION_3,
- mod_spdy::spdy::SPDY_VERSION_3_1));
-
-} // namespace
+++ /dev/null
-// 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.
-
-#include "mod_spdy/common/protocol_util.h"
-
-#include "base/strings/string_piece.h"
-#include "base/strings/string_util.h"
-#include "net/spdy/spdy_frame_builder.h"
-#include "net/spdy/spdy_framer.h"
-#include "net/spdy/spdy_protocol.h"
-
-namespace mod_spdy {
-
-namespace http {
-
-extern const char* const kAcceptEncoding = "accept-encoding";
-extern const char* const kConnection = "connection";
-extern const char* const kContentLength = "content-length";
-extern const char* const kContentType = "content-type";
-extern const char* const kHost = "host";
-extern const char* const kKeepAlive = "keep-alive";
-extern const char* const kProxyConnection = "proxy-connection";
-extern const char* const kReferer = "referer";
-extern const char* const kTransferEncoding = "transfer-encoding";
-extern const char* const kXAssociatedContent = "x-associated-content";
-extern const char* const kXModSpdy = "x-mod-spdy";
-
-extern const char* const kChunked = "chunked";
-extern const char* const kGzipDeflate = "gzip,deflate";
-
-} // namespace http
-
-namespace spdy {
-
-extern const char* const kSpdy2Method = "method";
-extern const char* const kSpdy2Scheme = "scheme";
-extern const char* const kSpdy2Status = "status";
-extern const char* const kSpdy2Url = "url";
-extern const char* const kSpdy2Version = "version";
-
-extern const char* const kSpdy3Host = ":host";
-extern const char* const kSpdy3Method = ":method";
-extern const char* const kSpdy3Path = ":path";
-extern const char* const kSpdy3Scheme = ":scheme";
-extern const char* const kSpdy3Status = ":status";
-extern const char* const kSpdy3Version = ":version";
-
-} // namespace spdy
-
-net::SpdyMajorVersion SpdyVersionToFramerVersion(spdy::SpdyVersion version) {
- switch (version) {
- case spdy::SPDY_VERSION_2:
- return net::SPDY2;
- case spdy::SPDY_VERSION_3:
- case spdy::SPDY_VERSION_3_1:
- return net::SPDY3;
- default:
- LOG(DFATAL) << "Invalid SpdyVersion value: " << version;
- return static_cast<net::SpdyMajorVersion>(0);
- }
-}
-
-const char* SpdyVersionNumberString(spdy::SpdyVersion version) {
- switch (version) {
- case spdy::SPDY_VERSION_2: return "2";
- case spdy::SPDY_VERSION_3: return "3";
- case spdy::SPDY_VERSION_3_1: return "3.1";
- default:
- LOG(DFATAL) << "Invalid SpdyVersion value: " << version;
- return "?";
- }
-}
-
-const char* GoAwayStatusCodeToString(net::SpdyGoAwayStatus status) {
- switch (status) {
- case net::GOAWAY_OK: return "OK";
- case net::GOAWAY_PROTOCOL_ERROR: return "PROTOCOL_ERROR";
- case net::GOAWAY_INTERNAL_ERROR: return "INTERNAL_ERROR";
- default: return "<unknown>";
- }
-}
-
-const char* SettingsIdToString(net::SpdySettingsIds id) {
- switch (id) {
- case net::SETTINGS_UPLOAD_BANDWIDTH: return "UPLOAD_BANDWIDTH";
- case net::SETTINGS_DOWNLOAD_BANDWIDTH: return "DOWNLOAD_BANDWIDTH";
- case net::SETTINGS_ROUND_TRIP_TIME: return "ROUND_TRIP_TIME";
- case net::SETTINGS_MAX_CONCURRENT_STREAMS: return "MAX_CONCURRENT_STREAMS";
- case net::SETTINGS_CURRENT_CWND: return "CURRENT_CWND";
- case net::SETTINGS_DOWNLOAD_RETRANS_RATE: return "DOWNLOAD_RETRANS_RATE";
- case net::SETTINGS_INITIAL_WINDOW_SIZE: return "INITIAL_WINDOW_SIZE";
- default: return "<unknown>";
- }
-}
-
-bool IsInvalidSpdyResponseHeader(base::StringPiece key) {
- // The following headers are forbidden in SPDY responses (SPDY draft 3
- // section 3.2.2).
- return (LowerCaseEqualsASCII(key.begin(), key.end(), http::kConnection) ||
- LowerCaseEqualsASCII(key.begin(), key.end(), http::kKeepAlive) ||
- LowerCaseEqualsASCII(key.begin(), key.end(),
- http::kProxyConnection) ||
- LowerCaseEqualsASCII(key.begin(), key.end(),
- http::kTransferEncoding));
-}
-
-net::SpdyPriority LowestSpdyPriorityForVersion(
- spdy::SpdyVersion spdy_version) {
- return (spdy_version < spdy::SPDY_VERSION_3 ? 3u : 7u);
-}
-
-void MergeInHeader(base::StringPiece key, base::StringPiece value,
- net::SpdyHeaderBlock* headers) {
- // The SPDY spec requires that header names be lowercase, so forcibly
- // lowercase the key here.
- std::string lower_key(key.as_string());
- StringToLowerASCII(&lower_key);
-
- net::SpdyHeaderBlock::iterator iter = headers->find(lower_key);
- if (iter == headers->end()) {
- (*headers)[lower_key] = value.as_string();
- } else {
- iter->second.push_back('\0');
- value.AppendToString(&iter->second);
- }
-}
-
-} // namespace mod_spdy
+++ /dev/null
-// 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.
-
-#ifndef MOD_SPDY_COMMON_PROTOCOL_UTIL_H_
-#define MOD_SPDY_COMMON_PROTOCOL_UTIL_H_
-
-#include "base/strings/string_piece.h"
-#include "net/spdy/spdy_framer.h"
-#include "net/spdy/spdy_protocol.h"
-
-namespace mod_spdy {
-
-namespace http {
-
-// HTTP header names. These values are all lower-case, so they can be used
-// directly in SPDY header blocks.
-extern const char* const kAcceptEncoding;
-extern const char* const kConnection;
-extern const char* const kContentLength;
-extern const char* const kContentType;
-extern const char* const kHost;
-extern const char* const kKeepAlive;
-extern const char* const kProxyConnection;
-extern const char* const kReferer;
-extern const char* const kTransferEncoding;
-extern const char* const kXAssociatedContent;
-extern const char* const kXModSpdy;
-
-// HTTP header values.
-extern const char* const kChunked;
-extern const char* const kGzipDeflate;
-
-} // namespace http
-
-namespace spdy {
-
-// Represents a specific SPDY version, including experimental versions such as
-// SPDY/3.1 (which uses version 3 frames, but has extra semantics borrowed from
-// SPDY/4).
-enum SpdyVersion {
- SPDY_VERSION_NONE, // not using SPDY
- SPDY_VERSION_2, // SPDY/2
- SPDY_VERSION_3, // SPDY/3
- SPDY_VERSION_3_1 // SPDY/3.1 (SPDY/3 framing, but with new flow control)
-};
-
-// Magic header names for SPDY v2.
-extern const char* const kSpdy2Method;
-extern const char* const kSpdy2Scheme;
-extern const char* const kSpdy2Status;
-extern const char* const kSpdy2Url;
-extern const char* const kSpdy2Version;
-
-// Magic header names for SPDY v3.
-extern const char* const kSpdy3Host;
-extern const char* const kSpdy3Method;
-extern const char* const kSpdy3Path;
-extern const char* const kSpdy3Scheme;
-extern const char* const kSpdy3Status;
-extern const char* const kSpdy3Version;
-
-} // namespace spdy
-
-// Given a SpdyVersion enum value, return the framer version number to use.
-// The argument must not be SPDY_VERSION_NONE.
-net::SpdyMajorVersion SpdyVersionToFramerVersion(spdy::SpdyVersion version);
-
-// Given a SpdyVersion enum value (other than SPDY_VERSION_NONE), return a
-// string for the version number (e.g. "3" or "3.1").
-const char* SpdyVersionNumberString(spdy::SpdyVersion version);
-
-// Convert various SPDY enum types to strings.
-const char* GoAwayStatusCodeToString(net::SpdyGoAwayStatus status);
-inline const char* RstStreamStatusCodeToString(
- net::SpdyRstStreamStatus status) {
- return net::SpdyFramer::StatusCodeToString(status);
-}
-const char* SettingsIdToString(net::SpdySettingsIds id);
-
-// Return true if this header is forbidden in SPDY responses (ignoring case).
-bool IsInvalidSpdyResponseHeader(base::StringPiece key);
-
-// Return the SpdyPriority representing the least important priority for the
-// given SPDY version. For SPDY v2 and below, it's 3; for SPDY v3 and above,
-// it's 7. (The most important SpdyPriority is always 0.)
-net::SpdyPriority LowestSpdyPriorityForVersion(spdy::SpdyVersion spdy_version);
-
-// Add a header to a header table, lower-casing and merging if necessary.
-void MergeInHeader(base::StringPiece key, base::StringPiece value,
- net::SpdyHeaderBlock* headers);
-
-} // namespace mod_spdy
-
-#endif // MOD_SPDY_COMMON_PROTOCOL_UTIL_H_
+++ /dev/null
-// Copyright 2010 Google Inc. All Rights Reserved.
-//
-// 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.
-
-#include "mod_spdy/common/protocol_util.h"
-
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace {
-
-TEST(ProtocolUtilTest, InvalidSpdyResponseHeaders) {
- // Forbidden headers should be rejected regardless of capitalization.
- EXPECT_TRUE(mod_spdy::IsInvalidSpdyResponseHeader("connection"));
- EXPECT_TRUE(mod_spdy::IsInvalidSpdyResponseHeader("Connection"));
- EXPECT_TRUE(mod_spdy::IsInvalidSpdyResponseHeader("cOnNeCtIoN"));
- EXPECT_TRUE(mod_spdy::IsInvalidSpdyResponseHeader("transfer-encoding"));
- EXPECT_TRUE(mod_spdy::IsInvalidSpdyResponseHeader("Transfer-Encoding"));
-}
-
-TEST(ProtocolUtilTest, ValidSpdyResponseHeaders) {
- // Permitted headers should be accepted regardless of capitalization (SPDY
- // requires header names to be lowercase, but this function shouldn't be
- // checking that).
- EXPECT_FALSE(mod_spdy::IsInvalidSpdyResponseHeader("content-length"));
- EXPECT_FALSE(mod_spdy::IsInvalidSpdyResponseHeader("Content-Length"));
- EXPECT_FALSE(mod_spdy::IsInvalidSpdyResponseHeader(
- "x-header-we-have-never-heard-of"));
- EXPECT_FALSE(mod_spdy::IsInvalidSpdyResponseHeader(
- "X-HEADER-WE-HAVE-NEVER-HEARD-OF"));
-}
-
-TEST(ProtocolUtilTest, MergeIntoEmpty) {
- net::SpdyHeaderBlock headers;
- ASSERT_EQ(0u, headers.size());
-
- mod_spdy::MergeInHeader("content-length", "256", &headers);
- ASSERT_EQ(1u, headers.size());
- ASSERT_EQ("256", headers["content-length"]);
-}
-
-TEST(ProtocolUtilTest, MakeLowerCase) {
- net::SpdyHeaderBlock headers;
- ASSERT_EQ(0u, headers.size());
-
- mod_spdy::MergeInHeader("Content-Length", "256", &headers);
- ASSERT_EQ(1u, headers.size());
- ASSERT_EQ(0u, headers.count("Content-Length"));
- ASSERT_EQ("256", headers["content-length"]);
-}
-
-TEST(ProtocolUtilTest, MergeDifferentHeaders) {
- net::SpdyHeaderBlock headers;
- ASSERT_EQ(0u, headers.size());
-
- mod_spdy::MergeInHeader("x-foo", "bar", &headers);
- ASSERT_EQ(1u, headers.size());
- ASSERT_EQ("bar", headers["x-foo"]);
-
- mod_spdy::MergeInHeader("x-baz", "quux", &headers);
- ASSERT_EQ(2u, headers.size());
- ASSERT_EQ("bar", headers["x-foo"]);
- ASSERT_EQ("quux", headers["x-baz"]);
-}
-
-TEST(ProtocolUtilTest, MergeRepeatedHeader) {
- net::SpdyHeaderBlock headers;
- ASSERT_EQ(0u, headers.size());
-
- mod_spdy::MergeInHeader("x-foo", "bar", &headers);
- ASSERT_EQ(1u, headers.size());
- const std::string expected1("bar");
- ASSERT_EQ(expected1, headers["x-foo"]);
-
- mod_spdy::MergeInHeader("x-foo", "baz", &headers);
- ASSERT_EQ(1u, headers.size());
- const std::string expected2("bar\0baz", 7);
- ASSERT_EQ(expected2, headers["x-foo"]);
-
- mod_spdy::MergeInHeader("x-foo", "quux", &headers);
- ASSERT_EQ(1u, headers.size());
- const std::string expected3("bar\0baz\0quux", 12);
- ASSERT_EQ(expected3, headers["x-foo"]);
-}
-
-} // namespace
+++ /dev/null
-// Copyright 2013 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.
-
-#include "mod_spdy/common/server_push_discovery_learner.h"
-
-#include <algorithm>
-#include <utility>
-
-#include "base/strings/string_util.h"
-
-namespace mod_spdy {
-
-namespace {
-
-int32_t GetPriorityFromExtension(const std::string& url) {
- if (EndsWith(url, ".js", false)) {
- return 1;
- } else if (EndsWith(url, ".css", false)) {
- return 1;
- } else {
- return -1;
- }
-}
-
-} // namespace
-
-ServerPushDiscoveryLearner::ServerPushDiscoveryLearner() {}
-
-std::vector<ServerPushDiscoveryLearner::Push>
-ServerPushDiscoveryLearner::GetPushes(const std::string& master_url) {
- base::AutoLock lock(lock_);
- UrlData& url_data = url_data_[master_url];
- std::vector<Push> pushes;
-
- uint64_t threshold = url_data.first_hit_count / 2;
-
- std::vector<AdjacentData> significant_adjacents;
-
- for (std::map<std::string, AdjacentData>::const_iterator it =
- url_data.adjacents.begin(); it != url_data.adjacents.end(); ++it) {
- if (it->second.hit_count >= threshold)
- significant_adjacents.push_back(it->second);
- }
-
- // Sort by average time from initial request. We want to provide the child
- // resources that the client needs immediately with a higher priority.
- std::sort(significant_adjacents.begin(), significant_adjacents.end(),
- &CompareAdjacentDataByAverageTimeFromInit);
-
- for (size_t i = 0; i < significant_adjacents.size(); ++i) {
- const AdjacentData& adjacent = significant_adjacents[i];
-
- // Give certain URLs fixed high priorities based on their extension.
- int32_t priority = GetPriorityFromExtension(adjacent.adjacent_url);
-
- // Otherwise, assign a higher priority based on its average request order.
- if (priority < 0) {
- priority = 2 + (i * 6 / significant_adjacents.size());
- }
-
- pushes.push_back(Push(adjacent.adjacent_url, priority));
- }
-
- return pushes;
-}
-
-void ServerPushDiscoveryLearner::AddFirstHit(const std::string& master_url) {
- base::AutoLock lock(lock_);
- UrlData& url_data = url_data_[master_url];
- ++url_data.first_hit_count;
-}
-
-void ServerPushDiscoveryLearner::AddAdjacentHit(const std::string& master_url,
- const std::string& adjacent_url,
- int64_t time_from_init) {
- base::AutoLock lock(lock_);
- std::map<std::string, AdjacentData>& master_url_adjacents =
- url_data_[master_url].adjacents;
-
- if (master_url_adjacents.find(adjacent_url) == master_url_adjacents.end()) {
- master_url_adjacents.insert(
- make_pair(adjacent_url, AdjacentData(adjacent_url)));
- }
-
- AdjacentData& adjacent_data = master_url_adjacents.find(adjacent_url)->second;
-
- ++adjacent_data.hit_count;
- double inverse_hit_count = 1.0 / adjacent_data.hit_count;
-
- adjacent_data.average_time_from_init =
- inverse_hit_count * time_from_init +
- (1 - inverse_hit_count) * adjacent_data.average_time_from_init;
-}
-
-// static
-bool ServerPushDiscoveryLearner::CompareAdjacentDataByAverageTimeFromInit(
- const AdjacentData& a, const AdjacentData& b) {
- return a.average_time_from_init < b.average_time_from_init;
-}
-
-} // namespace mod_spdy
+++ /dev/null
-// Copyright 2013 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.
-
-#ifndef MOD_SPDY_COMMON_SERVER_PUSH_DISCOVERY_LEARNER_H_
-#define MOD_SPDY_COMMON_SERVER_PUSH_DISCOVERY_LEARNER_H_
-
-#include <map>
-#include <string>
-#include <vector>
-
-#include "base/basictypes.h"
-#include "base/synchronization/lock.h"
-#include "net/spdy/spdy_protocol.h"
-
-namespace mod_spdy {
-
-// Used to keep track of request patterns and generate X-Associated-Content.
-// Stores the initial |master_url| request and the subsequent |adjacent_url|s.
-// Generates reasonable pushes based on a simple heuristic.
-class ServerPushDiscoveryLearner {
- public:
- struct Push {
- Push(const std::string& adjacent_url, net::SpdyPriority priority)
- : adjacent_url(adjacent_url),
- priority(priority) {
- }
-
- std::string adjacent_url;
- net::SpdyPriority priority;
- };
-
- ServerPushDiscoveryLearner();
-
- // Gets a list of child resource pushes for a given |master_url|.
- std::vector<Push> GetPushes(const std::string& master_url);
-
- // Called when module receives an initial master request for a page, and
- // module intends to log future child resource requests for learning.
- void AddFirstHit(const std::string& master_url);
-
- // Called when module receives child resource requests associated with
- // a master request received earlier. |time_from_init| is the time in
- // microseconds between this adjacent hit on |adjacent_url| and the initial
- // hit on the |master_url|.
- void AddAdjacentHit(const std::string& master_url,
- const std::string& adjacent_url, int64_t time_from_init);
-
- private:
- struct AdjacentData {
- AdjacentData(const std::string& adjacent_url)
- : adjacent_url(adjacent_url),
- hit_count(0),
- average_time_from_init(0) {
- }
-
- std::string adjacent_url;
- uint64_t hit_count;
- int64_t average_time_from_init;
- };
-
- struct UrlData {
- UrlData() : first_hit_count(0) {}
-
- uint64_t first_hit_count;
- std::map<std::string, AdjacentData> adjacents;
- };
-
- static bool CompareAdjacentDataByAverageTimeFromInit(const AdjacentData& a,
- const AdjacentData& b);
-
- std::map<std::string, UrlData> url_data_;
- base::Lock lock_;
-};
-
-} // namespace mod_spdy
-
-#endif // MOD_SPDY_COMMON_SERVER_PUSH_DISCOVERY_LEARNER_H_
+++ /dev/null
-// Copyright 2013 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.
-
-#include "mod_spdy/common/server_push_discovery_learner.h"
-
-#include "gtest/gtest.h"
-
-namespace mod_spdy {
-
-TEST(ServerPushDiscoveryLearnerTest, TrivialNoPush) {
- ServerPushDiscoveryLearner learner;
-
- EXPECT_TRUE(learner.GetPushes("a").empty());
-
- learner.AddFirstHit("a");
- learner.AddFirstHit("a");
- learner.AddFirstHit("a");
- learner.AddFirstHit("a");
-
- EXPECT_TRUE(learner.GetPushes("a").empty());
-
- // Add an adjacent hit, but it should not be enough to generate a push.
- learner.AddAdjacentHit("a", "b", 0);
-
- EXPECT_TRUE(learner.GetPushes("a").empty());
-}
-
-TEST(ServerPushDiscoveryLearnerTest, TrivialYesPush) {
- ServerPushDiscoveryLearner learner;
-
- learner.AddFirstHit("a");
- learner.AddAdjacentHit("a", "b", 0);
-
- std::vector<ServerPushDiscoveryLearner::Push> pushes = learner.GetPushes("a");
- EXPECT_FALSE(pushes.empty());
- EXPECT_EQ("b", pushes.front().adjacent_url);
-}
-
-TEST(ServerPushDiscoveryLearnerTest, PushOrder) {
- ServerPushDiscoveryLearner learner;
-
- learner.AddFirstHit("a");
- learner.AddAdjacentHit("a", "b", 1);
- learner.AddAdjacentHit("a", "c", 2);
-
- learner.AddFirstHit("a");
- learner.AddAdjacentHit("a", "b", 2);
- learner.AddAdjacentHit("a", "c", 3);
-
- learner.AddFirstHit("a");
- learner.AddAdjacentHit("a", "b", 3);
- learner.AddAdjacentHit("a", "c", 4);
-
- std::vector<ServerPushDiscoveryLearner::Push> pushes = learner.GetPushes("a");
- EXPECT_EQ(2u, pushes.size());
- EXPECT_EQ("b", pushes.front().adjacent_url);
- EXPECT_EQ("c", pushes.back().adjacent_url);
-}
-
-TEST(ServerPushDiscoveryLearnerTest, TurnoverPoint) {
- ServerPushDiscoveryLearner learner;
-
- uint64_t a_requests = 0;
- uint64_t b_requests = 0;
-
- // Put in 20 initial requests with no child requests.
- for (int i = 0; i < 20; ++i) {
- learner.AddFirstHit("a");
- ++a_requests;
- }
-
- // Put in more b requests until it tips over
- for (int i = 0; i < 50; ++i) {
- learner.AddAdjacentHit("a", "b", 0);
- ++b_requests;
- std::vector<ServerPushDiscoveryLearner::Push> pushes =
- learner.GetPushes("a");
-
- if (b_requests >= (a_requests / 2)) {
- ASSERT_TRUE(pushes.size() == 1) << "(a, b) = " << a_requests << ","
- << b_requests;
- EXPECT_EQ("b", pushes.front().adjacent_url);
- } else {
- EXPECT_TRUE(pushes.empty()) << "(a, b) = " << a_requests << ","
- << b_requests;
- }
- }
-}
-
-} // namespace mod_spdy
+++ /dev/null
-// Copyright 2013 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.
-
-#include "mod_spdy/common/server_push_discovery_session.h"
-
-namespace mod_spdy {
-
-const int64_t kServerPushSessionTimeout = 1000000; // 1 second in microseconds.
-
-ServerPushDiscoverySessionPool::ServerPushDiscoverySessionPool()
- : next_session_id_(0) {
-}
-
-ServerPushDiscoverySession* ServerPushDiscoverySessionPool::GetExistingSession(
- SessionId session_id,
- int64_t request_time) {
- base::AutoLock lock(lock_);
- std::map<SessionId, ServerPushDiscoverySession>::iterator it =
- session_cache_.find(session_id);
- if (it == session_cache_.end() ||
- it->second.TimeFromInit(request_time) > kServerPushSessionTimeout) {
- return NULL;
- }
-
- return &(it->second);
-}
-
-ServerPushDiscoverySessionPool::SessionId
-ServerPushDiscoverySessionPool::CreateSession(
- int64_t request_time,
- const std::string& request_url,
- bool took_push) {
- base::AutoLock lock(lock_);
- CleanExpired(request_time);
- // Create a session to track this request chain
- SessionId session_id = ++next_session_id_;
- session_cache_.insert(
- std::make_pair(session_id,
- ServerPushDiscoverySession(
- session_id, request_time, request_url, took_push)));
- return session_id;
-}
-
-void ServerPushDiscoverySessionPool::CleanExpired(int64_t request_time) {
- lock_.AssertAcquired();
-
- std::map<int64_t, ServerPushDiscoverySession>::iterator it =
- session_cache_.begin();
- while (it != session_cache_.end()) {
- if (it->second.TimeFromInit(request_time) > kServerPushSessionTimeout) {
- session_cache_.erase(it++);
- } else {
- ++it;
- }
- }
-}
-
-ServerPushDiscoverySession::ServerPushDiscoverySession(
- ServerPushDiscoverySessionPool::SessionId session_id,
- int64_t initial_request_time,
- const std::string& master_url,
- bool took_push)
- : session_id_(session_id),
- initial_request_time_(initial_request_time),
- master_url_(master_url),
- took_push_(took_push),
- last_access_(initial_request_time) {}
-
-} // namespace mod_spdy
+++ /dev/null
-// Copyright 2013 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.
-
-#ifndef MOD_SPDY_COMMON_SERVER_PUSH_DISCOVERY_SESSION_H_
-#define MOD_SPDY_COMMON_SERVER_PUSH_DISCOVERY_SESSION_H_
-
-#include <map>
-#include <string>
-
-#include "base/basictypes.h"
-#include "base/synchronization/lock.h"
-
-namespace mod_spdy {
-
-class ServerPushDiscoverySession;
-
-extern const int64_t kServerPushSessionTimeout;
-
-// This class manages a pool of sessions used to discover X-Associated-Content.
-// It tracks an initial request, i.e., for 'index.html', and all its child
-// requests, i.e., 'logo.gif', 'style.css'. This should be created during
-// per-process initialization. Class may be called from multiple threads.
-class ServerPushDiscoverySessionPool {
- public:
- typedef int64_t SessionId;
-
- ServerPushDiscoverySessionPool();
-
- // Retrieves an existing session. Returns NULL if it's been timed out already.
- // In which case the module should create a new session. The returned pointer
- // is an object owned by the pool and must not be deleted by the caller.
- ServerPushDiscoverySession* GetExistingSession(SessionId session_id,
- int64_t request_time);
-
- // Creates a new session. |took_push| denotes if the the initial request
- // response included an auto-learned X-Associated-Content header, since we
- // don't want to self-reinforce our URL statistics. Returns the session_id
- // for user agent storage.
- int64_t CreateSession(int64_t request_time,
- const std::string& request_url,
- bool took_push);
-
- private:
- // Caller should be holding |lock_|.
- void CleanExpired(int64_t request_time);
-
- SessionId next_session_id_;
- std::map<SessionId, ServerPushDiscoverySession> session_cache_;
-
- base::Lock lock_;
-};
-
-// Represents an initial page request and all its child resource requests.
-class ServerPushDiscoverySession {
- public:
- // Update the last access time on this session, extending its lifetime.
- void UpdateLastAccessTime(int64_t now) { last_access_ = now; }
-
- // Returns the elapsed microseconds between the initial request and this one.
- int64_t TimeFromInit(int64_t request_time) const {
- return request_time - initial_request_time_;
- }
-
- const std::string& master_url() const { return master_url_; }
- bool took_push() const { return took_push_; }
-
- private:
- friend class ServerPushDiscoverySessionPool;
-
- ServerPushDiscoverySession(
- ServerPushDiscoverySessionPool::SessionId session_id,
- int64_t initial_request_time,
- const std::string& master_url,
- bool took_push);
-
- ServerPushDiscoverySessionPool::SessionId session_id_;
- int64_t initial_request_time_;
- std::string master_url_;
- int64_t took_push_;
-
- int64_t last_access_;
-};
-
-} // namespace mod_spdy
-
-#endif // MOD_SPDY_COMMON_SERVER_PUSH_DISCOVERY_SESSION_H_
+++ /dev/null
-// Copyright 2013 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.
-
-#include "mod_spdy/common/server_push_discovery_session.h"
-
-#include "gtest/gtest.h"
-
-namespace mod_spdy {
-
-TEST(ServerPushDiscoverySessionTest, NoSession) {
- ServerPushDiscoverySessionPool pool;
- EXPECT_EQ(NULL, pool.GetExistingSession(0, 0));
-}
-
-TEST(ServerPushDiscoverySessionTest, GetSession) {
- ServerPushDiscoverySessionPool pool;
- std::vector<int64_t> session_ids;
- for (int i = 0; i < 40; i++)
- session_ids.push_back(pool.CreateSession(0, "", false));
-
- for (int i = 0; i < 40; i++)
- EXPECT_TRUE(pool.GetExistingSession(session_ids[i], 0));
-}
-
-TEST(ServerPushDiscoverySessionTest, ExpiryTest) {
- ServerPushDiscoverySessionPool pool;
- std::vector<int64_t> session_ids;
- for (int i = 0; i < 20; i++) {
- session_ids.push_back(pool.CreateSession(0, "", false));
- }
-
- for (int i = 0; i < 20; i++) {
- int64_t time = i * kServerPushSessionTimeout / 10;
- bool expired = time > kServerPushSessionTimeout;
- session_ids.push_back(pool.CreateSession(0, "", false));
-
- if (expired) {
- EXPECT_FALSE(pool.GetExistingSession(session_ids[i], time));
- } else {
- EXPECT_TRUE(pool.GetExistingSession(session_ids[i], time));
- }
- }
-}
-
-} // namespace mod_spdy
+++ /dev/null
-// Copyright 2013 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.
-
-#include "mod_spdy/common/shared_flow_control_window.h"
-
-#include "base/logging.h"
-#include "base/synchronization/condition_variable.h"
-#include "base/synchronization/lock.h"
-#include "mod_spdy/common/spdy_frame_priority_queue.h"
-#include "net/spdy/spdy_protocol.h"
-
-namespace mod_spdy {
-
-SharedFlowControlWindow::SharedFlowControlWindow(
- int32 initial_input_window_size, int32 initial_output_window_size)
- : condvar_(&lock_),
- aborted_(false),
- init_input_window_size_(initial_input_window_size),
- input_window_size_(initial_input_window_size),
- input_bytes_consumed_(0),
- output_window_size_(initial_output_window_size) {}
-
-SharedFlowControlWindow::~SharedFlowControlWindow() {}
-
-void SharedFlowControlWindow::Abort() {
- base::AutoLock autolock(lock_);
- aborted_ = true;
- condvar_.Broadcast();
-}
-
-bool SharedFlowControlWindow::is_aborted() const {
- base::AutoLock autolock(lock_);
- return aborted_;
-}
-
-int32 SharedFlowControlWindow::current_input_window_size() const {
- base::AutoLock autolock(lock_);
- return input_window_size_;
-}
-
-int32 SharedFlowControlWindow::current_output_window_size() const {
- base::AutoLock autolock(lock_);
- return output_window_size_;
-}
-
-int32 SharedFlowControlWindow::input_bytes_consumed() const {
- base::AutoLock autolock(lock_);
- return input_bytes_consumed_;
-}
-
-bool SharedFlowControlWindow::OnReceiveInputData(size_t length) {
- base::AutoLock autolock(lock_);
- if (aborted_) {
- return true;
- }
- DCHECK_GE(input_window_size_, 0);
- if (static_cast<size_t>(input_window_size_) < length) {
- return false;
- }
- input_window_size_ -= length;
- return true;
-}
-
-int32 SharedFlowControlWindow::OnInputDataConsumed(size_t length) {
- base::AutoLock autolock(lock_);
- if (aborted_) {
- return 0;
- }
-
- DCHECK_GE(input_bytes_consumed_, 0);
-
- // Check for overflow; this should never happen unless there is a bug in
- // mod_spdy, since we should never say we've consumed more data than we've
- // actually received.
- {
- const int64 new_input_bytes_consumed =
- static_cast<int64>(input_bytes_consumed_) + static_cast<int64>(length);
- CHECK_LE(new_input_bytes_consumed,
- static_cast<int64>(init_input_window_size_));
- CHECK_LE(new_input_bytes_consumed + static_cast<int64>(input_window_size_),
- static_cast<int64>(init_input_window_size_));
- input_bytes_consumed_ = new_input_bytes_consumed;
- }
-
- // Only send a WINDOW_UPDATE when we've consumed 1/16 of the maximum shared
- // window size, so that we don't send lots of small WINDOW_UDPATE frames.
- if (input_bytes_consumed_ < init_input_window_size_ / 16) {
- return 0;
- } else {
- input_window_size_ += input_bytes_consumed_;
- const int32 consumed = input_bytes_consumed_;
- input_bytes_consumed_ = 0;
- return consumed;
- }
-}
-
-void SharedFlowControlWindow::OnInputDataConsumedSendUpdateIfNeeded(
- size_t length, SpdyFramePriorityQueue* output_queue) {
- const int32 update = OnInputDataConsumed(length);
- if (update > 0) {
- output_queue->Insert(SpdyFramePriorityQueue::kTopPriority,
- new net::SpdyWindowUpdateIR(0, update));
- }
-}
-
-int32 SharedFlowControlWindow::RequestOutputQuota(int32 amount_requested) {
- base::AutoLock autolock(lock_);
- DCHECK_GT(amount_requested, 0);
-
- while (!aborted_ && output_window_size_ <= 0) {
- condvar_.Wait();
- }
-
- if (aborted_) {
- return 0;
- }
-
- // Give as much output quota as we can, but not more than is asked for.
- DCHECK_GT(output_window_size_, 0);
- const int32 amount_to_give = std::min(amount_requested, output_window_size_);
- output_window_size_ -= amount_to_give;
- DCHECK_GE(output_window_size_, 0);
- return amount_to_give;
-}
-
-bool SharedFlowControlWindow::IncreaseOutputWindowSize(int32 delta) {
- base::AutoLock autolock(lock_);
- DCHECK_GE(delta, 0);
- if (aborted_) {
- return true;
- }
-
- // Check for overflow; this can happen if the client is misbehaving.
- const int64 new_size =
- static_cast<int64>(output_window_size_) + static_cast<int64>(delta);
- if (new_size > static_cast<int64>(net::kSpdyMaximumWindowSize)) {
- return false;
- }
-
- // Increase the shared output window size, and wake up any stream threads
- // that are waiting for output quota.
- output_window_size_ += delta;
- DCHECK_LE(output_window_size_, net::kSpdyMaximumWindowSize);
- if (output_window_size_ > 0) {
- condvar_.Broadcast();
- }
- return true;
-}
-
-} // namespace mod_spdy
+++ /dev/null
-// Copyright 2013 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.
-
-#ifndef MOD_SPDY_COMMON_SHARED_FLOW_CONTROL_WINDOW_H_
-#define MOD_SPDY_COMMON_SHARED_FLOW_CONTROL_WINDOW_H_
-
-#include "base/basictypes.h"
-#include "base/compiler_specific.h"
-#include "base/synchronization/condition_variable.h"
-#include "base/synchronization/lock.h"
-
-namespace mod_spdy {
-
-class SpdyFramePriorityQueue;
-
-// SPDY/3.1 introduces an additional session-wide flow control window shared by
-// all streams, and represented in WINDOW_UPDATE frames as "stream 0". The
-// SharedFlowControlWindow class is a thread-safe object for tracking the size
-// of this shared flow control window and enforcing flow-control rules, in both
-// the input and output directions.
-class SharedFlowControlWindow {
- public:
- SharedFlowControlWindow(int32 initial_input_window_size,
- int32 initial_output_window_size);
- ~SharedFlowControlWindow();
-
- // Wake up all threads blocked on other methods. Future method calls to this
- // class will return immediately with no effect.
- void Abort();
-
- // Return true if Abort() has been called.
- bool is_aborted() const;
-
- // Get the current input/ouput window sizes (of course, it might very soon
- // change if other threads are accessing this object). This is primarily
- // useful for testing/debugging.
- int32 current_input_window_size() const;
- int32 current_output_window_size() const;
- // How many input bytes have been consumed that _haven't_ yet been
- // acknowledged by a WINDOW_UPDATE (signaled by OnInputDataConsumed)? This
- // is primarily useful for testing/debugging.
- int32 input_bytes_consumed() const;
-
- // Called by the connection thread when input data is received from the
- // client. Returns true (and reduces the input window size) on success, or
- // false if the input window is too small to accept that much data, in which
- // case the client has committed a flow control error and should be sent a
- // GOAWAY. If the SharedFlowControlWindow has already been aborted
- // (i.e. because the session is shutting down), returns true with no effect.
- bool OnReceiveInputData(size_t length) WARN_UNUSED_RESULT;
-
- // Called by stream threads when input data from the client has been
- // consumed. If a session WINDOW_UPDATE (stream 0) should be sent, returns
- // the size of the update to send; otherwise, returns zero. If the
- // SharedFlowControlWindow has already been aborted, returns 0 with no
- // effect.
- int32 OnInputDataConsumed(size_t length) WARN_UNUSED_RESULT;
-
- // Like OnInputDataConsumed, but automatically send a WINDOW_UPDATE for
- // stream 0 if needed.
- void OnInputDataConsumedSendUpdateIfNeeded(
- size_t length, SpdyFramePriorityQueue* output_queue);
-
- // This should be called by stream threads to consume quota from the shared
- // flow control window. Consumes up to `amount_requested` bytes from the
- // window (less if the window is currently smaller than `amount_requested`)
- // and returns the number of bytes successfully consumed. If the window is
- // currently empty, blocks until some value can be returned (or the
- // SharedFlowControlWindow is aborted); if the SharedFlowControlWindow is
- // aborted, returns zero. The `amount_requested` must be strictly positive.
- int32 RequestOutputQuota(int32 amount_requested) WARN_UNUSED_RESULT;
-
- // This should be called by the connection thread to adjust the window size,
- // due to receiving a WINDOW_UPDATE frame from the client. The delta
- // argument must be non-negative (WINDOW_UPDATE is never negative). Return
- // false if the delta would cause the window size to overflow (in which case
- // the client has committed a flow control error and should be sent a
- // GOAWAY), true otherwise. If the SharedFlowControlWindow has already been
- // aborted, returns true with no effect.
- bool IncreaseOutputWindowSize(int32 delta) WARN_UNUSED_RESULT;
-
- private:
- mutable base::Lock lock_; // protects the below fields
- base::ConditionVariable condvar_;
- bool aborted_;
- const int32 init_input_window_size_;
- int32 input_window_size_;
- int32 input_bytes_consumed_;
- int32 output_window_size_;
-
- DISALLOW_COPY_AND_ASSIGN(SharedFlowControlWindow);
-};
-
-} // namespace mod_spdy
-
-#endif // MOD_SPDY_COMMON_SHARED_FLOW_CONTROL_WINDOW_H_
+++ /dev/null
-// Copyright 2013 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.
-
-#include "mod_spdy/common/shared_flow_control_window.h"
-
-#include "base/threading/platform_thread.h"
-#include "mod_spdy/common/spdy_frame_priority_queue.h"
-#include "mod_spdy/common/testing/async_task_runner.h"
-#include "mod_spdy/common/testing/notification.h"
-#include "mod_spdy/common/testing/spdy_frame_matchers.h"
-#include "net/spdy/spdy_protocol.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace {
-
-// Test that when we receive input data, the input window size decreases, and
-// if we try to receive more data than the window allows, then
-// OnReceiveInputData returns false.
-TEST(SharedFlowControlWindowTest, ReceiveInput) {
- mod_spdy::SharedFlowControlWindow shared_window(1000, 1000);
- ASSERT_EQ(1000, shared_window.current_input_window_size());
-
- EXPECT_TRUE(shared_window.OnReceiveInputData(320));
- ASSERT_EQ(680, shared_window.current_input_window_size());
-
- EXPECT_TRUE(shared_window.OnReceiveInputData(600));
- ASSERT_EQ(80, shared_window.current_input_window_size());
-
- EXPECT_FALSE(shared_window.OnReceiveInputData(100));
- ASSERT_EQ(80, shared_window.current_input_window_size());
-
- EXPECT_TRUE(shared_window.OnReceiveInputData(80));
- ASSERT_EQ(0, shared_window.current_input_window_size());
-
- EXPECT_FALSE(shared_window.OnReceiveInputData(1));
- ASSERT_EQ(0, shared_window.current_input_window_size());
-}
-
-// Test that when we consume input data that we've already received, the input
-// window size goes up, but only once we've consumed enough total data for it
-// to be worth it to send a WINDOW_UPDATE.
-TEST(SharedFlowControlWindowTest, ConsumeInput) {
- mod_spdy::SharedFlowControlWindow shared_window(1000, 1000);
- ASSERT_FALSE(shared_window.is_aborted());
- ASSERT_EQ(1000, shared_window.current_input_window_size());
-
- EXPECT_TRUE(shared_window.OnReceiveInputData(1000));
- EXPECT_EQ(0, shared_window.current_input_window_size());
-
- EXPECT_EQ(0, shared_window.OnInputDataConsumed(10));
- EXPECT_EQ(0, shared_window.current_input_window_size());
- EXPECT_EQ(10, shared_window.input_bytes_consumed());
-
- EXPECT_EQ(0, shared_window.OnInputDataConsumed(40));
- EXPECT_EQ(0, shared_window.current_input_window_size());
- EXPECT_EQ(50, shared_window.input_bytes_consumed());
-
- EXPECT_EQ(550, shared_window.OnInputDataConsumed(500));
- EXPECT_EQ(550, shared_window.current_input_window_size());
- EXPECT_EQ(0, shared_window.input_bytes_consumed());
-
- EXPECT_EQ(0, shared_window.OnInputDataConsumed(10));
- EXPECT_EQ(550, shared_window.current_input_window_size());
- EXPECT_EQ(10, shared_window.input_bytes_consumed());
-
- EXPECT_EQ(450, shared_window.OnInputDataConsumed(440));
- EXPECT_EQ(1000, shared_window.current_input_window_size());
- EXPECT_EQ(0, shared_window.input_bytes_consumed());
-
- shared_window.Abort();
- ASSERT_TRUE(shared_window.is_aborted());
-
- EXPECT_TRUE(shared_window.OnReceiveInputData(1));
- EXPECT_EQ(0, shared_window.OnInputDataConsumed(1000));
-}
-
-// Test that OnInputDataConsumedSendUpdateIfNeeded sends WINDOW_UPDATE frames
-// correctly.
-TEST(SharedFlowControlWindowTest, ConsumeInputSendUpdate) {
- mod_spdy::SharedFlowControlWindow shared_window(1000, 1000);
- ASSERT_EQ(1000, shared_window.current_input_window_size());
-
- EXPECT_TRUE(shared_window.OnReceiveInputData(1000));
- EXPECT_EQ(0, shared_window.current_input_window_size());
-
- mod_spdy::SpdyFramePriorityQueue queue;
- net::SpdyFrameIR* raw_frame;
-
- shared_window.OnInputDataConsumedSendUpdateIfNeeded(5, &queue);
- EXPECT_EQ(0, shared_window.current_input_window_size());
- EXPECT_EQ(5, shared_window.input_bytes_consumed());
- ASSERT_FALSE(queue.Pop(&raw_frame));
-
- shared_window.OnInputDataConsumedSendUpdateIfNeeded(933, &queue);
- EXPECT_EQ(938, shared_window.current_input_window_size());
- EXPECT_EQ(0, shared_window.input_bytes_consumed());
- ASSERT_TRUE(queue.Pop(&raw_frame));
- scoped_ptr<net::SpdyFrameIR> frame(raw_frame);
- EXPECT_THAT(*frame, mod_spdy::testing::IsWindowUpdate(0, 938));
- ASSERT_FALSE(queue.Pop(&raw_frame));
-}
-
-// Test basic usage of RequestOutputQuota and IncreaseOutputWindowSize.
-TEST(SharedFlowControlWindowTest, OutputBasic) {
- mod_spdy::SharedFlowControlWindow shared_window(1000, 1000);
- EXPECT_FALSE(shared_window.is_aborted());
- EXPECT_EQ(1000, shared_window.current_output_window_size());
-
- EXPECT_TRUE(shared_window.IncreaseOutputWindowSize(0));
- EXPECT_EQ(1000, shared_window.current_output_window_size());
-
- EXPECT_TRUE(shared_window.IncreaseOutputWindowSize(47));
- EXPECT_EQ(1047, shared_window.current_output_window_size());
-
- EXPECT_EQ(800, shared_window.RequestOutputQuota(800));
- EXPECT_EQ(247, shared_window.current_output_window_size());
-
- EXPECT_EQ(247, shared_window.RequestOutputQuota(800));
- EXPECT_EQ(0, shared_window.current_output_window_size());
-
- EXPECT_TRUE(shared_window.IncreaseOutputWindowSize(2000));
- EXPECT_EQ(2000, shared_window.current_output_window_size());
-
- // After aborting, RequestOutputQuota always returns zero (without blocking).
- EXPECT_FALSE(shared_window.is_aborted());
- shared_window.Abort();
- EXPECT_TRUE(shared_window.is_aborted());
- EXPECT_EQ(0, shared_window.RequestOutputQuota(800));
- EXPECT_EQ(0, shared_window.RequestOutputQuota(9999));
-}
-
-// When run, a RequestOutputQuotaTask requests quota from the given
-// SharedFlowControlWindow.
-class RequestOutputQuotaTask : public mod_spdy::testing::AsyncTaskRunner::Task {
- public:
- RequestOutputQuotaTask(mod_spdy::SharedFlowControlWindow* window,
- int32 request)
- : window_(window), request_(request), received_(-1) {}
- virtual void Run() {
- received_ = window_->RequestOutputQuota(request_);
- }
- int32 received() const { return received_; }
- private:
- mod_spdy::SharedFlowControlWindow* const window_;
- const int32 request_;
- int32 received_;
- DISALLOW_COPY_AND_ASSIGN(RequestOutputQuotaTask);
-};
-
-// Test that RequestOutputQuota blocks if the window is completely empty.
-TEST(SharedFlowControlWindowTest, OutputBlocking) {
- mod_spdy::SharedFlowControlWindow shared_window(1000, 350);
-
- EXPECT_EQ(200, shared_window.RequestOutputQuota(200));
- EXPECT_EQ(150, shared_window.current_output_window_size());
-
- EXPECT_EQ(150, shared_window.RequestOutputQuota(200));
- EXPECT_EQ(0, shared_window.current_output_window_size());
-
- // Start an async task to request 200 bytes. It should block, because the
- // window is empty.
- RequestOutputQuotaTask* task =
- new RequestOutputQuotaTask(&shared_window, 200);
- mod_spdy::testing::AsyncTaskRunner runner(task);
- ASSERT_TRUE(runner.Start());
- base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(50));
- runner.notification()->ExpectNotSet();
-
- // Now increase the window size. RequestOutputQuota should unblock and return
- // what's available.
- EXPECT_TRUE(shared_window.IncreaseOutputWindowSize(63));
- runner.notification()->ExpectSetWithinMillis(100);
- EXPECT_EQ(63, task->received());
-}
-
-// Test that RequestOutputQuota unblocks if we abort.
-TEST(SharedFlowControlWindowTest, OutputAborting) {
- mod_spdy::SharedFlowControlWindow shared_window(1000, 350);
-
- EXPECT_EQ(350, shared_window.RequestOutputQuota(500));
- EXPECT_EQ(0, shared_window.current_output_window_size());
-
- // Start an async task to request 200 bytes. It should block, because the
- // window is empty.
- RequestOutputQuotaTask* task =
- new RequestOutputQuotaTask(&shared_window, 200);
- mod_spdy::testing::AsyncTaskRunner runner(task);
- ASSERT_TRUE(runner.Start());
- base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(50));
- runner.notification()->ExpectNotSet();
-
- // Now abort. RequestOutputQuota should unblock and return zero.
- EXPECT_FALSE(shared_window.is_aborted());
- shared_window.Abort();
- runner.notification()->ExpectSetWithinMillis(100);
- EXPECT_EQ(0, task->received());
- EXPECT_TRUE(shared_window.is_aborted());
-
- // Abort again, to check that it's idempotent.
- shared_window.Abort();
- EXPECT_TRUE(shared_window.is_aborted());
- EXPECT_EQ(0, shared_window.RequestOutputQuota(800));
-}
-
-} // namespace
+++ /dev/null
-// 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.
-
-#include "mod_spdy/common/spdy_frame_priority_queue.h"
-
-#include <list>
-#include <map>
-
-#include "base/logging.h"
-#include "base/stl_util.h"
-#include "base/synchronization/condition_variable.h"
-#include "base/synchronization/lock.h"
-#include "base/time/time.h"
-#include "net/spdy/spdy_protocol.h"
-
-namespace mod_spdy {
-
-SpdyFramePriorityQueue::SpdyFramePriorityQueue()
- : condvar_(&lock_) {}
-
-SpdyFramePriorityQueue::~SpdyFramePriorityQueue() {
- for (QueueMap::iterator iter = queue_map_.begin();
- iter != queue_map_.end(); ++iter) {
- FrameList* list = iter->second;
- STLDeleteContainerPointers(list->begin(), list->end());
- delete list;
- }
-}
-
-bool SpdyFramePriorityQueue::IsEmpty() const {
- base::AutoLock autolock(lock_);
- return queue_map_.empty();
-}
-
-const int SpdyFramePriorityQueue::kTopPriority = -1;
-
-void SpdyFramePriorityQueue::Insert(int priority, net::SpdyFrameIR* frame) {
- base::AutoLock autolock(lock_);
- DCHECK(frame);
-
- // Get the frame list for the given priority; if it doesn't currently exist,
- // create it in the map.
- FrameList* list = NULL;
- QueueMap::iterator iter = queue_map_.find(priority);
- if (iter == queue_map_.end()) {
- list = new FrameList;
- queue_map_[priority] = list;
- } else {
- list = iter->second;
- }
- DCHECK(list);
-
- // Add the frame to the end of the list, and wake up at most one thread
- // sleeping on a BlockingPop.
- list->push_back(frame);
- condvar_.Signal();
-}
-
-bool SpdyFramePriorityQueue::Pop(net::SpdyFrameIR** frame) {
- base::AutoLock autolock(lock_);
- return InternalPop(frame);
-}
-
-bool SpdyFramePriorityQueue::BlockingPop(const base::TimeDelta& max_time,
- net::SpdyFrameIR** frame) {
- base::AutoLock autolock(lock_);
- DCHECK(frame);
-
- const base::TimeDelta zero = base::TimeDelta();
- base::TimeDelta time_remaining = max_time;
- while (time_remaining > zero && queue_map_.empty()) {
- // TODO(mdsteele): It appears from looking at the Chromium source code that
- // HighResNow() is "expensive" on Windows (how expensive, I am not sure);
- // however, the other options for getting a "now" time either don't
- // guarantee monotonicity (so time might go backwards) or might be too
- // low-resolution for our purposes, so I think we'd better stick with this
- // for now. But is there a better way to do what we're doing here?
- const base::TimeTicks start = base::TimeTicks::HighResNow();
- condvar_.TimedWait(time_remaining);
- time_remaining -= base::TimeTicks::HighResNow() - start;
- }
-
- return InternalPop(frame);
-}
-
-bool SpdyFramePriorityQueue::InternalPop(net::SpdyFrameIR** frame) {
- lock_.AssertAcquired();
- DCHECK(frame);
- if (queue_map_.empty()) {
- return false;
- }
- // As an invariant, the lists in the queue map are never empty. So get the
- // list of highest priority (smallest priority number) and pop the first
- // frame from it.
- QueueMap::iterator iter = queue_map_.begin();
- FrameList* list = iter->second;
- DCHECK(!list->empty());
- *frame = list->front();
- list->pop_front();
- // If the list is now empty, we have to delete it from the map to maintain
- // the invariant.
- if (list->empty()) {
- queue_map_.erase(iter);
- delete list;
- }
- return true;
-}
-
-} // namespace mod_spdy
+++ /dev/null
-// 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.
-
-#ifndef MOD_SPDY_COMMON_SPDY_FRAME_PRIORITY_QUEUE_H_
-#define MOD_SPDY_COMMON_SPDY_FRAME_PRIORITY_QUEUE_H_
-
-#include <list>
-#include <map>
-
-#include "base/basictypes.h"
-#include "base/synchronization/condition_variable.h"
-#include "base/synchronization/lock.h"
-
-namespace base { class TimeDelta; }
-
-namespace net { class SpdyFrameIR; }
-
-namespace mod_spdy {
-
-// A priority queue of SPDY frames, intended for multiplexing output frames
-// from multiple SPDY stream threads back to the SPDY connection thread and
-// allowing frames from high-priority streams to cut in front of lower-priority
-// streams. This class is thread-safe -- its methods may be called
-// concurrently by multiple threads.
-class SpdyFramePriorityQueue {
- public:
- // Create an initially-empty queue.
- SpdyFramePriorityQueue();
- ~SpdyFramePriorityQueue();
-
- // Return true if the queue is currently empty. (Of course, there's no
- // guarantee that another thread won't change that as soon as this method
- // returns.)
- bool IsEmpty() const;
-
- // A priority value that is more important than any priority normally used
- // for sending SPDY frames.
- static const int kTopPriority;
-
- // Insert a frame into the queue at the specified priority. The queue takes
- // ownership of the frame, and will delete it if the queue is deleted before
- // the frame is removed from the queue by the Pop method. Note that smaller
- // numbers indicate higher priorities.
- void Insert(int priority, net::SpdyFrameIR* frame);
-
- // Remove and provide a frame from the queue and return true, or return false
- // if the queue is empty. The caller gains ownership of the provided frame
- // object. This method will try to yield higher-priority frames before
- // lower-priority ones (even if they were inserted later), but guarantees to
- // return same-priority frames in the same order they were inserted (FIFO).
- // In particular, this means that a sequence of frames from the same SPDY
- // stream will stay in order (assuming they were all inserted with the same
- // priority -- that of the stream).
- bool Pop(net::SpdyFrameIR** frame);
-
- // Like Pop(), but if the queue is empty this method will block for up to
- // max_time before returning false.
- bool BlockingPop(const base::TimeDelta& max_time, net::SpdyFrameIR** frame);
-
- private:
- // Same as Pop(), but requires lock_ to be held.
- bool InternalPop(net::SpdyFrameIR** frame);
-
- mutable base::Lock lock_;
- base::ConditionVariable condvar_;
- // We use a map of lists to store frames, to guarantee that frames of the
- // same priority are stored in FIFO order. A simpler implementation would be
- // to just use a multimap, which in practice is nearly always implemented
- // with the FIFO behavior that we want, but the spec doesn't actually
- // guarantee that behavior.
- //
- // Each list stores frames of a particular priority. Invariant: the lists in
- // the QueueMap are never empty; if one of the lists becomes empty, that
- // key/value pair is immediately removed from the map.
- typedef std::list<net::SpdyFrameIR*> FrameList;
- typedef std::map<int, FrameList*> QueueMap;
- QueueMap queue_map_;
-
- DISALLOW_COPY_AND_ASSIGN(SpdyFramePriorityQueue);
-};
-
-} // namespace mod_spdy
-
-#endif // MOD_SPDY_COMMON_SPDY_FRAME_PRIORITY_QUEUE_H_
+++ /dev/null
-// 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.
-
-#include "mod_spdy/common/spdy_frame_priority_queue.h"
-
-#include "base/time/time.h"
-#include "mod_spdy/common/testing/spdy_frame_matchers.h"
-#include "net/spdy/spdy_framer.h"
-#include "net/spdy/spdy_protocol.h"
-#include "testing/gmock/include/gmock/gmock.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace {
-
-void ExpectPop(net::SpdyPingId expected,
- mod_spdy::SpdyFramePriorityQueue* queue) {
- EXPECT_FALSE(queue->IsEmpty());
- net::SpdyFrameIR* raw_frame = NULL;
- const bool success = queue->Pop(&raw_frame);
- scoped_ptr<net::SpdyFrameIR> scoped_frame(raw_frame);
- EXPECT_TRUE(success);
- ASSERT_TRUE(scoped_frame != NULL);
- EXPECT_THAT(*scoped_frame, mod_spdy::testing::IsPing(expected));
-}
-
-void ExpectEmpty(mod_spdy::SpdyFramePriorityQueue* queue) {
- EXPECT_TRUE(queue->IsEmpty());
- net::SpdyFrameIR* frame = NULL;
- EXPECT_FALSE(queue->Pop(&frame));
- EXPECT_TRUE(frame == NULL);
-}
-
-TEST(SpdyFramePriorityQueueTest, InsertSpdy2) {
- net::SpdyFramer framer(net::SPDY2);
- mod_spdy::SpdyFramePriorityQueue queue;
- ExpectEmpty(&queue);
-
- EXPECT_EQ(3u, framer.GetLowestPriority());
- EXPECT_EQ(0u, framer.GetHighestPriority());
-
- queue.Insert(3, new net::SpdyPingIR(4));
- queue.Insert(0, new net::SpdyPingIR(1));
- queue.Insert(3, new net::SpdyPingIR(3));
-
- ExpectPop(1, &queue);
- ExpectPop(4, &queue);
-
- queue.Insert(2, new net::SpdyPingIR(2));
- queue.Insert(1, new net::SpdyPingIR(6));
- queue.Insert(1, new net::SpdyPingIR(5));
-
- ExpectPop(6, &queue);
- ExpectPop(5, &queue);
- ExpectPop(2, &queue);
- ExpectPop(3, &queue);
- ExpectEmpty(&queue);
-}
-
-TEST(SpdyFramePriorityQueueTest, InsertSpdy3) {
- net::SpdyFramer framer(net::SPDY3);
- mod_spdy::SpdyFramePriorityQueue queue;
- ExpectEmpty(&queue);
-
- EXPECT_EQ(7u, framer.GetLowestPriority());
- EXPECT_EQ(0u, framer.GetHighestPriority());
-
- queue.Insert(7, new net::SpdyPingIR(4));
- queue.Insert(0, new net::SpdyPingIR(1));
- queue.Insert(7, new net::SpdyPingIR(3));
-
- ExpectPop(1, &queue);
- ExpectPop(4, &queue);
-
- queue.Insert(6, new net::SpdyPingIR(2));
- queue.Insert(1, new net::SpdyPingIR(6));
- queue.Insert(5, new net::SpdyPingIR(5));
-
- ExpectPop(6, &queue);
- ExpectPop(5, &queue);
- ExpectPop(2, &queue);
- ExpectPop(3, &queue);
- ExpectEmpty(&queue);
-}
-
-TEST(SpdyFramePriorityQueueTest, InsertTopPriority) {
- mod_spdy::SpdyFramePriorityQueue queue;
- ExpectEmpty(&queue);
-
- queue.Insert(3, new net::SpdyPingIR(4));
- queue.Insert(mod_spdy::SpdyFramePriorityQueue::kTopPriority,
- new net::SpdyPingIR(2));
- queue.Insert(mod_spdy::SpdyFramePriorityQueue::kTopPriority,
- new net::SpdyPingIR(6));
- queue.Insert(0, new net::SpdyPingIR(1));
- queue.Insert(3, new net::SpdyPingIR(3));
-
- ExpectPop(2, &queue);
- ExpectPop(6, &queue);
- ExpectPop(1, &queue);
- ExpectPop(4, &queue);
-
- queue.Insert(mod_spdy::SpdyFramePriorityQueue::kTopPriority,
- new net::SpdyPingIR(5));
-
- ExpectPop(5, &queue);
- ExpectPop(3, &queue);
- ExpectEmpty(&queue);
-}
-
-TEST(SpdyFramePriorityQueueTest, BlockingPop) {
- mod_spdy::SpdyFramePriorityQueue queue;
- net::SpdyFrameIR* frame;
- ASSERT_FALSE(queue.Pop(&frame));
-
- const base::TimeDelta time_to_wait = base::TimeDelta::FromMilliseconds(50);
- const base::TimeTicks start = base::TimeTicks::HighResNow();
- ASSERT_FALSE(queue.BlockingPop(time_to_wait, &frame));
- const base::TimeDelta actual_time_waited =
- base::TimeTicks::HighResNow() - start;
-
- // Check that we waited at least as long as we asked for.
- EXPECT_GE(actual_time_waited, time_to_wait);
- // Check that we didn't wait too much longer than we asked for.
- EXPECT_LT(actual_time_waited.InMillisecondsF(),
- 1.1 * time_to_wait.InMillisecondsF());
-}
-
-} // namespace
+++ /dev/null
-// 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.
-
-#include "mod_spdy/common/spdy_frame_queue.h"
-
-#include <list>
-
-#include "base/logging.h"
-#include "base/stl_util.h"
-#include "base/synchronization/condition_variable.h"
-#include "base/synchronization/lock.h"
-#include "net/spdy/spdy_protocol.h"
-
-namespace mod_spdy {
-
-SpdyFrameQueue::SpdyFrameQueue()
- : condvar_(&lock_), is_aborted_(false) {}
-
-SpdyFrameQueue::~SpdyFrameQueue() {
- STLDeleteContainerPointers(queue_.begin(), queue_.end());
-}
-
-bool SpdyFrameQueue::is_aborted() const {
- base::AutoLock autolock(lock_);
- return is_aborted_;
-}
-
-void SpdyFrameQueue::Abort() {
- base::AutoLock autolock(lock_);
- is_aborted_ = true;
- STLDeleteContainerPointers(queue_.begin(), queue_.end());
- queue_.clear();
- condvar_.Broadcast();
-}
-
-void SpdyFrameQueue::Insert(net::SpdyFrameIR* frame) {
- base::AutoLock autolock(lock_);
- DCHECK(frame);
-
- if (is_aborted_) {
- DCHECK(queue_.empty());
- delete frame;
- } else {
- if (queue_.empty()) {
- condvar_.Signal();
- }
- queue_.push_front(frame);
- }
-}
-
-bool SpdyFrameQueue::Pop(bool block, net::SpdyFrameIR** frame) {
- base::AutoLock autolock(lock_);
- DCHECK(frame);
-
- if (block) {
- // Block until the queue is nonempty or we abort.
- while (queue_.empty() && !is_aborted_) {
- condvar_.Wait();
- }
- }
-
- // If we've aborted, the queue should now be empty.
- DCHECK(!is_aborted_ || queue_.empty());
- if (queue_.empty()) {
- return false;
- }
-
- *frame = queue_.back();
- queue_.pop_back();
- return true;
-}
-
-} // namespace mod_spdy
+++ /dev/null
-// 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.
-
-#ifndef MOD_SPDY_COMMON_SPDY_FRAME_QUEUE_H_
-#define MOD_SPDY_COMMON_SPDY_FRAME_QUEUE_H_
-
-#include <list>
-
-#include "base/basictypes.h"
-#include "base/synchronization/condition_variable.h"
-#include "base/synchronization/lock.h"
-
-namespace net { class SpdyFrameIR; }
-
-namespace mod_spdy {
-
-// A simple FIFO queue of SPDY frames, intended for sending input frames from
-// the SPDY connection thread to a SPDY stream thread. This class is
-// thread-safe -- all methods may be called concurrently by multiple threads.
-class SpdyFrameQueue {
- public:
- // Create an initially-empty queue.
- SpdyFrameQueue();
- ~SpdyFrameQueue();
-
- // Return true if this queue has been aborted.
- bool is_aborted() const;
-
- // Abort the queue. All frames held by the queue will be deleted; future
- // frames passed to Insert() will be immediately deleted; future calls to
- // Pop() will fail immediately; and current blocking calls to Pop will
- // immediately unblock and fail.
- void Abort();
-
- // Insert a frame into the queue. The queue takes ownership of the frame,
- // and will delete it if the queue is deleted or aborted before the frame is
- // removed from the queue by the Pop method.
- void Insert(net::SpdyFrameIR* frame);
-
- // Remove and provide a frame from the queue and return true, or return false
- // if the queue is empty or has been aborted. If the block argument is true,
- // block until a frame becomes available (or the queue is aborted). The
- // caller gains ownership of the provided frame object.
- bool Pop(bool block, net::SpdyFrameIR** frame);
-
- private:
- // This is a pretty naive implementation of a thread-safe queue, but it's
- // good enough for our purposes. We could use an apr_queue_t instead of
- // rolling our own class, but it lacks the ownership semantics that we want.
- mutable base::Lock lock_;
- base::ConditionVariable condvar_;
- std::list<net::SpdyFrameIR*> queue_;
- bool is_aborted_;
-
- DISALLOW_COPY_AND_ASSIGN(SpdyFrameQueue);
-};
-
-} // namespace mod_spdy
-
-#endif // MOD_SPDY_COMMON_SPDY_FRAME_QUEUE_H_
+++ /dev/null
-// 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.
-
-#include "mod_spdy/common/spdy_frame_queue.h"
-
-#include "base/basictypes.h"
-#include "base/threading/platform_thread.h"
-#include "mod_spdy/common/testing/async_task_runner.h"
-#include "mod_spdy/common/testing/notification.h"
-#include "mod_spdy/common/testing/spdy_frame_matchers.h"
-#include "net/spdy/spdy_protocol.h"
-#include "testing/gmock/include/gmock/gmock.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace {
-
-const int kSpdyVersion = 2;
-
-void ExpectPop(bool block, net::SpdyStreamId expected,
- mod_spdy::SpdyFrameQueue* queue) {
- net::SpdyFrameIR* raw_frame = NULL;
- const bool success = queue->Pop(block, &raw_frame);
- scoped_ptr<net::SpdyFrameIR> scoped_frame(raw_frame);
- EXPECT_TRUE(success);
- ASSERT_TRUE(scoped_frame != NULL);
- EXPECT_THAT(*scoped_frame, mod_spdy::testing::IsPing(expected));
-}
-
-void ExpectEmpty(mod_spdy::SpdyFrameQueue* queue) {
- net::SpdyFrameIR* frame = NULL;
- EXPECT_FALSE(queue->Pop(false, &frame));
- EXPECT_TRUE(frame == NULL);
-}
-
-TEST(SpdyFrameQueueTest, Simple) {
- mod_spdy::SpdyFrameQueue queue;
- ExpectEmpty(&queue);
-
- queue.Insert(new net::SpdyPingIR(4));
- queue.Insert(new net::SpdyPingIR(1));
- queue.Insert(new net::SpdyPingIR(3));
-
- ExpectPop(false, 4, &queue);
- ExpectPop(false, 1, &queue);
-
- queue.Insert(new net::SpdyPingIR(2));
- queue.Insert(new net::SpdyPingIR(5));
-
- ExpectPop(false, 3, &queue);
- ExpectPop(false, 2, &queue);
- ExpectPop(false, 5, &queue);
- ExpectEmpty(&queue);
-}
-
-TEST(SpdyFrameQueueTest, AbortEmptiesQueue) {
- mod_spdy::SpdyFrameQueue queue;
- ASSERT_FALSE(queue.is_aborted());
- ExpectEmpty(&queue);
-
- queue.Insert(new net::SpdyPingIR(4));
- queue.Insert(new net::SpdyPingIR(1));
- queue.Insert(new net::SpdyPingIR(3));
-
- ExpectPop(false, 4, &queue);
-
- queue.Abort();
-
- ExpectEmpty(&queue);
- ASSERT_TRUE(queue.is_aborted());
-}
-
-class BlockingPopTask : public mod_spdy::testing::AsyncTaskRunner::Task {
- public:
- explicit BlockingPopTask(mod_spdy::SpdyFrameQueue* queue) : queue_(queue) {}
- virtual void Run() { ExpectPop(true, 7, queue_); }
- private:
- mod_spdy::SpdyFrameQueue* const queue_;
- DISALLOW_COPY_AND_ASSIGN(BlockingPopTask);
-};
-
-TEST(SpdyFrameQueueTest, BlockingPop) {
- mod_spdy::SpdyFrameQueue queue;
-
- // Start a task that will do a blocking pop from the queue.
- mod_spdy::testing::AsyncTaskRunner runner(new BlockingPopTask(&queue));
- ASSERT_TRUE(runner.Start());
-
- // Even if we wait for a little bit, the task shouldn't complete, because
- // that thread is blocked, because the queue is still empty.
- base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(50));
- runner.notification()->ExpectNotSet();
- ExpectEmpty(&queue);
-
- // Now, if we push something into the queue, the task should soon unblock and
- // complete, and the queue should then be empty.
- queue.Insert(new net::SpdyPingIR(7));
- runner.notification()->ExpectSetWithinMillis(100);
- ExpectEmpty(&queue);
-}
-
-} // namespace
+++ /dev/null
-// 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.
-
-#include "mod_spdy/common/spdy_server_config.h"
-
-#include "mod_spdy/common/protocol_util.h"
-
-namespace {
-
-const bool kDefaultSpdyEnabled = false;
-const int kDefaultMaxStreamsPerConnection = 100;
-const int kDefaultMinThreadsPerProcess = 2;
-const int kDefaultMaxThreadsPerProcess = 10;
-const int kDefaultMaxServerPushDepth = 1;
-const bool kDefaultSendVersionHeader = true;
-const mod_spdy::spdy::SpdyVersion kDefaultUseSpdyVersionWithoutSsl =
- mod_spdy::spdy::SPDY_VERSION_NONE;
-const int kDefaultVlogLevel = 0;
-
-} // namespace
-
-namespace mod_spdy {
-
-SpdyServerConfig::SpdyServerConfig()
- : spdy_enabled_(kDefaultSpdyEnabled),
- max_streams_per_connection_(kDefaultMaxStreamsPerConnection),
- min_threads_per_process_(kDefaultMinThreadsPerProcess),
- max_threads_per_process_(kDefaultMaxThreadsPerProcess),
- max_server_push_depth_(kDefaultMaxServerPushDepth),
- send_version_header_(kDefaultSendVersionHeader),
- use_spdy_version_without_ssl_(kDefaultUseSpdyVersionWithoutSsl),
- vlog_level_(kDefaultVlogLevel) {}
-
-SpdyServerConfig::~SpdyServerConfig() {}
-
-void SpdyServerConfig::MergeFrom(const SpdyServerConfig& a,
- const SpdyServerConfig& b) {
- spdy_enabled_.MergeFrom(a.spdy_enabled_, b.spdy_enabled_);
- max_streams_per_connection_.MergeFrom(a.max_streams_per_connection_,
- b.max_streams_per_connection_);
- min_threads_per_process_.MergeFrom(a.min_threads_per_process_,
- b.min_threads_per_process_);
- max_threads_per_process_.MergeFrom(a.max_threads_per_process_,
- b.max_threads_per_process_);
- max_server_push_depth_.MergeFrom(a.max_server_push_depth_,
- b.max_server_push_depth_);
- send_version_header_.MergeFrom(
- a.send_version_header_, b.send_version_header_);
- use_spdy_version_without_ssl_.MergeFrom(
- a.use_spdy_version_without_ssl_, b.use_spdy_version_without_ssl_);
- vlog_level_.MergeFrom(a.vlog_level_, b.vlog_level_);
-}
-
-} // namespace mod_spdy
+++ /dev/null
-// 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.
-
-#ifndef MOD_SPDY_COMMON_SPDY_SERVER_CONFIG_H_
-#define MOD_SPDY_COMMON_SPDY_SERVER_CONFIG_H_
-
-#include "base/basictypes.h"
-#include "mod_spdy/common/protocol_util.h"
-
-namespace mod_spdy {
-
-// Stores server configuration settings for our module.
-class SpdyServerConfig {
- public:
- SpdyServerConfig();
- ~SpdyServerConfig();
-
- // Return true if SPDY is enabled for this server, false otherwise.
- bool spdy_enabled() const { return spdy_enabled_.get(); }
-
- // Return the maximum number of simultaneous SPDY streams that should be
- // permitted for a single client connection.
- int max_streams_per_connection() const {
- return max_streams_per_connection_.get();
- }
-
- // Return the minimum number of worker threads to spawn per child process.
- int min_threads_per_process() const {
- return min_threads_per_process_.get();
- }
-
- // Return the maximum number of worker threads to spawn per child process.
- int max_threads_per_process() const {
- return max_threads_per_process_.get();
- }
-
- // Return the maximum number of recursive levels to follow
- // X-Associated-Content headers
- int max_server_push_depth() const {
- return max_server_push_depth_.get();
- }
-
- // Whether or not we should include an x-mod-spdy header with the module
- // version number.
- bool send_version_header() const { return send_version_header_.get(); }
-
- // If nonzero, assume (unencrypted) SPDY/x for non-SSL connections, where x
- // is the version number returned here. This will most likely break normal
- // browsers, but is useful for testing.
- spdy::SpdyVersion use_spdy_version_without_ssl() const {
- return use_spdy_version_without_ssl_.get();
- }
-
- // Return the maximum VLOG level we should use.
- int vlog_level() const { return vlog_level_.get(); }
-
- // Setters. Call only during the configuration phase.
- void set_spdy_enabled(bool b) { spdy_enabled_.set(b); }
- void set_max_streams_per_connection(int n) {
- max_streams_per_connection_.set(n);
- }
- void set_min_threads_per_process(int n) { min_threads_per_process_.set(n); }
- void set_max_threads_per_process(int n) { max_threads_per_process_.set(n); }
- void set_max_server_push_depth(int n) { max_server_push_depth_.set(n); }
- void set_send_version_header(bool b) { send_version_header_.set(b); }
- void set_use_spdy_version_without_ssl(spdy::SpdyVersion v) {
- use_spdy_version_without_ssl_.set(v);
- }
- void set_vlog_level(int n) { vlog_level_.set(n); }
-
- // Set this config object to the merge of a and b. Call only during the
- // configuration phase.
- void MergeFrom(const SpdyServerConfig& a, const SpdyServerConfig& b);
-
- private:
- template <typename T>
- class Option {
- public:
- explicit Option(const T& default_value)
- : was_set_(false), value_(default_value) {}
- const T& get() const { return value_; }
- void set(const T& value) { was_set_ = true; value_ = value; }
- void MergeFrom(const Option<T>& a, const Option<T>& b) {
- was_set_ = a.was_set_ || b.was_set_;
- value_ = a.was_set_ ? a.value_ : b.value_;
- }
- private:
- bool was_set_;
- T value_;
- DISALLOW_COPY_AND_ASSIGN(Option);
- };
-
- // Configuration fields:
- Option<bool> spdy_enabled_;
- Option<int> max_streams_per_connection_;
- Option<int> min_threads_per_process_;
- Option<int> max_threads_per_process_;
- Option<int> max_server_push_depth_;
- Option<bool> send_version_header_;
- Option<spdy::SpdyVersion> use_spdy_version_without_ssl_;
- Option<int> vlog_level_;
- // Note: Add more config options here as needed; be sure to also update the
- // MergeFrom method in spdy_server_config.cc.
-
- DISALLOW_COPY_AND_ASSIGN(SpdyServerConfig);
-};
-
-} // namespace mod_spdy
-
-#endif // MOD_SPDY_CONTEXT_SPDY_SERVER_CONFIG_H_
+++ /dev/null
-// 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.
-
-#include "mod_spdy/common/spdy_server_push_interface.h"
-
-namespace mod_spdy {
-
-SpdyServerPushInterface::SpdyServerPushInterface() {}
-
-SpdyServerPushInterface::~SpdyServerPushInterface() {}
-
-} // namespace mod_spdy
+++ /dev/null
-// 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.
-
-#ifndef MOD_SPDY_COMMON_SPDY_SERVER_PUSH_INTERFACE_H_
-#define MOD_SPDY_COMMON_SPDY_SERVER_PUSH_INTERFACE_H_
-
-#include "base/basictypes.h"
-#include "net/spdy/spdy_framer.h"
-#include "net/spdy/spdy_protocol.h"
-
-namespace mod_spdy {
-
-class SpdyServerPushInterface {
- public:
- SpdyServerPushInterface();
- virtual ~SpdyServerPushInterface();
-
- enum PushStatus {
- // PUSH_STARTED: The server push was started successfully.
- PUSH_STARTED,
- // INVALID_REQUEST_HEADERS: The given request headers were invalid for a
- // server push (e.g. because required headers were missing).
- INVALID_REQUEST_HEADERS,
- // ASSOCIATED_STREAM_INACTIVE: The push could not be started because the
- // associated stream is not currently active.
- ASSOCIATED_STREAM_INACTIVE,
- // CANNOT_PUSH_EVER_AGAIN: We can't do any more pushes on this session,
- // either because the client has already sent us a GOAWAY frame, or the
- // session has been open so long that we've run out of stream IDs.
- CANNOT_PUSH_EVER_AGAIN,
- // TOO_MANY_CONCURRENT_PUSHES: The push could not be started right now
- // because there are too many currently active push streams.
- TOO_MANY_CONCURRENT_PUSHES,
- // PUSH_INTERNAL_ERROR: There was an internal error in the SpdySession
- // (typically something that caused a LOG(DFATAL).
- PUSH_INTERNAL_ERROR,
- };
-
- // Initiate a SPDY server push, roughly by pretending that the client sent a
- // SYN_STREAM with the given headers. To repeat: the headers argument is
- // _not_ the headers that the server will send to the client, but rather the
- // headers to _pretend_ that the client sent to the server.
- virtual PushStatus StartServerPush(
- net::SpdyStreamId associated_stream_id,
- int32 server_push_depth,
- net::SpdyPriority priority,
- const net::SpdyHeaderBlock& request_headers) = 0;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(SpdyServerPushInterface);
-};
-
-} // namespace mod_spdy
-
-#endif // MOD_SPDY_COMMON_SPDY_SERVER_PUSH_INTERFACE_H_
+++ /dev/null
-// 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.
-
-#include "mod_spdy/common/spdy_session.h"
-
-#include "base/basictypes.h"
-#include "base/logging.h"
-#include "base/memory/scoped_ptr.h"
-#include "base/synchronization/lock.h"
-#include "base/time/time.h"
-#include "mod_spdy/common/protocol_util.h"
-#include "mod_spdy/common/spdy_server_config.h"
-#include "mod_spdy/common/spdy_session_io.h"
-#include "mod_spdy/common/spdy_stream.h"
-#include "mod_spdy/common/spdy_stream_task_factory.h"
-#include "net/spdy/spdy_protocol.h"
-
-namespace {
-
-// Server push stream IDs must be even, and must fit in 31 bits (SPDY draft 3
-// section 2.3.2). Thus, this is the largest stream ID we can ever use for a
-// pushed stream.
-const net::SpdyStreamId kMaxServerPushStreamId = 0x7FFFFFFEu;
-
-// Until the client informs us otherwise, we will assume a limit of 100 open
-// push streams at a time.
-const uint32 kInitMaxConcurrentPushes = 100u;
-
-} // namespace
-
-namespace mod_spdy {
-
-SpdySession::SpdySession(spdy::SpdyVersion spdy_version,
- const SpdyServerConfig* config,
- SpdySessionIO* session_io,
- SpdyStreamTaskFactory* task_factory,
- Executor* executor)
- : spdy_version_(spdy_version),
- config_(config),
- session_io_(session_io),
- task_factory_(task_factory),
- executor_(executor),
- framer_(SpdyVersionToFramerVersion(spdy_version), true),
- session_stopped_(false),
- already_sent_goaway_(false),
- last_client_stream_id_(0u),
- initial_window_size_(net::kSpdyStreamInitialWindowSize),
- max_concurrent_pushes_(kInitMaxConcurrentPushes),
- last_server_push_stream_id_(0u),
- received_goaway_(false),
- shared_window_(net::kSpdyStreamInitialWindowSize,
- net::kSpdyStreamInitialWindowSize) {
- DCHECK_NE(spdy::SPDY_VERSION_NONE, spdy_version);
- framer_.set_visitor(this);
-}
-
-SpdySession::~SpdySession() {}
-
-int32 SpdySession::current_shared_input_window_size() const {
- DCHECK_GE(spdy_version_, spdy::SPDY_VERSION_3_1);
- return shared_window_.current_input_window_size();
-}
-
-int32 SpdySession::current_shared_output_window_size() const {
- DCHECK_GE(spdy_version_, spdy::SPDY_VERSION_3_1);
- return shared_window_.current_output_window_size();
-}
-
-void SpdySession::Run() {
- // Send a SETTINGS frame when the connection first opens, to inform the
- // client of our MAX_CONCURRENT_STREAMS limit.
- SendSettingsFrame();
-
- // Initial amount time to block when waiting for output -- we start with
- // this, and as long as we fail to perform any input OR output, we increase
- // exponentially to the max, resetting when we succeed again.
- const base::TimeDelta kInitOutputBlockTime =
- base::TimeDelta::FromMilliseconds(1);
- // Maximum time to block when waiting for output.
- const base::TimeDelta kMaxOutputBlockTime =
- base::TimeDelta::FromMilliseconds(30);
-
- base::TimeDelta output_block_time = kInitOutputBlockTime;
-
- // Until we stop the session, or it is aborted by the client, alternate
- // between reading input from the client and (compressing and) sending output
- // frames that our stream threads have posted to the output queue. This
- // basically amounts to a busy-loop, switching back and forth between input
- // and output, so we do our best to block when we can. It would be far nicer
- // to have separate threads for input and output and have them always block;
- // unfortunately, we cannot do that, because in Apache the input and output
- // filter chains for a connection must be invoked by the same thread.
- while (!session_stopped_) {
- if (session_io_->IsConnectionAborted()) {
- LOG(WARNING) << "Master connection was aborted.";
- StopSession();
- break;
- }
-
- // Step 1: Read input from the client.
- {
- // Determine whether we should block until more input data is available.
- // For now, our policy is to block only if there is no pending output and
- // there are no currently-active streams (which might produce new
- // output).
- const bool should_block = StreamMapIsEmpty() && output_queue_.IsEmpty();
-
- // If there's no current output, and we can't create new streams (so
- // there will be no future output), then we should just shut down the
- // connection.
- if (should_block && already_sent_goaway_) {
- StopSession();
- break;
- }
-
- // Read available input data. The SpdySessionIO will grab any
- // available data and push it into the SpdyFramer that we pass to it
- // here; the SpdyFramer, in turn, will call our OnControl and/or
- // OnStreamFrameData methods to report decoded frames. If no input data
- // is currently available and should_block is true, this will block until
- // input becomes available (or the connection is closed).
- const SpdySessionIO::ReadStatus status =
- session_io_->ProcessAvailableInput(should_block, &framer_);
- if (status == SpdySessionIO::READ_SUCCESS) {
- // We successfully did some I/O, so reset the output block timeout.
- output_block_time = kInitOutputBlockTime;
- } else if (status == SpdySessionIO::READ_CONNECTION_CLOSED) {
- // The reading side of the connection has closed, so we won't be
- // reading anything more. SPDY is transport-layer agnostic and not
- // TCP-specific; apparently, this means that there is no expectation
- // that we behave any differently for a half-closed connection than for
- // a fully-closed connection. So if the reading side of the connection
- // closes, we're just going to shut down completely.
- //
- // But just in case the writing side is still open, let's try to send a
- // GOAWAY to let the client know we're shutting down gracefully.
- SendGoAwayFrame(net::GOAWAY_OK);
- // Now, shut everything down.
- StopSession();
- } else if (status == SpdySessionIO::READ_ERROR) {
- // There was an error during reading, so the session is corrupted and
- // we have no chance of reading anything more.
- //
- // We've probably already sent a GOAWAY with a PROTOCOL_ERROR by this
- // point, but if we haven't (perhaps the error was our fault?) then
- // send a GOAWAY now. (If we've already sent a GOAWAY, then
- // SendGoAwayFrame is a no-op.)
- SendGoAwayFrame(net::GOAWAY_INTERNAL_ERROR);
- // Now, shut everything down.
- StopSession();
- } else {
- // Otherwise, there's simply no data available at the moment.
- DCHECK_EQ(SpdySessionIO::READ_NO_DATA, status);
- }
- }
-
- // Step 2: Send output to the client.
- if (!session_stopped_) {
- // If there are no active streams, then no new output can be getting
- // created right now, so we shouldn't block on output waiting for more.
- const bool no_active_streams = StreamMapIsEmpty();
-
- // Send any pending output, one frame at a time. If there are any active
- // streams, we're willing to block briefly to wait for more frames to
- // send, if only to prevent this loop from busy-waiting too heavily --
- // not a great solution, but better than nothing for now.
- net::SpdyFrameIR* frame = NULL;
- if (no_active_streams ? output_queue_.Pop(&frame) :
- output_queue_.BlockingPop(output_block_time, &frame)) {
- do {
- SendFrame(frame);
- } while (!session_stopped_ && output_queue_.Pop(&frame));
-
- // We successfully did some I/O, so reset the output block timeout.
- output_block_time = kInitOutputBlockTime;
- } else {
- // The queue is currently empty; if no more streams can be created and
- // no more remain, we're done.
- if (already_sent_goaway_ && no_active_streams) {
- StopSession();
- } else {
- // There were no output frames within the timeout; so do an
- // exponential backoff by doubling output_block_time.
- output_block_time = std::min(kMaxOutputBlockTime,
- output_block_time * 2);
- }
- }
- }
-
- // TODO(mdsteele): What we really want to be able to do is to block until
- // *either* more input or more output is available. Unfortunely, there's
- // no good way to query the input side (in Apache). One possibility would
- // be to grab the input socket object (which we can do), and then arrange
- // to block until either the socket is ready to read OR our output queue is
- // nonempty (obviously we would abstract that away in SpdySessionIO),
- // but there's not even a nice way to do that (that I know of).
- }
-}
-
-SpdyServerPushInterface::PushStatus SpdySession::StartServerPush(
- net::SpdyStreamId associated_stream_id,
- int32 server_push_depth,
- net::SpdyPriority priority,
- const net::SpdyHeaderBlock& request_headers) {
- // Server push is pretty ill-defined in SPDY v2, so we require v3 or higher.
- DCHECK_GE(spdy_version(), spdy::SPDY_VERSION_3);
-
- // Grab the headers that we are required to send with the initial SYN_STREAM.
- const net::SpdyHeaderBlock::const_iterator host_iter =
- request_headers.find(spdy::kSpdy3Host);
- const net::SpdyHeaderBlock::const_iterator path_iter =
- request_headers.find(spdy::kSpdy3Path);
- const net::SpdyHeaderBlock::const_iterator scheme_iter =
- request_headers.find(spdy::kSpdy3Scheme);
- if (host_iter == request_headers.end() ||
- path_iter == request_headers.end() ||
- scheme_iter == request_headers.end()) {
- return SpdyServerPushInterface::INVALID_REQUEST_HEADERS;
- }
- const std::string& host_header = host_iter->second;
- const std::string& path_header = path_iter->second;
- const std::string& scheme_header = scheme_iter->second;
-
- StreamTaskWrapper* task_wrapper = NULL;
- {
- base::AutoLock autolock(stream_map_lock_);
-
- // If we've received a GOAWAY frame the client, we shouldn't create any new
- // streams on this session (SPDY draft 3 section 2.6.6).
- if (received_goaway_) {
- return SpdyServerPushInterface::CANNOT_PUSH_EVER_AGAIN;
- }
-
- // The associated stream must be active (SPDY draft 3 section 3.3.1).
- if (!stream_map_.IsStreamActive(associated_stream_id)) {
- return SpdyServerPushInterface::ASSOCIATED_STREAM_INACTIVE;
- }
-
- // Check if we're allowed to create new push streams right now (based on
- // the client SETTINGS_MAX_CONCURRENT_STREAMS). Note that the number of
- // active push streams might be (temporarily) greater than the max, if the
- // client lowered the max after we already started a bunch of pushes.
- if (stream_map_.NumActivePushStreams() >= max_concurrent_pushes_) {
- return SpdyServerPushInterface::TOO_MANY_CONCURRENT_PUSHES;
- }
-
- // In the unlikely event that the session stays open so long that we run
- // out of server push stream IDs, we may not do any more pushes on this
- // session (SPDY draft 3 section 2.3.2).
- DCHECK_LE(last_server_push_stream_id_, kMaxServerPushStreamId);
- if (last_server_push_stream_id_ >= kMaxServerPushStreamId) {
- return SpdyServerPushInterface::CANNOT_PUSH_EVER_AGAIN;
- }
- // Server push stream IDs must be even (SPDY draft 3 section 2.3.2). So
- // each time we do a push, we increment last_server_push_stream_id_ by two.
- DCHECK_EQ(last_server_push_stream_id_ % 2u, 0u);
- last_server_push_stream_id_ += 2u;
- const net::SpdyStreamId stream_id = last_server_push_stream_id_;
- // Only the server can create even stream IDs, and we never use the same
- // one twice, so our chosen stream_id should definitely not be in use.
- if (stream_map_.IsStreamActive(stream_id)) {
- LOG(DFATAL) << "Next server push stream ID already in use: "
- << stream_id;
- return SpdyServerPushInterface::PUSH_INTERNAL_ERROR;
- }
-
- // Create task and add it to the stream map.
- task_wrapper = new StreamTaskWrapper(
- this, stream_id, associated_stream_id, server_push_depth, priority);
- stream_map_.AddStreamTask(task_wrapper);
- net::SpdySynStreamIR* frame = new net::SpdySynStreamIR(stream_id);
- frame->set_associated_to_stream_id(associated_stream_id);
- frame->set_priority(priority);
- frame->set_fin(true);
- frame->GetMutableNameValueBlock()->insert(
- request_headers.begin(), request_headers.end());
- task_wrapper->stream()->PostInputFrame(frame);
-
- // Send initial SYN_STREAM to the client. It only needs to contain the
- // ":host", ":path", and ":scheme" headers; the rest can follow in a later
- // HEADERS frame (SPDY draft 3 section 3.3.1).
- net::SpdyHeaderBlock initial_response_headers;
- initial_response_headers[spdy::kSpdy3Host] = host_header;
- initial_response_headers[spdy::kSpdy3Path] = path_header;
- initial_response_headers[spdy::kSpdy3Scheme] = scheme_header;
- task_wrapper->stream()->SendOutputSynStream(
- initial_response_headers, false);
-
- VLOG(2) << "Starting server push; opening stream " << stream_id;
- }
- if (task_wrapper == NULL) {
- LOG(DFATAL) << "Can't happen: task_wrapper is NULL";
- return SpdyServerPushInterface::PUSH_INTERNAL_ERROR;
- }
- executor_->AddTask(task_wrapper, priority);
- return SpdyServerPushInterface::PUSH_STARTED;
-}
-
-void SpdySession::OnError(net::SpdyFramer::SpdyError error_code) {
- LOG(ERROR) << "Session error: "
- << net::SpdyFramer::ErrorCodeToString(error_code);
- SendGoAwayFrame(net::GOAWAY_PROTOCOL_ERROR);
-}
-
-void SpdySession::OnStreamError(net::SpdyStreamId stream_id,
- const std::string& description) {
- LOG(ERROR) << "Stream " << stream_id << " error: " << description;
- AbortStream(stream_id, net::RST_STREAM_PROTOCOL_ERROR);
-}
-
-void SpdySession::OnStreamFrameData(
- net::SpdyStreamId stream_id, const char* data, size_t length, bool fin) {
- // First check the shared input flow control window (for SPDY/3.1 and up).
- if (spdy_version_ >= spdy::SPDY_VERSION_3_1) {
- if (!shared_window_.OnReceiveInputData(length)) {
- LOG(ERROR) << "Client violated flow control by sending too much data "
- << "to session. Sending GOAWAY.";
- SendGoAwayFrame(net::GOAWAY_PROTOCOL_ERROR);
- StopSession();
- return;
- }
- }
-
- // Look up the stream to post the data to. We need to lock when reading the
- // stream map, because one of the stream threads could call
- // RemoveStreamTask() at any time.
- {
- base::AutoLock autolock(stream_map_lock_);
- SpdyStream* stream = stream_map_.GetStream(stream_id);
- if (stream != NULL) {
- VLOG(4) << "[stream " << stream_id << "] Received DATA (length="
- << length << ")";
- // Copy the data into an _uncompressed_ SPDY data frame and post it to
- // the stream's input queue.
- // Note that we must still be holding stream_map_lock_ when we call this
- // method -- otherwise the stream may be deleted out from under us by the
- // StreamTaskWrapper destructor. That's okay -- PostInputFrame is a
- // quick operation and won't block (for any appreciable length of time).
- net::SpdyDataIR* frame =
- new net::SpdyDataIR(stream_id, base::StringPiece(data, length));
- frame->set_fin(fin);
- stream->PostInputFrame(frame);
- return;
- }
- }
-
- // If we reach this point, it means that the client has sent us DATA for a
- // stream that doesn't exist (possibly because it used to exist but has
- // already been closed by a FLAG_FIN); *unless* length=0, which is just the
- // BufferedSpdyFramer's way of telling us that there will be no more data on
- // this stream (i.e. because a FLAG_FIN has been received, possibly on a
- // previous control frame).
-
- // TODO(mdsteele): The BufferedSpdyFramer sends us OnStreamFrameData with
- // length=0 to indicate end-of-stream, but it will do this even if we already
- // got FLAG_FIN in a control frame (such as SYN_STREAM). For now, we fix
- // this issue by simply ignoring length=0 data for streams that no longer
- // exist. Once we transition to the new plain SpdyFramer, we'll be able to
- // handle this more precisely.
- if (length == 0) {
- return;
- }
-
- // If the client sends data for a nonexistant stream, we must send a
- // RST_STREAM frame with error code INVALID_STREAM (SPDY draft 2 section
- // 2.4). Note that we release the mutex *before* sending the frame.
- LOG(WARNING) << "Client sent DATA (length=" << length
- << ") for nonexistant stream " << stream_id;
- SendRstStreamFrame(stream_id, net::RST_STREAM_INVALID_STREAM);
-}
-
-void SpdySession::OnSynStream(
- net::SpdyStreamId stream_id,
- net::SpdyStreamId associated_stream_id,
- net::SpdyPriority priority,
- uint8 credential_slot,
- bool fin,
- bool unidirectional,
- const net::SpdyHeaderBlock& headers) {
- // The SPDY spec requires us to ignore SYN_STREAM frames after sending a
- // GOAWAY frame (SPDY draft 3 section 2.6.6).
- if (already_sent_goaway_) {
- return;
- }
-
- // Client stream IDs must be odd-numbered.
- if (stream_id % 2 == 0) {
- LOG(WARNING) << "Client sent SYN_STREAM for even stream ID (" << stream_id
- << "). Sending GOAWAY.";
- SendGoAwayFrame(net::GOAWAY_PROTOCOL_ERROR);
- return;
- }
-
- // Client stream IDs must be strictly increasing (SPDY draft 2 section
- // 2.5.1).
- if (stream_id <= last_client_stream_id_) {
- LOG(WARNING) << "Client sent SYN_STREAM for non-increasing stream ID ("
- << stream_id << " after " << last_client_stream_id_
- << ")."; // Aborting stream.";
-#if 0
- // TODO(mdsteele): re-enable this code block when
- // http://code.google.com/p/chromium/issues/detail?id=111708 is
- // fixed.
- AbortStream(stream_id, net::PROTOCOL_ERROR);
- return;
-#endif
- }
-
- StreamTaskWrapper* task_wrapper = NULL;
- {
- // Lock the stream map before we start checking its size or adding a new
- // stream to it. We need to lock when touching the stream map, because one
- // of the stream threads could call RemoveStreamTask() at any time.
- base::AutoLock autolock(stream_map_lock_);
-
-#if 0
- // TODO(mdsteele): re-enable this code block when
- // http://code.google.com/p/chromium/issues/detail?id=111708 is
- // fixed.
-
- // We already checked that stream_id > last_client_stream_id_, so there
- // definitely shouldn't already be a stream with this ID in the map.
- DCHECK(!stream_map_.IsStreamActive(stream_id));
-#else
- if (stream_map_.IsStreamActive(stream_id)) {
- SendGoAwayFrame(net::GOAWAY_PROTOCOL_ERROR);
- return;
- }
-#endif
-
- // Limit the number of simultaneous open streams the client can create;
- // refuse the stream if there are too many currently active (non-push)
- // streams.
- if (static_cast<int>(stream_map_.NumActiveClientStreams()) >=
- config_->max_streams_per_connection()) {
- SendRstStreamFrame(stream_id, net::RST_STREAM_REFUSED_STREAM);
- return;
- }
-
- // Initiate a new stream.
- last_client_stream_id_ = std::max(last_client_stream_id_, stream_id);
- task_wrapper = new StreamTaskWrapper(
- this, stream_id, associated_stream_id,
- 0, // server_push_depth = 0
- priority);
- stream_map_.AddStreamTask(task_wrapper);
- net::SpdySynStreamIR* frame = new net::SpdySynStreamIR(stream_id);
- frame->set_associated_to_stream_id(associated_stream_id);
- frame->set_priority(priority);
- frame->set_slot(credential_slot);
- frame->set_fin(fin);
- frame->set_unidirectional(unidirectional);
- frame->GetMutableNameValueBlock()->insert(headers.begin(), headers.end());
- task_wrapper->stream()->PostInputFrame(frame);
- }
- DCHECK(task_wrapper);
- // Release the lock before adding the task to the executor. This is mostly
- // for the benefit of unit tests, for which calling AddTask will execute the
- // task immediately (and we don't want to be holding the lock when that
- // happens). Note that it's safe for us to pass task_wrapper here without
- // holding the lock, because the task won't get deleted before it's been
- // added to the executor.
- VLOG(2) << "Received SYN_STREAM; opening stream " << stream_id;
- executor_->AddTask(task_wrapper, priority);
-}
-
-void SpdySession::OnSynReply(net::SpdyStreamId stream_id,
- bool fin,
- const net::SpdyHeaderBlock& headers) {
- // TODO(mdsteele)
-}
-
-void SpdySession::OnRstStream(net::SpdyStreamId stream_id,
- net::SpdyRstStreamStatus status) {
- switch (status) {
- // These are totally benign reasons to abort a stream, so just abort the
- // stream without a fuss.
- case net::RST_STREAM_REFUSED_STREAM:
- case net::RST_STREAM_CANCEL:
- VLOG(2) << "Client cancelled/refused stream " << stream_id;
- AbortStreamSilently(stream_id);
- break;
- // If there was an error, abort the stream, but log a warning first.
- // TODO(mdsteele): Should we have special behavior for different kinds of
- // errors?
- default:
- LOG(WARNING) << "Client sent RST_STREAM with "
- << RstStreamStatusCodeToString(status)
- << " for stream " << stream_id << ". Aborting stream.";
- AbortStreamSilently(stream_id);
- break;
- }
-}
-
-void SpdySession::OnSettings(bool clear_persisted) {
- // Do nothing; we never persist values, so we don't need to pay attention to
- // this flag.
-}
-
-void SpdySession::OnSetting(net::SpdySettingsIds id,
- uint8 flags, uint32 value) {
- VLOG(4) << "Received SETTING (flags=" << flags << "): "
- << SettingsIdToString(id) << "=" << value;
- switch (id) {
- case net::SETTINGS_MAX_CONCURRENT_STREAMS:
- max_concurrent_pushes_ = value;
- break;
- case net::SETTINGS_INITIAL_WINDOW_SIZE:
- // Flow control only exists for SPDY v3 and up.
- if (spdy_version() < spdy::SPDY_VERSION_3) {
- LOG(ERROR) << "Client sent INITIAL_WINDOW_SIZE setting over "
- << "SPDY/" << SpdyVersionNumberString(spdy_version())
- << ". Sending GOAWAY.";
- SendGoAwayFrame(net::GOAWAY_PROTOCOL_ERROR);
- } else {
- SetInitialWindowSize(value);
- }
- break;
- case net::SETTINGS_UPLOAD_BANDWIDTH:
- case net::SETTINGS_DOWNLOAD_BANDWIDTH:
- case net::SETTINGS_ROUND_TRIP_TIME:
- case net::SETTINGS_CURRENT_CWND:
- case net::SETTINGS_DOWNLOAD_RETRANS_RATE:
- // Ignore other settings for now.
- break;
- default:
- LOG(ERROR) << "Client sent invalid SETTINGS id (" << id
- << "). Sending GOAWAY.";
- SendGoAwayFrame(net::GOAWAY_PROTOCOL_ERROR);
- break;
- }
-}
-
-void SpdySession::OnPing(uint32 unique_id) {
- VLOG(4) << "Received PING frame (id=" << unique_id << ")";
- // The SPDY spec requires the server to ignore even-numbered PING frames that
- // it did not initiate (SPDY draft 3 section 2.6.5), and right now, we never
- // initiate pings.
- if (unique_id % 2 == 0) {
- return;
- }
-
- // Any odd-numbered PING frame we receive was initiated by the client, and
- // should be echoed back _immediately_ (SPDY draft 2 section 2.7.6).
- SendFrame(new net::SpdyPingIR(unique_id));
-}
-
-void SpdySession::OnGoAway(net::SpdyStreamId last_accepted_stream_id,
- net::SpdyGoAwayStatus status) {
- VLOG(4) << "Received GOAWAY frame (status="
- << GoAwayStatusCodeToString(status) << ", last_accepted_stream_id="
- << last_accepted_stream_id << ")";
-
- // Take note that we have received a GOAWAY frame; we should not start any
- // new server push streams on this session.
- {
- base::AutoLock autolock(stream_map_lock_);
- received_goaway_ = true;
- }
-
- // If this was not a normal shutdown (GOAWAY_OK), we should probably log a
- // warning to let the user know something's up.
- switch (status) {
- case net::GOAWAY_OK:
- break;
- case net::GOAWAY_PROTOCOL_ERROR:
- LOG(WARNING) << "Client sent GOAWAY with PROTOCOL_ERROR. Possibly we "
- << "did something wrong?";
- break;
- case net::GOAWAY_INTERNAL_ERROR:
- LOG(WARNING) << "Client sent GOAWAY with INTERNAL_ERROR. Apparently "
- << "they're broken?";
- break;
- default:
- LOG(ERROR) << "Client sent GOAWAY with invalid status code ("
- << status << "). Sending GOAWAY.";
- SendGoAwayFrame(net::GOAWAY_PROTOCOL_ERROR);
- break;
- }
-}
-
-void SpdySession::OnHeaders(net::SpdyStreamId stream_id,
- bool fin,
- const net::SpdyHeaderBlock& headers) {
- // Look up the stream to post the data to. We need to lock when reading the
- // stream map, because one of the stream threads could call
- // RemoveStreamTask() at any time.
- {
- // TODO(mdsteele): This is pretty similar to the code in OnStreamFrameData.
- // Maybe we can factor it out?
- base::AutoLock autolock(stream_map_lock_);
- SpdyStream* stream = stream_map_.GetStream(stream_id);
- if (stream != NULL) {
- VLOG(4) << "[stream " << stream_id << "] Received HEADERS frame";
- net::SpdySynStreamIR* frame = new net::SpdySynStreamIR(stream_id);
- frame->set_fin(true);
- frame->GetMutableNameValueBlock()->insert(
- headers.begin(), headers.end());
- stream->PostInputFrame(frame);
- return;
- }
- }
-
- // Note that we release the mutex *before* sending the frame.
- LOG(WARNING) << "Client sent HEADERS for nonexistant stream " << stream_id;
- SendRstStreamFrame(stream_id, net::RST_STREAM_INVALID_STREAM);
-}
-
-void SpdySession::OnPushPromise(net::SpdyStreamId stream_id,
- net::SpdyStreamId promised_stream_id) {
- LOG(ERROR) << "Got a PUSH_PROMISE(" << stream_id << ", "
- << promised_stream_id << ") frame from the client.";
- SendGoAwayFrame(net::GOAWAY_PROTOCOL_ERROR);
-}
-
-void SpdySession::OnWindowUpdate(net::SpdyStreamId stream_id,
- uint32 delta_window_size) {
- // Flow control only exists for SPDY/3 and up.
- if (spdy_version() < spdy::SPDY_VERSION_3) {
- LOG(ERROR) << "Got a WINDOW_UPDATE frame over SPDY/"
- << SpdyVersionNumberString(spdy_version());
- SendGoAwayFrame(net::GOAWAY_PROTOCOL_ERROR);
- return;
- }
-
- // Stream zero is special; starting in SPDY/3.1, it represents the
- // session-wide flow control window. For previous versions, it is invalid.
- if (stream_id == 0) {
- if (spdy_version() >= spdy::SPDY_VERSION_3_1) {
- if (!shared_window_.IncreaseOutputWindowSize(delta_window_size)) {
- LOG(ERROR) << "Got a WINDOW_UPDATE frame that overflows session "
- << "window. Sending GOAWAY.";
- SendGoAwayFrame(net::GOAWAY_PROTOCOL_ERROR);
- StopSession();
- }
- } else {
- LOG(ERROR) << "Got a WINDOW_UPDATE frame for stream 0 over SPDY/"
- << SpdyVersionNumberString(spdy_version());
- SendGoAwayFrame(net::GOAWAY_PROTOCOL_ERROR);
- StopSession();
- }
- return;
- }
-
- base::AutoLock autolock(stream_map_lock_);
- SpdyStream* stream = stream_map_.GetStream(stream_id);
- if (stream == NULL) {
- // We must ignore WINDOW_UPDATE frames for closed streams (SPDY draft 3
- // section 2.6.8).
- return;
- }
-
- VLOG(4) << "[stream " << stream_id << "] Received WINDOW_UPDATE("
- << delta_window_size << ") frame";
- stream->AdjustOutputWindowSize(delta_window_size);
-}
-
-void SpdySession::SetInitialWindowSize(uint32 new_init_window_size) {
- // Flow control only exists for SPDY v3 and up. We shouldn't be calling this
- // method for SPDY v2.
- if (spdy_version() < spdy::SPDY_VERSION_3) {
- LOG(DFATAL) << "SetInitialWindowSize called for SPDY/"
- << SpdyVersionNumberString(spdy_version());
- return;
- }
-
- // Validate the new window size; it must be positive, but at most int32max.
- if (new_init_window_size == 0 ||
- new_init_window_size >
- static_cast<uint32>(net::kSpdyMaximumWindowSize)) {
- LOG(WARNING) << "Client sent invalid init window size ("
- << new_init_window_size << "). Sending GOAWAY.";
- SendGoAwayFrame(net::GOAWAY_PROTOCOL_ERROR);
- return;
- }
- // Sanity check that our current init window size is positive. It's a signed
- // int32, so we know it's no more than int32max.
- DCHECK_GT(initial_window_size_, 0);
- // We can now be sure that this subtraction won't overflow/underflow.
- const int32 delta =
- static_cast<int32>(new_init_window_size) - initial_window_size_;
-
- // Set the initial window size for new streams.
- initial_window_size_ = new_init_window_size;
- // We also have to adjust the window size of all currently active streams by
- // the delta (SPDY draft 3 section 2.6.8).
- base::AutoLock autolock(stream_map_lock_);
- stream_map_.AdjustAllOutputWindowSizes(delta);
-}
-
-// Compress (if necessary), send, and then delete the given frame object.
-void SpdySession::SendFrame(const net::SpdyFrameIR* frame_ptr) {
- scoped_ptr<const net::SpdyFrameIR> frame(frame_ptr);
- scoped_ptr<const net::SpdySerializedFrame> serialized_frame(
- framer_.SerializeFrame(*frame));
- if (serialized_frame == NULL) {
- LOG(DFATAL) << "frame compression failed";
- StopSession();
- return;
- }
- SendFrameRaw(*serialized_frame);
-}
-
-void SpdySession::SendFrameRaw(const net::SpdySerializedFrame& frame) {
- const SpdySessionIO::WriteStatus status = session_io_->SendFrameRaw(frame);
- if (status == SpdySessionIO::WRITE_CONNECTION_CLOSED) {
- // If the connection was closed and we can't write anything to the client
- // anymore, then there's little point in continuing with the session.
- StopSession();
- } else {
- DCHECK_EQ(SpdySessionIO::WRITE_SUCCESS, status);
- }
-}
-
-void SpdySession::SendGoAwayFrame(net::SpdyGoAwayStatus status) {
- if (!already_sent_goaway_) {
- already_sent_goaway_ = true;
- SendFrame(new net::SpdyGoAwayIR(last_client_stream_id_, status));
- }
-}
-
-void SpdySession::SendRstStreamFrame(net::SpdyStreamId stream_id,
- net::SpdyRstStreamStatus status) {
- output_queue_.Insert(SpdyFramePriorityQueue::kTopPriority,
- new net::SpdyRstStreamIR(stream_id, status));
-}
-
-void SpdySession::SendSettingsFrame() {
- scoped_ptr<net::SpdySettingsIR> settings(new net::SpdySettingsIR);
- settings->AddSetting(net::SETTINGS_MAX_CONCURRENT_STREAMS,
- false, false, config_->max_streams_per_connection());
- SendFrame(settings.release());
-}
-
-void SpdySession::StopSession() {
- session_stopped_ = true;
- // Abort all remaining streams. We need to lock when reading the stream
- // map, because one of the stream threads could call RemoveStreamTask() at
- // any time.
- {
- base::AutoLock autolock(stream_map_lock_);
- stream_map_.AbortAllSilently();
- }
- shared_window_.Abort();
- // Stop all stream threads and tasks for this SPDY session. This will
- // block until all currently running stream tasks have exited, but since we
- // just aborted all streams, that should hopefully happen fairly soon. Note
- // that we must release the lock before calling this, because each stream
- // will remove itself from the stream map as it shuts down.
- executor_->Stop();
-}
-
-// Abort the stream without sending anything to the client.
-void SpdySession::AbortStreamSilently(net::SpdyStreamId stream_id) {
- // We need to lock when reading the stream map, because one of the stream
- // threads could call RemoveStreamTask() at any time.
- base::AutoLock autolock(stream_map_lock_);
- SpdyStream* stream = stream_map_.GetStream(stream_id);
- if (stream != NULL) {
- stream->AbortSilently();
- }
-}
-
-// Send a RST_STREAM frame and then abort the stream.
-void SpdySession::AbortStream(net::SpdyStreamId stream_id,
- net::SpdyRstStreamStatus status) {
- SendRstStreamFrame(stream_id, status);
- AbortStreamSilently(stream_id);
-}
-
-// Remove the StreamTaskWrapper from the stream map. This is the only method
-// of SpdySession that is ever called by another thread (specifically, it is
-// called by the StreamTaskWrapper destructor, which is called by the executor,
-// which presumably uses worker threads) -- it is because of this that we must
-// lock the stream_map_lock_ whenever we touch the stream map or its contents.
-void SpdySession::RemoveStreamTask(StreamTaskWrapper* task_wrapper) {
- // We need to lock when touching the stream map, in case the main connection
- // thread is currently in the middle of reading the stream map.
- base::AutoLock autolock(stream_map_lock_);
- VLOG(2) << "Closing stream " << task_wrapper->stream()->stream_id();
- stream_map_.RemoveStreamTask(task_wrapper);
-}
-
-bool SpdySession::StreamMapIsEmpty() {
- base::AutoLock autolock(stream_map_lock_);
- return stream_map_.IsEmpty();
-}
-
-// This constructor is always called by the main connection thread, so we're
-// safe to call spdy_session_->task_factory_->NewStreamTask(). However,
-// the other methods of this class (Run(), Cancel(), and the destructor) are
-// liable to be called from other threads by the executor.
-SpdySession::StreamTaskWrapper::StreamTaskWrapper(
- SpdySession* spdy_session,
- net::SpdyStreamId stream_id,
- net::SpdyStreamId associated_stream_id,
- int32 server_push_depth,
- net::SpdyPriority priority)
- : spdy_session_(spdy_session),
- stream_(spdy_session->spdy_version(), stream_id, associated_stream_id,
- server_push_depth, priority, spdy_session_->initial_window_size_,
- &spdy_session_->output_queue_, &spdy_session_->shared_window_,
- spdy_session_),
- subtask_(spdy_session_->task_factory_->NewStreamTask(&stream_)) {
- CHECK(subtask_);
-}
-
-SpdySession::StreamTaskWrapper::~StreamTaskWrapper() {
- // Remove this object from the SpdySession's stream map.
- spdy_session_->RemoveStreamTask(this);
-}
-
-void SpdySession::StreamTaskWrapper::Run() {
- subtask_->CallRun();
-}
-
-void SpdySession::StreamTaskWrapper::Cancel() {
- subtask_->CallCancel();
-}
-
-SpdySession::SpdyStreamMap::SpdyStreamMap()
- : num_active_push_streams_(0u) {}
-
-SpdySession::SpdyStreamMap::~SpdyStreamMap() {}
-
-bool SpdySession::SpdyStreamMap::IsEmpty() {
- DCHECK_LE(num_active_push_streams_, tasks_.size());
- return tasks_.empty();
-}
-
-size_t SpdySession::SpdyStreamMap::NumActiveClientStreams() {
- DCHECK_LE(num_active_push_streams_, tasks_.size());
- return tasks_.size() - num_active_push_streams_;
-}
-
-size_t SpdySession::SpdyStreamMap::NumActivePushStreams() {
- DCHECK_LE(num_active_push_streams_, tasks_.size());
- return num_active_push_streams_;
-}
-
-bool SpdySession::SpdyStreamMap::IsStreamActive(net::SpdyStreamId stream_id) {
- return tasks_.count(stream_id) > 0u;
-}
-
-void SpdySession::SpdyStreamMap::AddStreamTask(
- StreamTaskWrapper* task_wrapper) {
- DCHECK(task_wrapper);
- SpdyStream* stream = task_wrapper->stream();
- DCHECK(stream);
- net::SpdyStreamId stream_id = stream->stream_id();
- DCHECK_EQ(0u, tasks_.count(stream_id));
- tasks_[stream_id] = task_wrapper;
- if (stream->is_server_push()) {
- ++num_active_push_streams_;
- }
- DCHECK_LE(num_active_push_streams_, tasks_.size());
-}
-
-void SpdySession::SpdyStreamMap::RemoveStreamTask(
- StreamTaskWrapper* task_wrapper) {
- DCHECK(task_wrapper);
- SpdyStream* stream = task_wrapper->stream();
- DCHECK(stream);
- net::SpdyStreamId stream_id = stream->stream_id();
- DCHECK_EQ(1u, tasks_.count(stream_id));
- DCHECK_EQ(task_wrapper, tasks_[stream_id]);
- if (stream->is_server_push()) {
- DCHECK_GT(num_active_push_streams_, 0u);
- --num_active_push_streams_;
- }
- tasks_.erase(stream_id);
- DCHECK_LE(num_active_push_streams_, tasks_.size());
-}
-
-SpdyStream* SpdySession::SpdyStreamMap::GetStream(
- net::SpdyStreamId stream_id) {
- TaskMap::const_iterator iter = tasks_.find(stream_id);
- if (iter == tasks_.end()) {
- return NULL;
- }
- StreamTaskWrapper* task_wrapper = iter->second;
- DCHECK(task_wrapper);
- SpdyStream* stream = task_wrapper->stream();
- DCHECK(stream);
- DCHECK_EQ(stream_id, stream->stream_id());
- return stream;
-}
-
-void SpdySession::SpdyStreamMap::AdjustAllOutputWindowSizes(int32 delta) {
- for (TaskMap::const_iterator iter = tasks_.begin();
- iter != tasks_.end(); ++iter) {
- iter->second->stream()->AdjustOutputWindowSize(delta);
- }
-}
-
-void SpdySession::SpdyStreamMap::AbortAllSilently() {
- for (TaskMap::const_iterator iter = tasks_.begin();
- iter != tasks_.end(); ++iter) {
- iter->second->stream()->AbortSilently();
- }
-}
-
-} // namespace mod_spdy
+++ /dev/null
-// 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.
-
-#ifndef MOD_SPDY_COMMON_SPDY_SESSION_H_
-#define MOD_SPDY_COMMON_SPDY_SESSION_H_
-
-#include <map>
-
-#include "base/basictypes.h"
-#include "base/synchronization/lock.h"
-#include "mod_spdy/common/executor.h"
-#include "mod_spdy/common/protocol_util.h"
-#include "mod_spdy/common/shared_flow_control_window.h"
-#include "mod_spdy/common/spdy_frame_priority_queue.h"
-#include "mod_spdy/common/spdy_server_push_interface.h"
-#include "mod_spdy/common/spdy_stream.h"
-#include "net/instaweb/util/public/function.h"
-#include "net/spdy/buffered_spdy_framer.h"
-#include "net/spdy/spdy_protocol.h"
-
-namespace mod_spdy {
-
-class Executor;
-class SpdySessionIO;
-class SpdyServerConfig;
-class SpdyStreamTaskFactory;
-
-// Represents a SPDY session with a client. Given an Executor for processing
-// individual SPDY streams, and a SpdySessionIO for communicating with the
-// client (sending and receiving frames), this class takes care of implementing
-// the SPDY protocol and responding correctly to various situations.
-class SpdySession : public net::BufferedSpdyFramerVisitorInterface,
- public SpdyServerPushInterface {
- public:
- // The SpdySession does _not_ take ownership of any of these arguments.
- SpdySession(spdy::SpdyVersion spdy_version,
- const SpdyServerConfig* config,
- SpdySessionIO* session_io,
- SpdyStreamTaskFactory* task_factory,
- Executor* executor);
- virtual ~SpdySession();
-
- // What SPDY version is being used for this session?
- spdy::SpdyVersion spdy_version() const { return spdy_version_; }
-
- // What are the current shared window sizes for this session? These are
- // mostly useful for debugging. Requires that spdy_version() >=
- // SPDY_VERSION_3_1.
- int32 current_shared_input_window_size() const;
- int32 current_shared_output_window_size() const;
-
- // Process the session; don't return until the session is finished.
- void Run();
-
- // BufferedSpdyFramerVisitorInterface methods:
- virtual void OnError(net::SpdyFramer::SpdyError error_code);
- virtual void OnStreamError(
- net::SpdyStreamId stream_id, const std::string& description);
- virtual void OnSynStream(
- net::SpdyStreamId stream_id, net::SpdyStreamId associated_stream_id,
- net::SpdyPriority priority, uint8 credential_slot, bool fin,
- bool unidirectional, const net::SpdyHeaderBlock& headers);
- virtual void OnSynReply(
- net::SpdyStreamId stream_id, bool fin,
- const net::SpdyHeaderBlock& headers);
- virtual void OnHeaders(
- net::SpdyStreamId stream_id, bool fin,
- const net::SpdyHeaderBlock& headers);
- virtual void OnStreamFrameData(
- net::SpdyStreamId stream_id, const char* data, size_t length, bool fin);
- virtual void OnSettings(bool clear_persisted);
- virtual void OnSetting(net::SpdySettingsIds id, uint8 flags, uint32 value);
- virtual void OnPing(uint32 unique_id);
- virtual void OnRstStream(
- net::SpdyStreamId stream_id, net::SpdyRstStreamStatus status);
- virtual void OnGoAway(
- net::SpdyStreamId last_accepted_stream_id, net::SpdyGoAwayStatus status);
- virtual void OnWindowUpdate(
- net::SpdyStreamId stream_id, uint32 delta_window_size);
- virtual void OnPushPromise(
- net::SpdyStreamId stream_id, net::SpdyStreamId promised_stream_id);
-
- // SpdyServerPushInterface methods:
- // Initiate a SPDY server push, roughly by pretending that the client sent a
- // SYN_STREAM with the given headers. To repeat: the headers argument is
- // _not_ the headers that the server will send to the client, but rather the
- // headers to _pretend_ that the client sent to the server. Requires that
- // spdy_version() >= SPDY/3.
- // Note that unlike most other methods of this class, StartServerPush may be
- // called by stream threads, not just by the connection thread.
- virtual SpdyServerPushInterface::PushStatus StartServerPush(
- net::SpdyStreamId associated_stream_id,
- int32 server_push_depth,
- net::SpdyPriority priority,
- const net::SpdyHeaderBlock& request_headers);
-
- private:
- // A helper class for wrapping tasks returned by
- // SpdyStreamTaskFactory::NewStreamTask(). Running or cancelling this task
- // simply runs/cancels the wrapped task; however, this object also keeps a
- // SpdyStream object, and on deletion, this will remove itself from the
- // SpdySession's list of active streams.
- class StreamTaskWrapper : public net_instaweb::Function {
- public:
- // This constructor, called by the main connection thread, will call
- // task_factory_->NewStreamTask() to produce the wrapped task.
- StreamTaskWrapper(SpdySession* spdy_session,
- net::SpdyStreamId stream_id,
- net::SpdyStreamId associated_stream_id,
- int32 server_push_depth,
- net::SpdyPriority priority);
- virtual ~StreamTaskWrapper();
-
- SpdyStream* stream() { return &stream_; }
-
- protected:
- // net_instaweb::Function methods (our implementations of these simply
- // run/cancel the wrapped subtask):
- virtual void Run();
- virtual void Cancel();
-
- private:
- SpdySession* const spdy_session_;
- SpdyStream stream_;
- net_instaweb::Function* const subtask_;
-
- DISALLOW_COPY_AND_ASSIGN(StreamTaskWrapper);
- };
-
- // Helper class for keeping track of active stream tasks, and separately
- // tracking the number of active client/server-initiated streams. This class
- // is not thread-safe without external synchronization, so it is used below
- // along with a separate mutex.
- class SpdyStreamMap {
- public:
- SpdyStreamMap();
- ~SpdyStreamMap();
-
- // Determine whether there are no currently active streams.
- bool IsEmpty();
- // Get the number of currently active streams created by the client or
- // server, respectively.
- size_t NumActiveClientStreams();
- size_t NumActivePushStreams();
- // Determine if a particular stream ID is currently active.
- bool IsStreamActive(net::SpdyStreamId stream_id);
- // Get the specified stream object, or NULL if the stream is inactive.
- SpdyStream* GetStream(net::SpdyStreamId stream_id);
- // Add a new stream. Requires that the stream ID is currently inactive.
- void AddStreamTask(StreamTaskWrapper* task);
- // Remove a stream task. Requires that the stream is currently active.
- void RemoveStreamTask(StreamTaskWrapper* task);
- // Adjust the output window size of all active streams by the same delta.
- void AdjustAllOutputWindowSizes(int32 delta);
- // Abort all streams in the map. Note that this won't immediately empty
- // the map (the tasks still have to shut down).
- void AbortAllSilently();
-
- private:
- typedef std::map<net::SpdyStreamId, StreamTaskWrapper*> TaskMap;
- TaskMap tasks_;
- size_t num_active_push_streams_;
-
- DISALLOW_COPY_AND_ASSIGN(SpdyStreamMap);
- };
-
- // Validate and set the per-stream initial flow-control window size to the
- // new value. Must be using SPDY v3 or later to call this method.
- void SetInitialWindowSize(uint32 new_init_window_size);
-
- // Send a single SPDY frame to the client, compressing it first if necessary.
- // Stop the session if the connection turns out to be closed. This method
- // takes ownership of the passed frame and will delete it.
- void SendFrame(const net::SpdyFrameIR* frame);
- // Send the frame as-is (without taking ownership). Stop the session if the
- // connection turns out to be closed.
- void SendFrameRaw(const net::SpdySerializedFrame& frame);
-
- // Immediately send a GOAWAY frame to the client with the given status,
- // unless we've already sent one. This also prevents us from creating any
- // new streams, so calling this is the best way to shut the session down
- // gracefully; once all streams have finished normally and no new ones can be
- // created, the session will shut itself down.
- void SendGoAwayFrame(net::SpdyGoAwayStatus status);
- // Enqueue a RST_STREAM frame for the given stream ID. Note that this does
- // not abort the stream if it exists; for that, use AbortStream().
- void SendRstStreamFrame(net::SpdyStreamId stream_id,
- net::SpdyRstStreamStatus status);
- // Immediately send our SETTINGS frame, with values based on our
- // SpdyServerConfig object. This should be done exactly once, at session
- // start.
- void SendSettingsFrame();
-
- // Close down the whole session immediately. Abort all active streams, and
- // then block until all stream threads have shut down.
- void StopSession();
- // Abort the stream without sending anything to the client.
- void AbortStreamSilently(net::SpdyStreamId stream_id);
- // Send a RST_STREAM frame and then abort the stream.
- void AbortStream(net::SpdyStreamId stream_id,
- net::SpdyRstStreamStatus status);
-
- // Remove the given StreamTaskWrapper object from the stream map. This is
- // the only other method of this class, aside from StartServerPush, that
- // might be called from another thread. (Specifically, it is called by the
- // StreamTaskWrapper destructor, which is called by the executor).
- void RemoveStreamTask(StreamTaskWrapper* stream_data);
-
- // Grab the stream_map_lock_ and check if stream_map_ is empty.
- bool StreamMapIsEmpty();
-
- // These fields are accessed only by the main connection thread, so they need
- // not be protected by a lock:
- const spdy::SpdyVersion spdy_version_;
- const SpdyServerConfig* const config_;
- SpdySessionIO* const session_io_;
- SpdyStreamTaskFactory* const task_factory_;
- Executor* const executor_;
- net::BufferedSpdyFramer framer_;
- bool session_stopped_; // StopSession() has been called
- bool already_sent_goaway_; // GOAWAY frame has been sent
- net::SpdyStreamId last_client_stream_id_;
- int32 initial_window_size_; // per-stream initial flow-control window size
- uint32 max_concurrent_pushes_; // max number of active server pushes at once
-
- // The stream map must be protected by a lock, because each stream thread
- // will remove itself from the map (by calling RemoveStreamTask) when the
- // stream closes. You MUST hold the lock to use the stream_map_ OR to use
- // any of the StreamTaskWrapper or SpdyStream objects contained therein
- // (e.g. to post a frame to the stream), otherwise the stream object may be
- // deleted by another thread while you're using it. You should NOT be
- // holding the lock when you e.g. send a frame to the client, as that may
- // block for a long time.
- base::Lock stream_map_lock_;
- SpdyStreamMap stream_map_;
- // These fields are also protected by the stream_map_lock_; they are used for
- // controlling server pushes, which can be initiated by stream threads as
- // well as by the connection thread. We could use a separate lock for these,
- // but right now we probably don't need that much locking granularity.
- net::SpdyStreamId last_server_push_stream_id_;
- bool received_goaway_; // we've received a GOAWAY frame from the client
-
- // These objects are also shared between all stream threads, but these
- // classes are each thread-safe, and don't need additional synchronization.
- SpdyFramePriorityQueue output_queue_;
- SharedFlowControlWindow shared_window_;
-
- DISALLOW_COPY_AND_ASSIGN(SpdySession);
-};
-
-} // namespace mod_spdy
-
-#endif // MOD_SPDY_COMMON_SPDY_SESSION_H_
+++ /dev/null
-// 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.
-
-#include "mod_spdy/common/spdy_session_io.h"
-
-namespace mod_spdy {
-
-SpdySessionIO::SpdySessionIO() {}
-
-SpdySessionIO::~SpdySessionIO() {}
-
-} // namespace mod_spdy
+++ /dev/null
-// 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.
-
-#ifndef MOD_SPDY_COMMON_SPDY_SESSION_IO_H_
-#define MOD_SPDY_COMMON_SPDY_SESSION_IO_H_
-
-#include "base/basictypes.h"
-#include "net/spdy/spdy_protocol.h"
-
-namespace net {
-class BufferedSpdyFramer;
-} // namespace net
-
-namespace mod_spdy {
-
-class SpdyStream;
-
-// SpdySessionIO is a helper interface for the SpdySession class. The
-// SpdySessionIO takes care of implementation-specific details about how to
-// send and receive data, allowing the SpdySession to focus on the SPDY
-// protocol itself. For example, a SpdySessionIO for Apache would hold onto a
-// conn_rec object and invoke the input and output filter chains for
-// ProcessAvailableInput and SendFrameRaw, respectively. The SpdySessionIO
-// itself does not need to be thread-safe -- it is only ever used by the main
-// connection thread.
-class SpdySessionIO {
- public:
- // Status to describe whether reading succeeded.
- enum ReadStatus {
- READ_SUCCESS, // we successfully pushed data into the SpdyFramer
- READ_NO_DATA, // no data is currently available
- READ_CONNECTION_CLOSED, // the connection has been closed
- READ_ERROR // an unrecoverable error (e.g. client sent malformed data)
- };
-
- // Status to describe whether writing succeeded.
- enum WriteStatus {
- WRITE_SUCCESS, // we successfully wrote the frame out to the network
- WRITE_CONNECTION_CLOSED, // the connection has been closed
- };
-
- SpdySessionIO();
- virtual ~SpdySessionIO();
-
- // Return true if the connection has been externally aborted and should
- // stop, false otherwise.
- virtual bool IsConnectionAborted() = 0;
-
- // Pull any available input data from the connection and feed it into the
- // ProcessInput() method of the given SpdyFramer. If no input data is
- // currently available and the block argument is true, this should block
- // until more data arrives; otherwise, this should not block.
- virtual ReadStatus ProcessAvailableInput(
- bool block, net::BufferedSpdyFramer* framer) = 0;
-
- // Send a single SPDY frame to the client as-is; block until it has been
- // sent down the wire. Return true on success.
- //
- // TODO(mdsteele): We do need to be able to flush a single frame down the
- // wire, but we probably don't need/want to flush every single frame
- // individually in places where we send multiple frames at once. We'll
- // probably want to adjust this API a bit.
- virtual WriteStatus SendFrameRaw(const net::SpdySerializedFrame& frame) = 0;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(SpdySessionIO);
-};
-
-} // namespace mod_spdy
-
-#endif // MOD_SPDY_COMMON_SPDY_SESSION_IO_H_
+++ /dev/null
-// Copyright 2010 Google Inc. All Rights Reserved.
-//
-// 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.
-
-#include "mod_spdy/common/spdy_session.h"
-
-#include <list>
-#include <string>
-
-#include "base/basictypes.h"
-#include "base/logging.h"
-#include "base/memory/scoped_ptr.h"
-#include "mod_spdy/common/protocol_util.h"
-#include "mod_spdy/common/spdy_server_config.h"
-#include "mod_spdy/common/spdy_session_io.h"
-#include "mod_spdy/common/spdy_stream_task_factory.h"
-#include "mod_spdy/common/testing/spdy_frame_matchers.h"
-#include "mod_spdy/common/thread_pool.h"
-#include "net/instaweb/util/public/function.h"
-#include "net/spdy/buffered_spdy_framer.h"
-#include "net/spdy/spdy_framer.h"
-#include "net/spdy/spdy_protocol.h"
-#include "testing/gmock/include/gmock/gmock.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-using mod_spdy::testing::IsDataFrame;
-using mod_spdy::testing::IsGoAway;
-using mod_spdy::testing::IsHeaders;
-using mod_spdy::testing::IsPing;
-using mod_spdy::testing::IsRstStream;
-using mod_spdy::testing::IsSettings;
-using mod_spdy::testing::IsSynReply;
-using mod_spdy::testing::IsSynStream;
-using testing::_;
-using testing::AllOf;
-using testing::AtLeast;
-using testing::DoAll;
-using testing::Eq;
-using testing::Invoke;
-using testing::InvokeWithoutArgs;
-using testing::NotNull;
-using testing::Property;
-using testing::Return;
-using testing::StrictMock;
-using testing::WithArg;
-
-namespace {
-
-void AddRequestHeaders(mod_spdy::spdy::SpdyVersion version,
- net::SpdyNameValueBlock *headers) {
- const bool spdy2 = version < mod_spdy::spdy::SPDY_VERSION_3;
- (*headers)[spdy2 ? mod_spdy::http::kHost :
- mod_spdy::spdy::kSpdy3Host] = "www.example.com";
- (*headers)[spdy2 ? mod_spdy::spdy::kSpdy2Method :
- mod_spdy::spdy::kSpdy3Method] = "GET";
- (*headers)[spdy2 ? mod_spdy::spdy::kSpdy2Scheme :
- mod_spdy::spdy::kSpdy3Scheme] = "https";
- (*headers)[spdy2 ? mod_spdy::spdy::kSpdy2Url :
- mod_spdy::spdy::kSpdy3Path] = "/foo/index.html";
- (*headers)[spdy2 ? mod_spdy::spdy::kSpdy2Version :
- mod_spdy::spdy::kSpdy3Version] = "HTTP/1.1";
-}
-
-void AddResponseHeaders(mod_spdy::spdy::SpdyVersion version,
- net::SpdyNameValueBlock *headers) {
- const bool spdy2 = version < mod_spdy::spdy::SPDY_VERSION_3;
- (*headers)[spdy2 ? mod_spdy::spdy::kSpdy2Status :
- mod_spdy::spdy::kSpdy3Status] = "200";
- (*headers)[spdy2 ? mod_spdy::spdy::kSpdy2Version :
- mod_spdy::spdy::kSpdy3Version] = "HTTP/1.1";
- (*headers)[mod_spdy::http::kContentType] = "text/html";
-}
-
-void AddInitialServerPushHeaders(const std::string& path,
- net::SpdyNameValueBlock *headers) {
- (*headers)[mod_spdy::spdy::kSpdy3Host] = "www.example.com";
- (*headers)[mod_spdy::spdy::kSpdy3Path] = path;
- (*headers)[mod_spdy::spdy::kSpdy3Scheme] = "https";
-}
-
-class MockSpdySessionIO : public mod_spdy::SpdySessionIO {
- public:
- MOCK_METHOD0(IsConnectionAborted, bool());
- MOCK_METHOD2(ProcessAvailableInput,
- ReadStatus(bool, net::BufferedSpdyFramer*));
- MOCK_METHOD1(SendFrameRaw, WriteStatus(const net::SpdySerializedFrame&));
-};
-
-class MockSpdyStreamTaskFactory : public mod_spdy::SpdyStreamTaskFactory {
- public:
- MOCK_METHOD1(NewStreamTask, net_instaweb::Function*(mod_spdy::SpdyStream*));
-};
-
-class MockStreamTask : public net_instaweb::Function {
- public:
- MockStreamTask() : stream(NULL) {}
- MOCK_METHOD0(Run, void());
- MOCK_METHOD0(Cancel, void());
- mod_spdy::SpdyStream* stream;
- private:
- DISALLOW_COPY_AND_ASSIGN(MockStreamTask);
-};
-
-// gMock action to be used with NewStreamTask.
-ACTION_P(ReturnMockTask, task) {
- task->stream = arg0;
- return task;
-}
-
-// gMock action to be used with MockStreamTask::Run.
-ACTION_P4(StartServerPush, task, priority, path, expected_status) {
- net::SpdyHeaderBlock push_headers;
- AddInitialServerPushHeaders(path, &push_headers);
- EXPECT_EQ(expected_status,
- task->stream->StartServerPush(priority, push_headers));
-}
-
-// gMock action to be used with MockStreamTask::Run.
-ACTION_P(SendResponseHeaders, task) {
- net::SpdyHeaderBlock headers;
- AddResponseHeaders(task->stream->spdy_version(), &headers);
- if (task->stream->is_server_push()) {
- task->stream->SendOutputHeaders(headers, false);
- } else {
- task->stream->SendOutputSynReply(headers, false);
- }
-}
-
-// gMock action to be used with MockStreamTask::Run.
-ACTION_P3(SendDataFrame, task, data, fin) {
- task->stream->SendOutputDataFrame(data, fin);
-}
-
-// gMock action to be used with MockStreamTask::Run.
-ACTION_P(ConsumeInputUntilAborted, task) {
- while (!task->stream->is_aborted()) {
- net::SpdyFrameIR* raw_frame = NULL;
- if (task->stream->GetInputFrame(true, &raw_frame)) {
- delete raw_frame;
- }
- }
-}
-
-// An executor that runs all tasks in the same thread, either immediately when
-// they are added or when it is told to run them.
-class InlineExecutor : public mod_spdy::Executor {
- public:
- InlineExecutor() : run_on_add_(false), stopped_(false) {}
- virtual ~InlineExecutor() { Stop(); }
-
- virtual void AddTask(net_instaweb::Function* task,
- net::SpdyPriority priority) {
- if (stopped_) {
- task->CallCancel();
- } else if (run_on_add_) {
- task->CallRun();
- } else {
- tasks_.push_back(task);
- }
- }
- virtual void Stop() {
- stopped_ = true;
- while (!tasks_.empty()) {
- tasks_.front()->CallCancel();
- tasks_.pop_front();
- }
- }
- void RunOne() {
- if (!tasks_.empty()) {
- tasks_.front()->CallRun();
- tasks_.pop_front();
- }
- }
- void RunAll() {
- while (!tasks_.empty()) {
- RunOne();
- }
- }
- void set_run_on_add(bool run) { run_on_add_ = run; }
- bool stopped() const { return stopped_; }
-
- private:
- std::list<net_instaweb::Function*> tasks_;
- bool run_on_add_;
- bool stopped_;
-
- DISALLOW_COPY_AND_ASSIGN(InlineExecutor);
-};
-
-// A BufferedSpdyFramer visitor that constructs IR objects for the frames it
-// parses.
-class ClientVisitor : public net::BufferedSpdyFramerVisitorInterface {
- public:
- ClientVisitor() : last_data_(NULL), last_settings_(NULL) {}
- virtual ~ClientVisitor() {}
-
- virtual void OnError(net::SpdyFramer::SpdyError error_code) {}
- virtual void OnStreamError(net::SpdyStreamId stream_id,
- const std::string& description) {}
- virtual void OnSynStream(net::SpdyStreamId id, net::SpdyStreamId assoc_id,
- net::SpdyPriority priority, uint8 slot,
- bool fin, bool unidirectional,
- const net::SpdyHeaderBlock& headers) {
- scoped_ptr<net::SpdySynStreamIR> frame(new net::SpdySynStreamIR(id));
- frame->set_associated_to_stream_id(assoc_id);
- frame->set_priority(priority);
- frame->set_slot(slot);
- frame->set_fin(fin);
- frame->set_unidirectional(unidirectional);
- frame->GetMutableNameValueBlock()->insert(
- headers.begin(), headers.end());
- last_frame_.reset(frame.release());
- }
- virtual void OnSynReply(net::SpdyStreamId id, bool fin,
- const net::SpdyHeaderBlock& headers) {
- scoped_ptr<net::SpdySynReplyIR> frame(new net::SpdySynReplyIR(id));
- frame->set_fin(fin);
- frame->GetMutableNameValueBlock()->insert(
- headers.begin(), headers.end());
- last_frame_.reset(frame.release());
- }
- virtual void OnHeaders(net::SpdyStreamId id, bool fin,
- const net::SpdyHeaderBlock& headers) {
- scoped_ptr<net::SpdyHeadersIR> frame(new net::SpdyHeadersIR(id));
- frame->set_fin(fin);
- frame->GetMutableNameValueBlock()->insert(
- headers.begin(), headers.end());
- last_frame_.reset(frame.release());
- }
- virtual void OnStreamFrameData(net::SpdyStreamId id, const char* data,
- size_t len, bool fin) {
- if (len == 0 && last_data_ != NULL && last_data_ == last_frame_.get()) {
- last_data_->set_fin(fin);
- } else {
- scoped_ptr<net::SpdyDataIR> frame(new net::SpdyDataIR(
- id, base::StringPiece(data, len)));
- frame->set_fin(fin);
- last_data_ = frame.get();
- last_frame_.reset(frame.release());
- }
- }
- virtual void OnSettings(bool clear_persisted) {
- scoped_ptr<net::SpdySettingsIR> frame(new net::SpdySettingsIR);
- frame->set_clear_settings(clear_persisted);
- last_settings_ = frame.get();
- last_frame_.reset(frame.release());
- }
- virtual void OnSetting(net::SpdySettingsIds id, uint8 flags, uint32 value) {
- CHECK(last_settings_ != NULL && last_settings_ == last_frame_.get());
- last_settings_->AddSetting(
- id, (flags & net::SETTINGS_FLAG_PLEASE_PERSIST),
- (flags & net::SETTINGS_FLAG_PERSISTED), value);
- }
- virtual void OnPing(uint32 id) {
- last_frame_.reset(new net::SpdyPingIR(id));
- }
- virtual void OnRstStream(net::SpdyStreamId id,
- net::SpdyRstStreamStatus status) {
- last_frame_.reset(new net::SpdyRstStreamIR(id, status));
- }
- virtual void OnGoAway(net::SpdyStreamId id, net::SpdyGoAwayStatus status) {
- last_frame_.reset(new net::SpdyGoAwayIR(id, status));
- }
- virtual void OnWindowUpdate(net::SpdyStreamId id, uint32 delta) {
- last_frame_.reset(new net::SpdyWindowUpdateIR(id, delta));
- }
- virtual void OnPushPromise(net::SpdyStreamId id, net::SpdyStreamId promise) {
- last_frame_.reset(new net::SpdyPushPromiseIR(id, promise));
- }
-
- net::SpdyFrameIR* ReleaseLastFrame() {
- return last_frame_.release();
- }
-
- private:
- net::SpdyDataIR* last_data_;
- net::SpdySettingsIR* last_settings_;
- scoped_ptr<net::SpdyFrameIR> last_frame_;
-
- DISALLOW_COPY_AND_ASSIGN(ClientVisitor);
-};
-
-ACTION_P2(ClientDecodeFrame, test, matcher) {
- scoped_ptr<net::SpdyFrameIR> frame(test->DecodeFrameOnClient(arg0));
- ASSERT_TRUE(frame != NULL);
- EXPECT_THAT(*frame, matcher);
-}
-
-ACTION_P3(SendBackWindowUpdate, test, stream_id, delta) {
- test->ReceiveWindowUpdateFrameFromClient(stream_id, delta);
-}
-
-ACTION_P3(SendBackSettings, test, key, value) {
- test->ReceiveSettingsFrameFromClient(key, value);
-}
-
-// Base class for SpdySession tests.
-class SpdySessionTestBase :
- public testing::TestWithParam<mod_spdy::spdy::SpdyVersion> {
- public:
- SpdySessionTestBase()
- : spdy_version_(GetParam()),
- client_framer_(mod_spdy::SpdyVersionToFramerVersion(spdy_version_),
- true) {
- client_framer_.set_visitor(&client_visitor_);
- ON_CALL(session_io_, IsConnectionAborted()).WillByDefault(Return(false));
- ON_CALL(session_io_, ProcessAvailableInput(_, NotNull()))
- .WillByDefault(Invoke(this, &SpdySessionTestBase::ReadNextInputChunk));
- ON_CALL(session_io_, SendFrameRaw(_))
- .WillByDefault(Return(mod_spdy::SpdySessionIO::WRITE_SUCCESS));
- }
-
- // Use as gMock action for ProcessAvailableInput:
- // Invoke(this, &SpdySessionTest::ReadNextInputChunk)
- mod_spdy::SpdySessionIO::ReadStatus ReadNextInputChunk(
- bool block, net::BufferedSpdyFramer* framer) {
- if (input_queue_.empty()) {
- return mod_spdy::SpdySessionIO::READ_NO_DATA;
- }
- const std::string chunk = input_queue_.front();
- input_queue_.pop_front();
- framer->ProcessInput(chunk.data(), chunk.size());
- return (framer->HasError() ? mod_spdy::SpdySessionIO::READ_ERROR :
- mod_spdy::SpdySessionIO::READ_SUCCESS);
- }
-
- // This is called by the ClientDecodeFrame gMock action defined above.
- net::SpdyFrameIR* DecodeFrameOnClient(
- const net::SpdySerializedFrame& frame) {
- client_framer_.ProcessInput(frame.data(), frame.size());
- return client_visitor_.ReleaseLastFrame();
- }
-
- // Push a frame into the input queue.
- void ReceiveFrameFromClient(const net::SpdySerializedFrame& frame) {
- input_queue_.push_back(std::string(frame.data(), frame.size()));
- }
-
- // Push a PING frame into the input queue.
- void ReceivePingFromClient(uint32 id) {
- scoped_ptr<net::SpdySerializedFrame> frame(
- client_framer_.CreatePingFrame(id));
- ReceiveFrameFromClient(*frame);
- }
-
- // Push a valid SYN_STREAM frame into the input queue.
- void ReceiveSynStreamFromClient(net::SpdyStreamId stream_id,
- net::SpdyPriority priority,
- net::SpdyControlFlags flags) {
- net::SpdyHeaderBlock headers;
- AddRequestHeaders(spdy_version_, &headers);
- scoped_ptr<net::SpdySerializedFrame> frame(client_framer_.CreateSynStream(
- stream_id, 0, priority, 0, flags,
- true, // true = use compression
- &headers));
- ReceiveFrameFromClient(*frame);
- }
-
- // Push a valid DATA frame into the input queue.
- void ReceiveDataFromClient(net::SpdyStreamId stream_id,
- base::StringPiece data,
- net::SpdyDataFlags flags) {
- scoped_ptr<net::SpdySerializedFrame> frame(client_framer_.CreateDataFrame(
- stream_id, data.data(), data.size(), flags));
- ReceiveFrameFromClient(*frame);
- }
-
- // Push a SETTINGS frame into the input queue.
- void ReceiveSettingsFrameFromClient(
- net::SpdySettingsIds setting, uint32 value) {
- net::SettingsMap settings;
- settings[setting] = std::make_pair(net::SETTINGS_FLAG_NONE, value);
- scoped_ptr<net::SpdySerializedFrame> frame(
- client_framer_.CreateSettings(settings));
- ReceiveFrameFromClient(*frame);
- }
-
- // Push a WINDOW_UPDATE frame into the input queue.
- void ReceiveWindowUpdateFrameFromClient(
- net::SpdyStreamId stream_id, uint32 delta) {
- scoped_ptr<net::SpdySerializedFrame> frame(
- client_framer_.CreateWindowUpdate(stream_id, delta));
- ReceiveFrameFromClient(*frame);
- }
-
- protected:
- void ExpectSendFrame(::testing::Matcher<const net::SpdyFrameIR&> matcher) {
- EXPECT_CALL(session_io_, SendFrameRaw(_))
- .WillOnce(DoAll(ClientDecodeFrame(this, matcher),
- Return(mod_spdy::SpdySessionIO::WRITE_SUCCESS)));
- }
-
- void ExpectBeginServerPush(
- net::SpdyStreamId stream_id, net::SpdyStreamId assoc_stream_id,
- net::SpdyPriority priority, const std::string& path) {
- net::SpdyNameValueBlock headers;
- AddInitialServerPushHeaders(path, &headers);
- ExpectSendFrame(IsSynStream(stream_id, assoc_stream_id, priority, false,
- true, headers));
- }
-
- void ExpectSendSynReply(net::SpdyStreamId stream_id, bool fin) {
- net::SpdyNameValueBlock headers;
- AddResponseHeaders(spdy_version_, &headers);
- ExpectSendFrame(IsSynReply(stream_id, fin, headers));
- }
-
- void ExpectSendHeaders(net::SpdyStreamId stream_id, bool fin) {
- net::SpdyNameValueBlock headers;
- AddResponseHeaders(spdy_version_, &headers);
- ExpectSendFrame(IsHeaders(stream_id, fin, headers));
- }
-
- void ExpectSendGoAway(net::SpdyStreamId last_stream_id,
- net::SpdyGoAwayStatus status) {
- // SPDY/2 doesn't have status codes on GOAWAY frames, so for SPDY/2 the
- // client framer decodes it as GOAWAY_OK regardless of what we sent.
- if (spdy_version_ == mod_spdy::spdy::SPDY_VERSION_2) {
- ExpectSendFrame(IsGoAway(last_stream_id, net::GOAWAY_OK));
- } else {
- ExpectSendFrame(IsGoAway(last_stream_id, status));
- }
- }
-
- const mod_spdy::spdy::SpdyVersion spdy_version_;
- ClientVisitor client_visitor_;
- net::BufferedSpdyFramer client_framer_;
- mod_spdy::SpdyServerConfig config_;
- StrictMock<MockSpdySessionIO> session_io_;
- StrictMock<MockSpdyStreamTaskFactory> task_factory_;
- std::list<std::string> input_queue_;
-};
-
-// Class for most SpdySession tests; this uses an InlineExecutor, so that test
-// behavior is very predictable.
-class SpdySessionTest : public SpdySessionTestBase {
- public:
- SpdySessionTest()
- : session_(spdy_version_, &config_, &session_io_, &task_factory_,
- &executor_) {}
-
- protected:
- InlineExecutor executor_;
- mod_spdy::SpdySession session_;
-};
-
-// Test that if the connection is already closed, we stop immediately.
-TEST_P(SpdySessionTest, ConnectionAlreadyClosed) {
- testing::InSequence seq;
- EXPECT_CALL(session_io_, SendFrameRaw(_))
- .WillOnce(Return(mod_spdy::SpdySessionIO::WRITE_CONNECTION_CLOSED));
-
- session_.Run();
- EXPECT_TRUE(executor_.stopped());
-}
-
-// Test that when the connection is aborted, we stop.
-TEST_P(SpdySessionTest, ImmediateConnectionAbort) {
- testing::InSequence seq;
- ExpectSendFrame(IsSettings(net::SETTINGS_MAX_CONCURRENT_STREAMS, 100));
- EXPECT_CALL(session_io_, IsConnectionAborted()).WillOnce(Return(true));
-
- session_.Run();
- EXPECT_TRUE(executor_.stopped());
-}
-
-// Test responding to a PING frame from the client (followed by the connection
-// closing, so that we can exit the Run loop).
-TEST_P(SpdySessionTest, SinglePing) {
- ReceivePingFromClient(47);
-
- testing::InSequence seq;
- ExpectSendFrame(IsSettings(net::SETTINGS_MAX_CONCURRENT_STREAMS, 100));
- EXPECT_CALL(session_io_, IsConnectionAborted());
- EXPECT_CALL(session_io_, ProcessAvailableInput(Eq(true), NotNull()));
- ExpectSendFrame(IsPing(47));
- EXPECT_CALL(session_io_, IsConnectionAborted());
- EXPECT_CALL(session_io_, ProcessAvailableInput(Eq(true), NotNull()))
- .WillOnce(Return(mod_spdy::SpdySessionIO::READ_CONNECTION_CLOSED));
- ExpectSendGoAway(0, net::GOAWAY_OK);
-
- session_.Run();
- EXPECT_TRUE(executor_.stopped());
-}
-
-// Test handling a single stream request.
-TEST_P(SpdySessionTest, SingleStream) {
- MockStreamTask* task = new MockStreamTask;
- executor_.set_run_on_add(false);
- const net::SpdyStreamId stream_id = 1;
- const net::SpdyPriority priority = 2;
- ReceiveSynStreamFromClient(stream_id, priority, net::CONTROL_FLAG_FIN);
-
- testing::InSequence seq;
- ExpectSendFrame(IsSettings(net::SETTINGS_MAX_CONCURRENT_STREAMS, 100));
- EXPECT_CALL(session_io_, IsConnectionAborted());
- EXPECT_CALL(session_io_, ProcessAvailableInput(Eq(true), NotNull()));
- EXPECT_CALL(task_factory_, NewStreamTask(
- AllOf(Property(&mod_spdy::SpdyStream::stream_id, Eq(stream_id)),
- Property(&mod_spdy::SpdyStream::associated_stream_id, Eq(0u)),
- Property(&mod_spdy::SpdyStream::priority, Eq(priority)))))
- .WillOnce(ReturnMockTask(task));
- EXPECT_CALL(session_io_, IsConnectionAborted())
- .WillOnce(DoAll(InvokeWithoutArgs(&executor_, &InlineExecutor::RunAll),
- Return(false)));
- EXPECT_CALL(*task, Run()).WillOnce(DoAll(
- SendResponseHeaders(task), SendDataFrame(task, "foobar", false),
- SendDataFrame(task, "quux", true)));
- EXPECT_CALL(session_io_, ProcessAvailableInput(Eq(false), NotNull()));
- ExpectSendSynReply(stream_id, false);
- ExpectSendFrame(IsDataFrame(stream_id, false, "foobar"));
- ExpectSendFrame(IsDataFrame(stream_id, true, "quux"));
- EXPECT_CALL(session_io_, IsConnectionAborted());
- EXPECT_CALL(session_io_, ProcessAvailableInput(Eq(true), NotNull()))
- .WillOnce(Return(mod_spdy::SpdySessionIO::READ_CONNECTION_CLOSED));
- ExpectSendGoAway(1, net::GOAWAY_OK);
-
- session_.Run();
- EXPECT_TRUE(executor_.stopped());
-}
-
-// Test that if SendFrameRaw fails, we immediately stop trying to send data and
-// shut down the session.
-TEST_P(SpdySessionTest, ShutDownSessionIfSendFrameRawFails) {
- MockStreamTask* task = new MockStreamTask;
- executor_.set_run_on_add(false);
- const net::SpdyStreamId stream_id = 1;
- const net::SpdyPriority priority = 2;
- ReceiveSynStreamFromClient(stream_id, priority, net::CONTROL_FLAG_FIN);
-
- testing::InSequence seq;
- // We start out the same way as in the SingleStream test above.
- ExpectSendFrame(IsSettings(net::SETTINGS_MAX_CONCURRENT_STREAMS, 100));
- EXPECT_CALL(session_io_, IsConnectionAborted());
- EXPECT_CALL(session_io_, ProcessAvailableInput(_, _));
- EXPECT_CALL(task_factory_, NewStreamTask(_))
- .WillOnce(ReturnMockTask(task));
- EXPECT_CALL(session_io_, IsConnectionAborted())
- .WillOnce(DoAll(InvokeWithoutArgs(&executor_, &InlineExecutor::RunAll),
- Return(false)));
- EXPECT_CALL(*task, Run()).WillOnce(DoAll(
- SendResponseHeaders(task), SendDataFrame(task, "foobar", false),
- SendDataFrame(task, "quux", true)));
- EXPECT_CALL(session_io_, ProcessAvailableInput(_, _));
- ExpectSendSynReply(stream_id, false);
- // At this point, the connection is closed by the client.
- EXPECT_CALL(session_io_, SendFrameRaw(_))
- .WillOnce(Return(mod_spdy::SpdySessionIO::WRITE_CONNECTION_CLOSED));
- // Even though we have another frame to send at this point (already in the
- // output queue), we immediately stop sending data and exit the session.
-
- session_.Run();
- EXPECT_TRUE(executor_.stopped());
-}
-
-// Test that when the client sends us garbage data, we send a GOAWAY frame and
-// then quit.
-TEST_P(SpdySessionTest, SendGoawayInResponseToGarbage) {
- input_queue_.push_back("\x88\x5f\x92\x02\xf8\x92\x12\xd1"
- "\x82\xdc\x1a\x40\xbb\xb2\x9d\x13");
-
- testing::InSequence seq;
- ExpectSendFrame(IsSettings(net::SETTINGS_MAX_CONCURRENT_STREAMS, 100));
- EXPECT_CALL(session_io_, IsConnectionAborted());
- EXPECT_CALL(session_io_, ProcessAvailableInput(Eq(true), NotNull()));
- ExpectSendGoAway(0, net::GOAWAY_PROTOCOL_ERROR);
-
- session_.Run();
- EXPECT_TRUE(executor_.stopped());
-}
-
-// Test that when the client sends us a SYN_STREAM with a corrupted header
-// block, we send a GOAWAY frame and then quit.
-TEST_P(SpdySessionTest, SendGoawayForBadSynStreamCompression) {
- net::SpdyHeaderBlock headers;
- headers["foobar"] = "Foo is to bar as bar is to baz.";
- net::SpdyFramer framer(mod_spdy::SpdyVersionToFramerVersion(spdy_version_));
- framer.set_enable_compression(false);
- scoped_ptr<net::SpdySerializedFrame> frame(framer.CreateSynStream(
- 1, 0, framer.GetHighestPriority(), 0, net::CONTROL_FLAG_FIN,
- false, // false = no compression
- &headers));
- ReceiveFrameFromClient(*frame);
-
- testing::InSequence seq;
- ExpectSendFrame(IsSettings(net::SETTINGS_MAX_CONCURRENT_STREAMS, 100));
- EXPECT_CALL(session_io_, IsConnectionAborted());
- EXPECT_CALL(session_io_, ProcessAvailableInput(Eq(true), NotNull()));
- ExpectSendGoAway(0, net::GOAWAY_PROTOCOL_ERROR);
-
- session_.Run();
- EXPECT_TRUE(executor_.stopped());
-}
-
-// TODO(mdsteele): At the moment, SpdyFramer DCHECKs that the stream ID is
-// nonzero when decoding, so this test would crash in debug builds. Once this
-// has been corrected in the Chromium code, we can remove this #ifdef.
-#ifdef NDEBUG
-// Test that when the client sends us a SYN_STREAM with a stream ID of 0, we
-// send a GOAWAY frame and then quit.
-TEST_P(SpdySessionTest, SendGoawayForSynStreamIdZero) {
- net::SpdyHeaderBlock headers;
- AddRequestHeaders(spdy_version_, &headers);
- scoped_ptr<net::SpdySerializedFrame> frame(client_framer_.CreateSynStream(
- 0, 0, client_framer_.GetHighestPriority(), 0, net::CONTROL_FLAG_FIN,
- true, // true = use compression
- &headers));
- ReceiveFrameFromClient(*frame);
-
- testing::InSequence seq;
- ExpectSendFrame(IsSettings(net::SETTINGS_MAX_CONCURRENT_STREAMS, 100));
- EXPECT_CALL(session_io_, IsConnectionAborted());
- EXPECT_CALL(session_io_, ProcessAvailableInput(Eq(true), NotNull()));
- ExpectSendGoAway(0, net::GOAWAY_PROTOCOL_ERROR);
-
- session_.Run();
- EXPECT_TRUE(executor_.stopped());
-}
-#endif
-
-// Test that when the client sends us two SYN_STREAMs with the same ID, we send
-// a GOAWAY frame (but still finish out the good stream before quitting).
-TEST_P(SpdySessionTest, SendGoawayForDuplicateStreamId) {
- MockStreamTask* task = new MockStreamTask;
- executor_.set_run_on_add(false);
- const net::SpdyStreamId stream_id = 1;
- const net::SpdyPriority priority = 2;
- ReceiveSynStreamFromClient(stream_id, priority, net::CONTROL_FLAG_FIN);
- ReceiveSynStreamFromClient(stream_id, priority, net::CONTROL_FLAG_FIN);
-
- testing::InSequence seq;
- ExpectSendFrame(IsSettings(net::SETTINGS_MAX_CONCURRENT_STREAMS, 100));
- EXPECT_CALL(session_io_, IsConnectionAborted());
- // Get the first SYN_STREAM; it looks good, so create a new task (but because
- // we set executor_.set_run_on_add(false) above, it doesn't execute yet).
- EXPECT_CALL(session_io_, ProcessAvailableInput(Eq(true), NotNull()));
- EXPECT_CALL(task_factory_, NewStreamTask(
- AllOf(Property(&mod_spdy::SpdyStream::stream_id, Eq(stream_id)),
- Property(&mod_spdy::SpdyStream::associated_stream_id, Eq(0u)),
- Property(&mod_spdy::SpdyStream::priority, Eq(priority)))))
- .WillOnce(ReturnMockTask(task));
- EXPECT_CALL(session_io_, IsConnectionAborted());
- // There's an active stream out, so ProcessAvailableInput should have false
- // for the first argument (false = nonblocking read). Here we get the second
- // SYN_STREAM with the same stream ID, so we should send GOAWAY.
- EXPECT_CALL(session_io_, ProcessAvailableInput(Eq(false), NotNull()));
- ExpectSendGoAway(1, net::GOAWAY_PROTOCOL_ERROR);
- // At this point, tell the executor to run the task.
- EXPECT_CALL(session_io_, IsConnectionAborted())
- .WillOnce(DoAll(InvokeWithoutArgs(&executor_, &InlineExecutor::RunAll),
- Return(false)));
- EXPECT_CALL(*task, Run()).WillOnce(DoAll(
- SendResponseHeaders(task), SendDataFrame(task, "foobar", false),
- SendDataFrame(task, "quux", true)));
- // The stream is no longer active, but there are pending frames to send, so
- // we shouldn't block on input.
- EXPECT_CALL(session_io_, ProcessAvailableInput(Eq(false), NotNull()));
- // Now we should send the output.
- ExpectSendSynReply(stream_id, false);
- ExpectSendFrame(IsDataFrame(stream_id, false, "foobar"));
- ExpectSendFrame(IsDataFrame(stream_id, true, "quux"));
- // Finally, there is no more output to send, and no chance of creating new
- // streams (since we GOAWAY'd), so we quit.
- EXPECT_CALL(session_io_, IsConnectionAborted());
-
- session_.Run();
- EXPECT_TRUE(executor_.stopped());
-}
-
-// Run each test over both SPDY v2 and SPDY v3.
-INSTANTIATE_TEST_CASE_P(Spdy2And3, SpdySessionTest, testing::Values(
- mod_spdy::spdy::SPDY_VERSION_2, mod_spdy::spdy::SPDY_VERSION_3,
- mod_spdy::spdy::SPDY_VERSION_3_1));
-
-// Create a type alias so that we can instantiate some of our
-// SpdySessionTest-based tests using a different set of parameters.
-typedef SpdySessionTest SpdySessionNoFlowControlTest;
-
-// Test that we send GOAWAY if the client tries to send
-// SETTINGS_INITIAL_WINDOW_SIZE over SPDY v2.
-TEST_P(SpdySessionNoFlowControlTest, SendGoawayForInitialWindowSize) {
- net::SettingsMap settings;
- settings[net::SETTINGS_INITIAL_WINDOW_SIZE] =
- std::make_pair(net::SETTINGS_FLAG_NONE, 4000);
- scoped_ptr<net::SpdySerializedFrame> frame(
- client_framer_.CreateSettings(settings));
- ReceiveFrameFromClient(*frame);
-
- testing::InSequence seq;
- ExpectSendFrame(IsSettings(net::SETTINGS_MAX_CONCURRENT_STREAMS, 100));
- EXPECT_CALL(session_io_, IsConnectionAborted());
- EXPECT_CALL(session_io_, ProcessAvailableInput(Eq(true), NotNull()));
- ExpectSendGoAway(0, net::GOAWAY_PROTOCOL_ERROR);
-
- session_.Run();
- EXPECT_TRUE(executor_.stopped());
-}
-
-// Only run no-flow-control tests for SPDY v2.
-INSTANTIATE_TEST_CASE_P(Spdy2, SpdySessionNoFlowControlTest, testing::Values(
- mod_spdy::spdy::SPDY_VERSION_2));
-
-// Test class for flow-control tests. This uses a ThreadPool Executor, so that
-// we can test concurrency behavior.
-class SpdySessionFlowControlTest : public SpdySessionTestBase {
- public:
- SpdySessionFlowControlTest() : thread_pool_(1, 1) {}
-
- void SetUp() {
- ASSERT_TRUE(thread_pool_.Start());
- executor_.reset(thread_pool_.NewExecutor());
- session_.reset(new mod_spdy::SpdySession(
- spdy_version_, &config_, &session_io_, &task_factory_,
- executor_.get()));
- }
-
- void ExpectSendDataGetWindowUpdateBack(
- net::SpdyStreamId stream_id, bool fin, base::StringPiece payload) {
- EXPECT_CALL(session_io_, SendFrameRaw(_)).WillOnce(DoAll(
- ClientDecodeFrame(this, IsDataFrame(stream_id, fin, payload)),
- SendBackWindowUpdate(this, stream_id, payload.size()),
- Return(mod_spdy::SpdySessionIO::WRITE_SUCCESS)));
- }
-
- protected:
- mod_spdy::ThreadPool thread_pool_;
- scoped_ptr<mod_spdy::Executor> executor_;
- scoped_ptr<mod_spdy::SpdySession> session_;
-};
-
-TEST_P(SpdySessionFlowControlTest, SingleStreamWithFlowControl) {
- MockStreamTask* task = new MockStreamTask;
- // Start by setting the initial window size to very small (three bytes).
- ReceiveSettingsFrameFromClient(net::SETTINGS_INITIAL_WINDOW_SIZE, 3);
- // Then send a SYN_STREAM.
- const net::SpdyStreamId stream_id = 1;
- const net::SpdyPriority priority = 2;
- ReceiveSynStreamFromClient(stream_id, priority, net::CONTROL_FLAG_FIN);
-
- // We'll have to go through the loop at least five times -- once for each of
- // five frames that we _must_ receive (SETTINGS, SYN_STREAM, and three
- // WINDOW_UDPATEs.
- EXPECT_CALL(session_io_, IsConnectionAborted()).Times(AtLeast(5));
- EXPECT_CALL(session_io_, ProcessAvailableInput(_, NotNull()))
- .Times(AtLeast(5));
-
- // The rest of these will have to happen in a fixed order.
- testing::InSequence seq;
- ExpectSendFrame(IsSettings(net::SETTINGS_MAX_CONCURRENT_STREAMS, 100));
- EXPECT_CALL(task_factory_, NewStreamTask(
- AllOf(Property(&mod_spdy::SpdyStream::stream_id, Eq(stream_id)),
- Property(&mod_spdy::SpdyStream::associated_stream_id, Eq(0u)),
- Property(&mod_spdy::SpdyStream::priority, Eq(priority)))))
- .WillOnce(ReturnMockTask(task));
- EXPECT_CALL(*task, Run()).WillOnce(DoAll(
- SendResponseHeaders(task), SendDataFrame(task, "foobar", false),
- SendDataFrame(task, "quux", true)));
- // Since the window size is just three bytes, we can only send three bytes at
- // a time.
- ExpectSendSynReply(stream_id, false);
- ExpectSendDataGetWindowUpdateBack(stream_id, false, "foo");
- ExpectSendDataGetWindowUpdateBack(stream_id, false, "bar");
- ExpectSendDataGetWindowUpdateBack(stream_id, false, "quu");
- ExpectSendDataGetWindowUpdateBack(stream_id, true, "x");
- EXPECT_CALL(session_io_, ProcessAvailableInput(Eq(true), NotNull()))
- .WillOnce(Return(mod_spdy::SpdySessionIO::READ_CONNECTION_CLOSED));
- ExpectSendGoAway(stream_id, net::GOAWAY_OK);
-
- session_->Run();
-}
-
-// Suppose the input side of the connection closes while we're blocked on flow
-// control; we should abort the blocked streams.
-TEST_P(SpdySessionFlowControlTest, CeaseInputWithFlowControl) {
- MockStreamTask* task = new MockStreamTask;
- // Start by setting the initial window size to very small (three bytes).
- ReceiveSettingsFrameFromClient(net::SETTINGS_INITIAL_WINDOW_SIZE, 3);
- // Then send a SYN_STREAM.
- const net::SpdyStreamId stream_id = 1;
- const net::SpdyPriority priority = 2;
- ReceiveSynStreamFromClient(stream_id, priority, net::CONTROL_FLAG_FIN);
-
- EXPECT_CALL(session_io_, IsConnectionAborted()).Times(AtLeast(1));
- EXPECT_CALL(session_io_, ProcessAvailableInput(_, NotNull()))
- .Times(AtLeast(1));
-
- // The rest of these will have to happen in a fixed order.
- testing::InSequence seq;
- ExpectSendFrame(IsSettings(net::SETTINGS_MAX_CONCURRENT_STREAMS, 100));
- EXPECT_CALL(task_factory_, NewStreamTask(
- AllOf(Property(&mod_spdy::SpdyStream::stream_id, Eq(stream_id)),
- Property(&mod_spdy::SpdyStream::associated_stream_id, Eq(0u)),
- Property(&mod_spdy::SpdyStream::priority, Eq(priority)))))
- .WillOnce(ReturnMockTask(task));
- EXPECT_CALL(*task, Run()).WillOnce(DoAll(
- SendResponseHeaders(task), SendDataFrame(task, "foobar", false),
- SendDataFrame(task, "quux", true)));
- ExpectSendSynReply(stream_id, false);
- // Since the window size is just three bytes, we can only send three bytes at
- // a time. The stream thread will then be blocked.
- ExpectSendFrame(IsDataFrame(stream_id, false, "foo"));
- EXPECT_CALL(session_io_, ProcessAvailableInput(_, _))
- .WillOnce(Return(mod_spdy::SpdySessionIO::READ_CONNECTION_CLOSED));
- // At this point, we're blocked on flow control, and the test will close the
- // input side of the connection. Since the stream can never complete, the
- // session should abort the stream and shut down, rather than staying blocked
- // forever.
- ExpectSendGoAway(stream_id, net::GOAWAY_OK);
-
- session_->Run();
-}
-
-// Test that we send GOAWAY if the client tries to send
-// SETTINGS_INITIAL_WINDOW_SIZE with a value of 0.
-TEST_P(SpdySessionFlowControlTest, SendGoawayForTooSmallInitialWindowSize) {
- ReceiveSettingsFrameFromClient(net::SETTINGS_INITIAL_WINDOW_SIZE, 0);
-
- testing::InSequence seq;
- ExpectSendFrame(IsSettings(net::SETTINGS_MAX_CONCURRENT_STREAMS, 100));
- EXPECT_CALL(session_io_, IsConnectionAborted());
- EXPECT_CALL(session_io_, ProcessAvailableInput(Eq(true), NotNull()));
- ExpectSendGoAway(0, net::GOAWAY_PROTOCOL_ERROR);
-
- session_->Run();
-}
-
-// Test that we send GOAWAY if the client tries to send
-// SETTINGS_INITIAL_WINDOW_SIZE with a value of 0x80000000.
-TEST_P(SpdySessionFlowControlTest, SendGoawayForTooLargeInitialWindowSize) {
- ReceiveSettingsFrameFromClient(net::SETTINGS_INITIAL_WINDOW_SIZE,
- 0x80000000);
-
- testing::InSequence seq;
- ExpectSendFrame(IsSettings(net::SETTINGS_MAX_CONCURRENT_STREAMS, 100));
- EXPECT_CALL(session_io_, IsConnectionAborted());
- EXPECT_CALL(session_io_, ProcessAvailableInput(Eq(true), NotNull()));
- ExpectSendGoAway(0, net::GOAWAY_PROTOCOL_ERROR);
-
- session_->Run();
-}
-
-TEST_P(SpdySessionFlowControlTest, SharedOutputFlowControlWindow) {
- ReceiveWindowUpdateFrameFromClient(0, 10000);
-
- testing::InSequence seq;
- ExpectSendFrame(IsSettings(net::SETTINGS_MAX_CONCURRENT_STREAMS, 100));
- EXPECT_CALL(session_io_, IsConnectionAborted());
- EXPECT_CALL(session_io_, ProcessAvailableInput(Eq(true), NotNull()));
- if (session_->spdy_version() >= mod_spdy::spdy::SPDY_VERSION_3_1) {
- EXPECT_CALL(session_io_, IsConnectionAborted()).WillOnce(Return(true));
- } else {
- ExpectSendGoAway(0, net::GOAWAY_PROTOCOL_ERROR);
- }
-
- if (session_->spdy_version() >= mod_spdy::spdy::SPDY_VERSION_3_1) {
- EXPECT_EQ(65536, session_->current_shared_output_window_size());
- }
- session_->Run();
- if (session_->spdy_version() >= mod_spdy::spdy::SPDY_VERSION_3_1) {
- EXPECT_EQ(75536, session_->current_shared_output_window_size());
- }
-}
-
-TEST_P(SpdySessionFlowControlTest, SharedInputFlowControlWindow) {
- MockStreamTask* task = new MockStreamTask;
- const net::SpdyStreamId stream_id = 1;
- const net::SpdyPriority priority = 2;
- ReceiveSynStreamFromClient(stream_id, priority, net::CONTROL_FLAG_NONE);
- const std::string data1(32000, 'x');
- const std::string data2(2000, 'y');
- ReceiveDataFromClient(stream_id, data1, net::DATA_FLAG_NONE);
- ReceiveDataFromClient(stream_id, data1, net::DATA_FLAG_NONE);
- ReceiveDataFromClient(stream_id, data2, net::DATA_FLAG_FIN);
-
- EXPECT_CALL(session_io_, IsConnectionAborted()).Times(AtLeast(4));
-
- // The rest of these will have to happen in a fixed order.
- testing::InSequence seq;
- ExpectSendFrame(IsSettings(net::SETTINGS_MAX_CONCURRENT_STREAMS, 100));
- // Receive the SYN_STREAM from the client.
- EXPECT_CALL(session_io_, ProcessAvailableInput(_, NotNull()));
- EXPECT_CALL(task_factory_, NewStreamTask(
- AllOf(Property(&mod_spdy::SpdyStream::stream_id, Eq(stream_id)),
- Property(&mod_spdy::SpdyStream::associated_stream_id, Eq(0u)),
- Property(&mod_spdy::SpdyStream::priority, Eq(priority)))))
- .WillOnce(ReturnMockTask(task));
- EXPECT_CALL(*task, Run()).WillOnce(ConsumeInputUntilAborted(task));
- // Receive the first two blocks of data from the client with no problems.
- EXPECT_CALL(session_io_, ProcessAvailableInput(_, NotNull()));
- EXPECT_CALL(session_io_, ProcessAvailableInput(_, NotNull()));
- // The third block of data is too much; it's a flow control error. For
- // SPDY/3.1 and up it's a session flow control error; for SPDY/3 it's a
- // stream flow control error.
- EXPECT_CALL(session_io_, ProcessAvailableInput(_, NotNull()));
- if (session_->spdy_version() >= mod_spdy::spdy::SPDY_VERSION_3_1) {
- ExpectSendGoAway(stream_id, net::GOAWAY_PROTOCOL_ERROR);
- } else {
- ExpectSendFrame(IsRstStream(1, net::RST_STREAM_FLOW_CONTROL_ERROR));
- EXPECT_CALL(session_io_, IsConnectionAborted()).WillOnce(Return(true));
- }
-
- session_->Run();
-}
-
-// Only run flow control tests for SPDY v3 and up.
-INSTANTIATE_TEST_CASE_P(Spdy3, SpdySessionFlowControlTest, testing::Values(
- mod_spdy::spdy::SPDY_VERSION_3, mod_spdy::spdy::SPDY_VERSION_3_1));
-
-// Create a type alias so that we can instantiate some of our
-// SpdySessionTest-based tests using a different set of parameters.
-typedef SpdySessionTest SpdySessionServerPushTest;
-
-TEST_P(SpdySessionServerPushTest, SimpleServerPush) {
- MockStreamTask* task1 = new MockStreamTask;
- MockStreamTask* task2 = new MockStreamTask;
- executor_.set_run_on_add(true);
- const net::SpdyStreamId stream_id = 3;
- const net::SpdyPriority priority = 2;
- const net::SpdyPriority push_priority = 3;
- const std::string push_path = "/script.js";
- ReceiveSynStreamFromClient(stream_id, priority, net::CONTROL_FLAG_FIN);
-
- testing::InSequence seq;
- ExpectSendFrame(IsSettings(net::SETTINGS_MAX_CONCURRENT_STREAMS, 100));
- EXPECT_CALL(session_io_, IsConnectionAborted());
- EXPECT_CALL(session_io_, ProcessAvailableInput(Eq(true), NotNull()));
- EXPECT_CALL(task_factory_, NewStreamTask(
- AllOf(Property(&mod_spdy::SpdyStream::stream_id, Eq(stream_id)),
- Property(&mod_spdy::SpdyStream::associated_stream_id, Eq(0u)),
- Property(&mod_spdy::SpdyStream::priority, Eq(priority)))))
- .WillOnce(ReturnMockTask(task1));
- EXPECT_CALL(*task1, Run()).WillOnce(DoAll(
- SendResponseHeaders(task1),
- StartServerPush(task1, push_priority, push_path,
- mod_spdy::SpdyServerPushInterface::PUSH_STARTED),
- SendDataFrame(task1, "foobar", false),
- SendDataFrame(task1, "quux", true)));
- // We should right away create the server push task, and get the SYN_STREAM
- // before any other frames from the original stream.
- EXPECT_CALL(task_factory_, NewStreamTask(
- AllOf(Property(&mod_spdy::SpdyStream::stream_id, Eq(2u)),
- Property(&mod_spdy::SpdyStream::associated_stream_id,
- Eq(stream_id)),
- Property(&mod_spdy::SpdyStream::priority, Eq(push_priority)))))
- .WillOnce(ReturnMockTask(task2));
- EXPECT_CALL(*task2, Run()).WillOnce(DoAll(
- SendResponseHeaders(task2),
- SendDataFrame(task2, "hello", false),
- SendDataFrame(task2, "world", true)));
- ExpectBeginServerPush(2u, stream_id, push_priority, push_path);
- // The pushed stream has a low priority, so the rest of the first stream
- // should get sent before the rest of the pushed stream.
- ExpectSendSynReply(stream_id, false);
- ExpectSendFrame(IsDataFrame(stream_id, false, "foobar"));
- ExpectSendFrame(IsDataFrame(stream_id, true, "quux"));
- // Now we should get the rest of the pushed stream.
- ExpectSendHeaders(2u, false);
- ExpectSendFrame(IsDataFrame(2u, false, "hello"));
- ExpectSendFrame(IsDataFrame(2u, true, "world"));
- // And, we're done.
- EXPECT_CALL(session_io_, IsConnectionAborted());
- EXPECT_CALL(session_io_, ProcessAvailableInput(Eq(true), NotNull()))
- .WillOnce(Return(mod_spdy::SpdySessionIO::READ_CONNECTION_CLOSED));
- ExpectSendGoAway(stream_id, net::GOAWAY_OK);
-
- session_.Run();
- EXPECT_TRUE(executor_.stopped());
-}
-
-TEST_P(SpdySessionServerPushTest, TooManyConcurrentPushes) {
- MockStreamTask* task1 = new MockStreamTask;
- MockStreamTask* task2 = new MockStreamTask;
- MockStreamTask* task3 = new MockStreamTask;
- executor_.set_run_on_add(false);
- const net::SpdyStreamId stream_id = 9;
- const net::SpdyPriority priority = 0;
- ReceiveSettingsFrameFromClient(net::SETTINGS_MAX_CONCURRENT_STREAMS, 2);
- ReceiveSynStreamFromClient(stream_id, priority, net::CONTROL_FLAG_FIN);
-
- EXPECT_CALL(session_io_, IsConnectionAborted()).Times(AtLeast(3));
- EXPECT_CALL(session_io_, ProcessAvailableInput(_, NotNull()))
- .Times(AtLeast(3));
-
- testing::InSequence seq;
- ExpectSendFrame(IsSettings(net::SETTINGS_MAX_CONCURRENT_STREAMS, 100));
- EXPECT_CALL(task_factory_, NewStreamTask(
- AllOf(Property(&mod_spdy::SpdyStream::stream_id, Eq(stream_id)),
- Property(&mod_spdy::SpdyStream::associated_stream_id, Eq(0u)),
- Property(&mod_spdy::SpdyStream::priority, Eq(priority)))))
- .WillOnce(ReturnMockTask(task1));
- EXPECT_CALL(session_io_, IsConnectionAborted())
- .WillOnce(DoAll(InvokeWithoutArgs(&executor_, &InlineExecutor::RunOne),
- Return(false)));
- EXPECT_CALL(*task1, Run()).WillOnce(DoAll(
- StartServerPush(task1, 3u, "/foo.css",
- mod_spdy::SpdyServerPushInterface::PUSH_STARTED),
- StartServerPush(task1, 2u, "/bar.css",
- mod_spdy::SpdyServerPushInterface::PUSH_STARTED),
- StartServerPush(task1, 1u, "/baz.css",
- mod_spdy::SpdyServerPushInterface::TOO_MANY_CONCURRENT_PUSHES),
- SendResponseHeaders(task1), SendDataFrame(task1, "html", true)));
- // Start the first two pushes. The third push should fail due to too many
- // concurrent pushes.
- EXPECT_CALL(task_factory_, NewStreamTask(
- AllOf(Property(&mod_spdy::SpdyStream::stream_id, Eq(2u)),
- Property(&mod_spdy::SpdyStream::associated_stream_id,
- Eq(stream_id)),
- Property(&mod_spdy::SpdyStream::priority, Eq(3u)))))
- .WillOnce(ReturnMockTask(task2));
- EXPECT_CALL(task_factory_, NewStreamTask(
- AllOf(Property(&mod_spdy::SpdyStream::stream_id, Eq(4u)),
- Property(&mod_spdy::SpdyStream::associated_stream_id,
- Eq(stream_id)),
- Property(&mod_spdy::SpdyStream::priority, Eq(2u)))))
- .WillOnce(ReturnMockTask(task3));
- // Now we get the SYN_STREAMs for the pushed streams before anything else.
- ExpectBeginServerPush(2u, stream_id, 3u, "/foo.css");
- ExpectBeginServerPush(4u, stream_id, 2u, "/bar.css");
- // We now send the frames from the original stream.
- ExpectSendSynReply(stream_id, false);
- ExpectSendFrame(IsDataFrame(stream_id, true, "html"));
- // At this point, the client will change MAX_CONCURRENT_STREAMS to zero. We
- // shouldn't barf, even though we have more active push streams than the new
- // maximum.
- EXPECT_CALL(session_io_, IsConnectionAborted())
- .WillOnce(DoAll(
- SendBackSettings(this, net::SETTINGS_MAX_CONCURRENT_STREAMS, 0u),
- Return(false)));
- // Now let's run the rest of the tasks. One of them will try to start yet
- // another server push, but that should fail because MAX_CONCURRENT_STREAMS
- // is now zero.
- EXPECT_CALL(session_io_, IsConnectionAborted())
- .WillOnce(DoAll(InvokeWithoutArgs(&executor_, &InlineExecutor::RunAll),
- Return(false)));
- EXPECT_CALL(*task2, Run()).WillOnce(DoAll(
- SendResponseHeaders(task2), SendDataFrame(task2, "foo", true)));
- EXPECT_CALL(*task3, Run()).WillOnce(DoAll(
- StartServerPush(task3, 3u, "/stuff.png",
- mod_spdy::SpdyServerPushInterface::TOO_MANY_CONCURRENT_PUSHES),
- SendResponseHeaders(task3), SendDataFrame(task3, "bar", true)));
- // And now we get all those frames. The "bar" stream's frames should come
- // first, because that's a higher-priority stream.
- ExpectSendHeaders(4u, false);
- ExpectSendFrame(IsDataFrame(4u, true, "bar"));
- ExpectSendHeaders(2u, false);
- ExpectSendFrame(IsDataFrame(2u, true, "foo"));
- // And, we're done.
- EXPECT_CALL(session_io_, ProcessAvailableInput(_, NotNull()))
- .WillOnce(Return(mod_spdy::SpdySessionIO::READ_CONNECTION_CLOSED));
- ExpectSendGoAway(stream_id, net::GOAWAY_OK);
-
- session_.Run();
- EXPECT_TRUE(executor_.stopped());
-}
-
-// Only run server push tests for SPDY v3 and up.
-INSTANTIATE_TEST_CASE_P(Spdy3, SpdySessionServerPushTest, testing::Values(
- mod_spdy::spdy::SPDY_VERSION_3, mod_spdy::spdy::SPDY_VERSION_3_1));
-
-} // namespace
+++ /dev/null
-// 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.
-
-#include "mod_spdy/common/spdy_stream.h"
-
-
-#include "base/logging.h"
-#include "base/memory/scoped_ptr.h"
-#include "base/synchronization/condition_variable.h"
-#include "base/synchronization/lock.h"
-#include "mod_spdy/common/protocol_util.h"
-#include "mod_spdy/common/shared_flow_control_window.h"
-#include "mod_spdy/common/spdy_frame_priority_queue.h"
-#include "mod_spdy/common/spdy_frame_queue.h"
-#include "net/spdy/spdy_protocol.h"
-
-namespace {
-
-// The smallest WINDOW_UPDATE delta we're willing to send. If the client sends
-// us less than this much data, we wait for more data before sending a
-// WINDOW_UPDATE frame (so that we don't end up sending lots of little ones).
-const size_t kMinWindowUpdateSize =
- static_cast<size_t>(net::kSpdyStreamInitialWindowSize) / 8;
-
-class DataLengthVisitor : public net::SpdyFrameVisitor {
- public:
- DataLengthVisitor() : length_(0) {}
- virtual ~DataLengthVisitor() {}
-
- size_t length() const { return length_; }
-
- virtual void VisitSynStream(const net::SpdySynStreamIR& frame) {}
- virtual void VisitSynReply(const net::SpdySynReplyIR& frame) {}
- virtual void VisitRstStream(const net::SpdyRstStreamIR& frame) {}
- virtual void VisitSettings(const net::SpdySettingsIR& frame) {}
- virtual void VisitPing(const net::SpdyPingIR& frame) {}
- virtual void VisitGoAway(const net::SpdyGoAwayIR& frame) {}
- virtual void VisitHeaders(const net::SpdyHeadersIR& frame) {}
- virtual void VisitWindowUpdate(const net::SpdyWindowUpdateIR& frame) {}
- virtual void VisitCredential(const net::SpdyCredentialIR& frame) {}
- virtual void VisitBlocked(const net::SpdyBlockedIR& frame) {}
- virtual void VisitPushPromise(const net::SpdyPushPromiseIR& frame) {}
- virtual void VisitData(const net::SpdyDataIR& frame) {
- length_ = frame.data().size();
- }
-
- private:
- size_t length_;
-
- DISALLOW_COPY_AND_ASSIGN(DataLengthVisitor);
-};
-
-// For data frames, return the size of the data payload; for control frames,
-// return zero.
-size_t DataFrameLength(const net::SpdyFrameIR& frame) {
- DataLengthVisitor visitor;
- frame.Visit(&visitor);
- return visitor.length();
-}
-
-} // namespace
-
-namespace mod_spdy {
-
-SpdyStream::SpdyStream(spdy::SpdyVersion spdy_version,
- net::SpdyStreamId stream_id,
- net::SpdyStreamId associated_stream_id,
- int32 server_push_depth,
- net::SpdyPriority priority,
- int32 initial_output_window_size,
- SpdyFramePriorityQueue* output_queue,
- SharedFlowControlWindow* shared_window,
- SpdyServerPushInterface* pusher)
- : spdy_version_(spdy_version),
- stream_id_(stream_id),
- associated_stream_id_(associated_stream_id),
- server_push_depth_(server_push_depth),
- priority_(priority),
- output_queue_(output_queue),
- shared_window_(shared_window),
- pusher_(pusher),
- condvar_(&lock_),
- aborted_(false),
- output_window_size_(initial_output_window_size),
- // TODO(mdsteele): Make our initial input window size configurable (we
- // would send the chosen value to the client with a SETTINGS frame).
- input_window_size_(net::kSpdyStreamInitialWindowSize),
- input_bytes_consumed_(0) {
- DCHECK_NE(spdy::SPDY_VERSION_NONE, spdy_version);
- DCHECK(output_queue_);
- DCHECK(shared_window_ || spdy_version < spdy::SPDY_VERSION_3_1);
- DCHECK(pusher_);
- DCHECK_GT(output_window_size_, 0);
- // In SPDY v2, priorities are in the range 0-3; in SPDY v3, they are 0-7.
- DCHECK_GE(priority, 0u);
- DCHECK_LE(priority, LowestSpdyPriorityForVersion(spdy_version));
-}
-
-SpdyStream::~SpdyStream() {}
-
-bool SpdyStream::is_server_push() const {
- // By the SPDY spec, a stream has an even stream ID if and only if it was
- // initiated by the server.
- return stream_id_ % 2 == 0;
-}
-
-bool SpdyStream::is_aborted() const {
- base::AutoLock autolock(lock_);
- return aborted_;
-}
-
-void SpdyStream::AbortSilently() {
- base::AutoLock autolock(lock_);
- InternalAbortSilently();
-}
-
-void SpdyStream::AbortWithRstStream(net::SpdyRstStreamStatus status) {
- base::AutoLock autolock(lock_);
- InternalAbortWithRstStream(status);
-}
-
-int32 SpdyStream::current_input_window_size() const {
- base::AutoLock autolock(lock_);
- DCHECK_GE(spdy_version(), spdy::SPDY_VERSION_3);
- return input_window_size_;
-}
-
-int32 SpdyStream::current_output_window_size() const {
- base::AutoLock autolock(lock_);
- DCHECK_GE(spdy_version(), spdy::SPDY_VERSION_3);
- return output_window_size_;
-}
-
-void SpdyStream::OnInputDataConsumed(size_t size) {
- // Sanity check: there is no input data to absorb for a server push stream,
- // so we should only be getting called for client-initiated streams.
- DCHECK(!is_server_push());
-
- // Flow control only exists for SPDY v3 and up, so for SPDY v2 we don't need
- // to bother tracking this.
- if (spdy_version() < spdy::SPDY_VERSION_3) {
- return;
- }
-
- // If the size arg is zero, this method should be a no-op, so just quit now.
- if (size == 0) {
- return;
- }
-
- base::AutoLock autolock(lock_);
-
- // Don't bother with any of this if the stream has been aborted.
- if (aborted_) {
- return;
- }
-
- // First, if we're using SPDY/3.1 or later, we need to deal with the shared
- // session window. If after consuming this input data the shared window
- // thinks it's time to send a WINDOW_UPDATE for the session input window
- // (stream 0), send one, at top priority.
- if (spdy_version_ >= spdy::SPDY_VERSION_3_1) {
- const int32 shared_window_update =
- shared_window_->OnInputDataConsumed(size);
- if (shared_window_update > 0) {
- output_queue_->Insert(
- SpdyFramePriorityQueue::kTopPriority,
- new net::SpdyWindowUpdateIR(0, shared_window_update));
- }
- }
-
- // Make sure the current input window size is sane. Although there are
- // provisions in the SPDY spec that allow the window size to be temporarily
- // negative, or to go above its default initial size, with our current
- // implementation that should never happen. Once we make the initial input
- // window size configurable, we may need to adjust or remove these checks.
- DCHECK_GE(input_window_size_, 0);
- DCHECK_LE(input_window_size_, net::kSpdyStreamInitialWindowSize);
-
- // Add the newly consumed data to the total. Assuming our caller is behaving
- // well (even if the client isn't) -- that is, they are only consuming as
- // much data as we have put into the input queue -- there should be no
- // overflow here, and the new value should be at most the amount of
- // un-WINDOW_UPDATE-ed data we've received. The reason we can be sure of
- // this is that PostInputFrame() refuses to put more data into the queue than
- // the window size allows, and aborts the stream if the client tries.
- input_bytes_consumed_ += size;
- DCHECK_GE(input_bytes_consumed_, size);
- DCHECK_LE(input_bytes_consumed_,
- static_cast<size_t>(net::kSpdyStreamInitialWindowSize -
- input_window_size_));
-
- // We don't want to send lots of little WINDOW_UPDATE frames (as that would
- // waste bandwidth), so only bother sending one once it would have a
- // reasonably large value.
- // TODO(mdsteele): Consider also tracking whether we have received a FLAG_FIN
- // on this stream; once we've gotten FLAG_FIN, there will be no more data,
- // so we don't need to send any more WINDOW_UPDATE frames.
- if (input_bytes_consumed_ < kMinWindowUpdateSize) {
- return;
- }
-
- // The SPDY spec forbids sending WINDOW_UPDATE frames with a non-positive
- // delta-window-size (SPDY draft 3 section 2.6.8). But since we already
- // checked above that size was positive, input_bytes_consumed_ should now be
- // positive as well.
- DCHECK_GT(input_bytes_consumed_, 0u);
- // Make sure there won't be any overflow shenanigans.
- COMPILE_ASSERT(sizeof(size_t) >= sizeof(net::kSpdyMaximumWindowSize),
- size_t_is_at_least_32_bits);
- DCHECK_LE(input_bytes_consumed_,
- static_cast<size_t>(net::kSpdyMaximumWindowSize));
-
- // Send a WINDOW_UPDATE frame to the client and update our window size.
- SendOutputFrame(new net::SpdyWindowUpdateIR(
- stream_id_, input_bytes_consumed_));
- input_window_size_ += input_bytes_consumed_;
- DCHECK_LE(input_window_size_, net::kSpdyStreamInitialWindowSize);
- input_bytes_consumed_ = 0;
-}
-
-void SpdyStream::AdjustOutputWindowSize(int32 delta) {
- base::AutoLock autolock(lock_);
-
- // Flow control only exists for SPDY v3 and up.
- DCHECK_GE(spdy_version(), spdy::SPDY_VERSION_3);
-
- if (aborted_) {
- return;
- }
-
- // Check for overflow; if it happens, abort the stream (which will wake up
- // any blocked threads). Note that although delta is usually positive, it
- // can also be negative, so we check for both overflow and underflow.
- const int64 new_size =
- static_cast<int64>(output_window_size_) + static_cast<int64>(delta);
- if (new_size > static_cast<int64>(net::kSpdyMaximumWindowSize) ||
- new_size < -static_cast<int64>(net::kSpdyMaximumWindowSize)) {
- LOG(WARNING) << "Flow control overflow/underflow on stream "
- << stream_id_ << ". Aborting stream.";
- InternalAbortWithRstStream(net::RST_STREAM_FLOW_CONTROL_ERROR);
- return;
- }
-
- // Update the window size.
- const int32 old_size = output_window_size_;
- output_window_size_ = static_cast<int32>(new_size);
-
- // If the window size is newly positive, wake up any blocked threads.
- if (old_size <= 0 && output_window_size_ > 0) {
- condvar_.Broadcast();
- }
-}
-
-void SpdyStream::PostInputFrame(net::SpdyFrameIR* frame_ptr) {
- base::AutoLock autolock(lock_);
-
- // Take ownership of the frame, so it will get deleted if we return early.
- scoped_ptr<net::SpdyFrameIR> frame(frame_ptr);
-
- // Once a stream has been aborted, nothing more goes into the queue.
- if (aborted_) {
- return;
- }
-
- // If this is a nonempty data frame (and we're using SPDY v3 or above) we
- // need to track flow control.
- if (spdy_version() >= spdy::SPDY_VERSION_3) {
- DCHECK_GE(input_window_size_, 0);
- const int size = DataFrameLength(*frame); // returns zero for ctrl frames
- if (size > 0) {
- // If receiving this much data would overflow the window size, then abort
- // the stream with a flow control error.
- if (size > input_window_size_) {
- LOG(WARNING) << "Client violated flow control by sending too much data "
- << "to stream " << stream_id_ << ". Aborting stream.";
- InternalAbortWithRstStream(net::RST_STREAM_FLOW_CONTROL_ERROR);
- return; // Quit without posting the frame to the queue.
- }
- // Otherwise, decrease the window size. It will be increased again once
- // the data has been comsumed (by OnInputDataConsumed()).
- else {
- input_window_size_ -= size;
- }
- }
- }
-
- // Now that we've decreased the window size as necessary, we can make the
- // frame available for consumption by the stream thread.
- input_queue_.Insert(frame.release());
-}
-
-bool SpdyStream::GetInputFrame(bool block, net::SpdyFrameIR** frame) {
- return input_queue_.Pop(block, frame);
-}
-
-void SpdyStream::SendOutputSynStream(const net::SpdyHeaderBlock& headers,
- bool flag_fin) {
- DCHECK(is_server_push());
- base::AutoLock autolock(lock_);
- if (aborted_) {
- return;
- }
-
- scoped_ptr<net::SpdySynStreamIR> frame(new net::SpdySynStreamIR(stream_id_));
- frame->set_associated_to_stream_id(associated_stream_id_);
- frame->set_priority(priority_);
- frame->set_fin(flag_fin);
- frame->set_unidirectional(true);
- frame->GetMutableNameValueBlock()->insert(headers.begin(), headers.end());
- output_queue_->Insert(SpdyFramePriorityQueue::kTopPriority, frame.release());
-}
-
-void SpdyStream::SendOutputSynReply(const net::SpdyHeaderBlock& headers,
- bool flag_fin) {
- DCHECK(!is_server_push());
- base::AutoLock autolock(lock_);
- if (aborted_) {
- return;
- }
-
- scoped_ptr<net::SpdySynReplyIR> frame(new net::SpdySynReplyIR(stream_id_));
- frame->set_fin(flag_fin);
- frame->GetMutableNameValueBlock()->insert(headers.begin(), headers.end());
- SendOutputFrame(frame.release());
-}
-
-void SpdyStream::SendOutputHeaders(const net::SpdyHeaderBlock& headers,
- bool flag_fin) {
- base::AutoLock autolock(lock_);
- if (aborted_) {
- return;
- }
-
- scoped_ptr<net::SpdyHeadersIR> frame(new net::SpdyHeadersIR(stream_id_));
- frame->set_fin(flag_fin);
- frame->GetMutableNameValueBlock()->insert(headers.begin(), headers.end());
- SendOutputFrame(frame.release());
-}
-
-void SpdyStream::SendOutputDataFrame(base::StringPiece data, bool flag_fin) {
- base::AutoLock autolock(lock_);
- if (aborted_) {
- return;
- }
-
- // Flow control only exists for SPDY v3 and up; for SPDY v2, we can just send
- // the data without regard to the window size. Even with flow control, we
- // can of course send empty DATA frames at will.
- if (spdy_version() < spdy::SPDY_VERSION_3 || data.empty()) {
- // Suppress empty DATA frames (unless we're setting FLAG_FIN).
- if (!data.empty() || flag_fin) {
- scoped_ptr<net::SpdyDataIR> frame(new net::SpdyDataIR(stream_id_, data));
- frame->set_fin(flag_fin);
- SendOutputFrame(frame.release());
- }
- return;
- }
-
- while (!data.empty()) {
- // If the current window size is non-positive, we must wait to send data
- // until the client increases it (or we abort). Note that the window size
- // can be negative if the client decreased the maximum window size (with a
- // SETTINGS frame) after we already sent data (SPDY draft 3 section 2.6.8).
- while (!aborted_ && output_window_size_ <= 0) {
- condvar_.Wait();
- }
- if (aborted_) {
- return;
- }
- // If the current window size is less than the amount of data we'd like to
- // send, send a smaller data frame with the first part of the data, and
- // then we'll sleep until the window size is increased before sending the
- // rest.
- DCHECK_LE(data.size(), static_cast<size_t>(kint32max));
- const int32 full_length = data.size();
- DCHECK_GT(output_window_size_, 0);
- const int32 length_desired = std::min(full_length, output_window_size_);
- output_window_size_ -= length_desired;
- DCHECK_GE(output_window_size_, 0);
- // Now we need to request quota from the session-shared flow control
- // window. Since the call to RequestQuota may block, we need to unlock
- // first.
- int32 length_acquired;
- if (spdy_version() >= spdy::SPDY_VERSION_3_1) {
- base::AutoUnlock autounlock(lock_);
- DCHECK(shared_window_);
- length_acquired = shared_window_->RequestOutputQuota(length_desired);
- } else {
- // For SPDY versions that don't have a session window, just act like we
- // got the quota we wanted.
- length_acquired = length_desired;
- }
- // RequestQuota will return zero if the shared window has been aborted
- // (i.e. if the session has been aborted). So in that case let's just
- // abort too.
- if (length_acquired <= 0) {
- InternalAbortSilently();
- return;
- }
- // If we didn't acquire as much as we wanted from the shared window, put
- // the amount we're not actually using back into output_window_size_.
- else if (length_acquired < length_desired) {
- output_window_size_ += length_desired - length_acquired;
- }
- // Actually send the frame.
- scoped_ptr<net::SpdyDataIR> frame(
- new net::SpdyDataIR(stream_id_, data.substr(0, length_acquired)));
- frame->set_fin(flag_fin && length_acquired == full_length);
- SendOutputFrame(frame.release());
- data = data.substr(length_acquired);
- }
-}
-
-SpdyServerPushInterface::PushStatus SpdyStream::StartServerPush(
- net::SpdyPriority priority,
- const net::SpdyHeaderBlock& request_headers) {
- DCHECK_GE(spdy_version(), spdy::SPDY_VERSION_3);
- return pusher_->StartServerPush(stream_id_, server_push_depth_ + 1, priority,
- request_headers);
-}
-
-void SpdyStream::SendOutputFrame(net::SpdyFrameIR* frame) {
- lock_.AssertAcquired();
- DCHECK(!aborted_);
- output_queue_->Insert(static_cast<int>(priority_), frame);
-}
-
-void SpdyStream::InternalAbortSilently() {
- lock_.AssertAcquired();
- input_queue_.Abort();
- aborted_ = true;
- condvar_.Broadcast();
-}
-
-void SpdyStream::InternalAbortWithRstStream(net::SpdyRstStreamStatus status) {
- lock_.AssertAcquired();
- output_queue_->Insert(SpdyFramePriorityQueue::kTopPriority,
- new net::SpdyRstStreamIR(stream_id_, status));
- // InternalAbortSilently will set aborted_ to true, which will prevent the
- // stream thread from sending any more frames on this stream after the
- // RST_STREAM.
- InternalAbortSilently();
-}
-
-} // namespace mod_spdy
+++ /dev/null
-// 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.
-
-#ifndef MOD_SPDY_COMMON_SPDY_STREAM_H_
-#define MOD_SPDY_COMMON_SPDY_STREAM_H_
-
-#include "base/basictypes.h"
-#include "base/strings/string_piece.h"
-#include "base/synchronization/condition_variable.h"
-#include "base/synchronization/lock.h"
-#include "net/spdy/spdy_protocol.h"
-#include "mod_spdy/common/protocol_util.h"
-#include "mod_spdy/common/spdy_frame_queue.h"
-#include "mod_spdy/common/spdy_server_push_interface.h"
-
-namespace mod_spdy {
-
-class SharedFlowControlWindow;
-class SpdyFramePriorityQueue;
-
-// Represents one stream of a SPDY connection. This class is used to
-// coordinate and pass SPDY frames between the SPDY-to-HTTP filter, the
-// HTTP-to-SPDY filter, and the master SPDY connection thread. This class is
-// thread-safe, and in particular can be used concurrently by the stream thread
-// and the connection thread (although certain methods are meant to only ever
-// be called by one thread or the other; see the doc comments).
-class SpdyStream {
- public:
- // The SpdyStream object does *not* take ownership of any of these arguments.
- SpdyStream(spdy::SpdyVersion spdy_version,
- net::SpdyStreamId stream_id,
- net::SpdyStreamId associated_stream_id_,
- int32 server_push_depth,
- net::SpdyPriority priority,
- int32 initial_output_window_size,
- SpdyFramePriorityQueue* output_queue,
- SharedFlowControlWindow* shared_window,
- SpdyServerPushInterface* pusher);
- ~SpdyStream();
-
- // What version of SPDY is being used for this connection?
- spdy::SpdyVersion spdy_version() const { return spdy_version_; }
-
- // Return true if this stream was initiated by the server, false if it was
- // initiated by the client.
- bool is_server_push() const;
-
- // Get the ID for this SPDY stream.
- net::SpdyStreamId stream_id() const { return stream_id_; }
-
- // Get the ID for the SPDY stream with which this one is associated. By the
- // SPDY spec, if there is no associated stream, this will be zero.
- net::SpdyStreamId associated_stream_id() const {
- return associated_stream_id_;
- }
-
- // Get the current depth of the stream. 0 if this is a client initiated
- // stream or associated_stream.depth+1 if this stream was created as
- // a result of another stream.
- int32 server_push_depth() const { return server_push_depth_; }
-
- // Get the priority of this stream.
- net::SpdyPriority priority() const { return priority_; }
-
- // Return true if this stream has been aborted and should shut down.
- bool is_aborted() const;
-
- // Abort this stream. This method returns immediately, and the thread
- // running the stream will stop as soon as possible (if it is currently
- // blocked on the window size, it will be woken up).
- void AbortSilently();
-
- // Same as AbortSilently, but also sends a RST_STREAM frame for this stream.
- void AbortWithRstStream(net::SpdyRstStreamStatus status);
-
- // What are the current window sizes for this stream? These are mostly
- // useful for debugging. Requires that spdy_version() >= SPDY_VERSION_3.
- int32 current_input_window_size() const;
- int32 current_output_window_size() const;
-
- // This should be called by the stream thread for each chunk of input data
- // that it consumes. The SpdyStream object will take care of sending
- // WINDOW_UPDATE frames as appropriate (automatically bunching up smaller,
- // chunks to avoid sending too many frames, and of course not sending
- // WINDOW_UPDATE frames for SPDY/2 connections). The connection thread must
- // not call this method.
- void OnInputDataConsumed(size_t size);
-
- // This should be called by the connection thread to adjust the window size,
- // either due to receiving a WINDOW_UPDATE frame from the client, or from the
- // client changing the initial window size with a SETTINGS frame. The delta
- // argument will usually be positive (WINDOW_UPDATE is always positive), but
- // *can* be negative (if the client reduces the window size with SETTINGS).
- //
- // This method should *not* be called by the stream thread; the SpdyStream
- // object will automatically take care of decreasing the window size for sent
- // data.
- void AdjustOutputWindowSize(int32 delta);
-
- // Provide a SPDY frame sent from the client. This is to be called from the
- // master connection thread. This method takes ownership of the frame
- // object.
- void PostInputFrame(net::SpdyFrameIR* frame);
-
- // Get a SPDY frame from the client and return true, or return false if no
- // frame is available. If the block argument is true and no frame is
- // currently available, block until a frame becomes available or the stream
- // is aborted. This is to be called from the stream thread. The caller
- // gains ownership of the provided frame.
- bool GetInputFrame(bool block, net::SpdyFrameIR** frame);
-
- // Send a SYN_STREAM frame to the client for this stream. This may only be
- // called if is_server_push() is true.
- void SendOutputSynStream(const net::SpdyHeaderBlock& headers, bool flag_fin);
-
- // Send a SYN_REPLY frame to the client for this stream. This may only be
- // called if is_server_push() is false.
- void SendOutputSynReply(const net::SpdyHeaderBlock& headers, bool flag_fin);
-
- // Send a HEADERS frame to the client for this stream.
- void SendOutputHeaders(const net::SpdyHeaderBlock& headers, bool flag_fin);
-
- // Send a SPDY data frame to the client on this stream.
- void SendOutputDataFrame(base::StringPiece data, bool flag_fin);
-
- // Initiate a SPDY server push associated with this stream, roughly by
- // pretending that the client sent a SYN_STREAM with the given headers. To
- // repeat: the headers argument is _not_ the headers that the server will
- // send to the client, but rather the headers to _pretend_ that the client
- // sent to the server. Requires that spdy_version() >= 3.
- SpdyServerPushInterface::PushStatus StartServerPush(
- net::SpdyPriority priority,
- const net::SpdyHeaderBlock& request_headers);
-
- private:
- // Send a SPDY frame to the client. This is to be called from the stream
- // thread. This method takes ownership of the frame object. Must be holding
- // lock_ to call this method.
- void SendOutputFrame(net::SpdyFrameIR* frame);
-
- // Aborts the input queue, sets aborted_, and wakes up threads waiting on
- // condvar_. Must be holding lock_ to call this method.
- void InternalAbortSilently();
-
- // Like InternalAbortSilently, but also sends a RST_STREAM frame for this
- // stream. Must be holding lock_ to call this method.
- void InternalAbortWithRstStream(net::SpdyRstStreamStatus status);
-
- // These fields are all either constant or thread-safe, and do not require
- // additional synchronization.
- const spdy::SpdyVersion spdy_version_;
- const net::SpdyStreamId stream_id_;
- const net::SpdyStreamId associated_stream_id_;
- const int32 server_push_depth_;
- const net::SpdyPriority priority_;
- SpdyFrameQueue input_queue_;
- SpdyFramePriorityQueue* const output_queue_;
- SharedFlowControlWindow* const shared_window_;
- SpdyServerPushInterface* const pusher_;
-
- // The lock protects the fields below. The above fields do not require
- // additional synchronization.
- mutable base::Lock lock_;
- base::ConditionVariable condvar_;
- bool aborted_;
- int32 output_window_size_;
- int32 input_window_size_;
- size_t input_bytes_consumed_; // consumed since we last sent a WINDOW_UPDATE
- size_t input_bytes_unconsumed_; // received but not yet consumed
-
- DISALLOW_COPY_AND_ASSIGN(SpdyStream);
-};
-
-} // namespace mod_spdy
-
-#endif // MOD_SPDY_COMMON_SPDY_STREAM_H_
+++ /dev/null
-// 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.
-
-#include "mod_spdy/common/spdy_stream_task_factory.h"
-
-namespace mod_spdy {
-
-SpdyStreamTaskFactory::SpdyStreamTaskFactory() {}
-
-SpdyStreamTaskFactory::~SpdyStreamTaskFactory() {}
-
-} // namespace mod_spdy
+++ /dev/null
-// 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.
-
-#ifndef MOD_SPDY_COMMON_SPDY_STREAM_TASK_FACTORY_H_
-#define MOD_SPDY_COMMON_SPDY_STREAM_TASK_FACTORY_H_
-
-#include "base/basictypes.h"
-
-namespace net_instaweb { class Function; }
-
-namespace mod_spdy {
-
-class SpdyStream;
-
-// SpdyStreamTaskFactory is a helper interface for the SpdySession class.
-// The task factory generates tasks that take care of processing SPDY streams.
-// The task factory must not be deleted before all such tasks have been
-// disposed of (run or cancelled).
-class SpdyStreamTaskFactory {
- public:
- SpdyStreamTaskFactory();
- virtual ~SpdyStreamTaskFactory();
-
- // Create a new task to process the given stream. Running the task should
- // process the stream -- that is, pull frames off the stream's input queue
- // and post frames to the stream's output queue -- and the task should not
- // complete until the stream is completely finished.
- //
- // The implementation may assume that the factory will outlive the task.
- virtual net_instaweb::Function* NewStreamTask(SpdyStream* stream) = 0;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(SpdyStreamTaskFactory);
-};
-
-} // namespace mod_spdy
-
-#endif // MOD_SPDY_COMMON_SPDY_STREAM_TASK_FACTORY_H_
+++ /dev/null
-// 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.
-
-#include "mod_spdy/common/spdy_stream.h"
-
-#include <string>
-
-#include "base/basictypes.h"
-#include "base/memory/scoped_ptr.h"
-#include "base/strings/string_piece.h"
-#include "base/time/time.h"
-#include "mod_spdy/common/protocol_util.h"
-#include "mod_spdy/common/shared_flow_control_window.h"
-#include "mod_spdy/common/spdy_frame_priority_queue.h"
-#include "mod_spdy/common/testing/async_task_runner.h"
-#include "mod_spdy/common/testing/notification.h"
-#include "mod_spdy/common/testing/spdy_frame_matchers.h"
-#include "net/spdy/spdy_protocol.h"
-#include "testing/gmock/include/gmock/gmock.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-using mod_spdy::testing::IsDataFrame;
-using mod_spdy::testing::IsRstStream;
-using mod_spdy::testing::IsWindowUpdate;
-
-namespace {
-
-const net::SpdyStreamId kStreamId = 1;
-const net::SpdyStreamId kAssocStreamId = 0;
-const int32 kInitServerPushDepth = 0;
-const net::SpdyPriority kPriority = 2;
-
-class MockSpdyServerPushInterface : public mod_spdy::SpdyServerPushInterface {
- public:
- MOCK_METHOD4(StartServerPush,
- mod_spdy::SpdyServerPushInterface::PushStatus(
- net::SpdyStreamId associated_stream_id,
- int32 server_push_depth,
- net::SpdyPriority priority,
- const net::SpdyNameValueBlock& request_headers));
-};
-
-// Expect to get a frame from the queue (within 100 milliseconds) that is a
-// data frame with the given payload and FLAG_FIN setting.
-void ExpectDataFrame(mod_spdy::SpdyFramePriorityQueue* output_queue,
- base::StringPiece data, bool flag_fin) {
- net::SpdyFrameIR* raw_frame;
- ASSERT_TRUE(output_queue->BlockingPop(
- base::TimeDelta::FromMilliseconds(100), &raw_frame));
- scoped_ptr<net::SpdyFrameIR> frame(raw_frame);
- EXPECT_THAT(*frame, IsDataFrame(kStreamId, flag_fin, data));
-}
-
-// Expect to get a frame from the queue (within 100 milliseconds) that is a
-// RST_STREAM frame with the given status code.
-void ExpectRstStream(mod_spdy::SpdyFramePriorityQueue* output_queue,
- net::SpdyRstStreamStatus status) {
- net::SpdyFrameIR* raw_frame;
- ASSERT_TRUE(output_queue->BlockingPop(
- base::TimeDelta::FromMilliseconds(100), &raw_frame));
- scoped_ptr<net::SpdyFrameIR> frame(raw_frame);
- EXPECT_THAT(*frame, IsRstStream(kStreamId, status));
-}
-
-// Expect to get a frame from the queue (within 100 milliseconds) that is a
-// WINDOW_UPDATE frame with the given delta.
-void ExpectWindowUpdate(mod_spdy::SpdyFramePriorityQueue* output_queue,
- uint32 delta) {
- net::SpdyFrameIR* raw_frame;
- ASSERT_TRUE(output_queue->BlockingPop(
- base::TimeDelta::FromMilliseconds(100), &raw_frame));
- scoped_ptr<net::SpdyFrameIR> frame(raw_frame);
- EXPECT_THAT(*frame, IsWindowUpdate(kStreamId, delta));
-}
-
-// Expect to get a frame from the queue (within 100 milliseconds) that is a
-// WINDOW_UPDATE frame, for stream zero, with the given delta.
-void ExpectSessionWindowUpdate(mod_spdy::SpdyFramePriorityQueue* output_queue,
- uint32 delta) {
- net::SpdyFrameIR* raw_frame;
- ASSERT_TRUE(output_queue->BlockingPop(
- base::TimeDelta::FromMilliseconds(100), &raw_frame));
- scoped_ptr<net::SpdyFrameIR> frame(raw_frame);
- EXPECT_THAT(*frame, IsWindowUpdate(0, delta));
-}
-
-// When run, a SendDataTask sends the given data to the given stream.
-class SendDataTask : public mod_spdy::testing::AsyncTaskRunner::Task {
- public:
- SendDataTask(mod_spdy::SpdyStream* stream, base::StringPiece data,
- bool flag_fin)
- : stream_(stream), data_(data), flag_fin_(flag_fin) {}
- virtual void Run() {
- stream_->SendOutputDataFrame(data_, flag_fin_);
- }
- private:
- mod_spdy::SpdyStream* const stream_;
- const base::StringPiece data_;
- const bool flag_fin_;
- DISALLOW_COPY_AND_ASSIGN(SendDataTask);
-};
-
-// Test that the flow control features are disabled for SPDY v2.
-TEST(SpdyStreamTest, NoFlowControlInSpdy2) {
- mod_spdy::SpdyFramePriorityQueue output_queue;
- MockSpdyServerPushInterface pusher;
- const int32 initial_window_size = 10;
- mod_spdy::SpdyStream stream(
- mod_spdy::spdy::SPDY_VERSION_2, kStreamId, kAssocStreamId,
- kInitServerPushDepth, kPriority, initial_window_size, &output_queue,
- NULL, &pusher);
-
- // Send more data than can fit in the initial window size.
- const base::StringPiece data = "abcdefghijklmnopqrstuvwxyz";
- stream.SendOutputDataFrame(data, true);
-
- // We should get all the data out in one frame anyway, because we're using
- // SPDY v2 and the stream shouldn't be using flow control.
- ExpectDataFrame(&output_queue, data, true);
- EXPECT_TRUE(output_queue.IsEmpty());
-}
-
-// Test that flow control works correctly for SPDY/3.
-TEST(SpdyStreamTest, HasFlowControlInSpdy3) {
- mod_spdy::SpdyFramePriorityQueue output_queue;
- mod_spdy::SharedFlowControlWindow shared_window(1000, 7);
- MockSpdyServerPushInterface pusher;
- const int32 initial_window_size = 10;
- mod_spdy::SpdyStream stream(
- mod_spdy::spdy::SPDY_VERSION_3, kStreamId, kAssocStreamId,
- kInitServerPushDepth, kPriority, initial_window_size, &output_queue,
- &shared_window, &pusher);
-
- // Send more data than can fit in the initial window size.
- const base::StringPiece data = "abcdefghijklmnopqrstuvwxyz";
- mod_spdy::testing::AsyncTaskRunner runner(
- new SendDataTask(&stream, data, true));
- ASSERT_TRUE(runner.Start());
-
- // We should get a single frame out with the first initial_window_size=10
- // bytes (and no FLAG_FIN yet), and then the task should be blocked for now.
- ExpectDataFrame(&output_queue, "abcdefghij", false);
- EXPECT_TRUE(output_queue.IsEmpty());
- runner.notification()->ExpectNotSet();
-
- // After increasing the window size by eight, we should get eight more bytes,
- // and then we should still be blocked.
- stream.AdjustOutputWindowSize(8);
- ExpectDataFrame(&output_queue, "klmnopqr", false);
- EXPECT_TRUE(output_queue.IsEmpty());
- runner.notification()->ExpectNotSet();
-
- // Finally, we increase the window size by fifteen. We should get the last
- // eight bytes of data out (with FLAG_FIN now set), the task should be
- // completed, and the remaining window size should be seven.
- stream.AdjustOutputWindowSize(15);
- ExpectDataFrame(&output_queue, "stuvwxyz", true);
- EXPECT_TRUE(output_queue.IsEmpty());
- runner.notification()->ExpectSetWithinMillis(100);
- EXPECT_EQ(7, stream.current_output_window_size());
-}
-
-// Test that the session flow control window works correctly for SPDY/3.1.
-TEST(SpdyStreamTest, SessionWindowInSpdy31) {
- mod_spdy::SpdyFramePriorityQueue output_queue;
- mod_spdy::SharedFlowControlWindow shared_window(1000, 7);
- MockSpdyServerPushInterface pusher;
- const int32 initial_window_size = 10;
- mod_spdy::SpdyStream stream(
- mod_spdy::spdy::SPDY_VERSION_3_1, kStreamId, kAssocStreamId,
- kInitServerPushDepth, kPriority, initial_window_size,
- &output_queue, &shared_window, &pusher);
-
- // Send more data than can fit in the initial window size.
- const base::StringPiece data = "abcdefghijklmnopqrstuvwxyz";
- mod_spdy::testing::AsyncTaskRunner runner(
- new SendDataTask(&stream, data, true));
- ASSERT_TRUE(runner.Start());
-
- // The stream window size is 10, but the session window size is only 7. So
- // we should only get 7 bytes at first.
- ExpectDataFrame(&output_queue, "abcdefg", false);
- EXPECT_TRUE(output_queue.IsEmpty());
- runner.notification()->ExpectNotSet();
- EXPECT_EQ(0, shared_window.current_output_window_size());
-
- // Now we increase the shared window size to 8. The stream window size is
- // only 3, so we should get just 3 more bytes.
- EXPECT_TRUE(shared_window.IncreaseOutputWindowSize(8));
- ExpectDataFrame(&output_queue, "hij", false);
- EXPECT_TRUE(output_queue.IsEmpty());
- runner.notification()->ExpectNotSet();
- EXPECT_EQ(5, shared_window.current_output_window_size());
- EXPECT_EQ(0, stream.current_output_window_size());
-
- // Next, increase the stream window by 20 bytes. The shared window is only
- // 5, so we get 5 bytes.
- stream.AdjustOutputWindowSize(20);
- ExpectDataFrame(&output_queue, "klmno", false);
- EXPECT_TRUE(output_queue.IsEmpty());
- runner.notification()->ExpectNotSet();
- EXPECT_EQ(0, shared_window.current_output_window_size());
-
- // Finally, we increase the shared window size by 20. We should get the last
- // 11 bytes of data out (with FLAG_FIN now set), and the task should be
- // completed.
- EXPECT_TRUE(shared_window.IncreaseOutputWindowSize(20));
- ExpectDataFrame(&output_queue, "pqrstuvwxyz", true);
- EXPECT_TRUE(output_queue.IsEmpty());
- runner.notification()->ExpectSetWithinMillis(100);
- EXPECT_EQ(9, shared_window.current_output_window_size());
- EXPECT_EQ(4, stream.current_output_window_size());
-}
-
-// Test that flow control is well-behaved when the stream is aborted.
-TEST(SpdyStreamTest, FlowControlAbort) {
- mod_spdy::SpdyFramePriorityQueue output_queue;
- MockSpdyServerPushInterface pusher;
- const int32 initial_window_size = 7;
- mod_spdy::SpdyStream stream(
- mod_spdy::spdy::SPDY_VERSION_3, kStreamId, kAssocStreamId,
- kInitServerPushDepth, kPriority, initial_window_size, &output_queue,
- NULL, &pusher);
-
- // Send more data than can fit in the initial window size.
- const base::StringPiece data = "abcdefghijklmnopqrstuvwxyz";
- mod_spdy::testing::AsyncTaskRunner runner(
- new SendDataTask(&stream, data, true));
- ASSERT_TRUE(runner.Start());
-
- // We should get a single frame out with the first initial_window_size=7
- // bytes (and no FLAG_FIN yet), and then the task should be blocked for now.
- ExpectDataFrame(&output_queue, "abcdefg", false);
- EXPECT_TRUE(output_queue.IsEmpty());
- runner.notification()->ExpectNotSet();
- EXPECT_FALSE(stream.is_aborted());
-
- // We now abort with a RST_STREAM frame. We should get the RST_STREAM frame
- // out, but no more data, and the call to SendOutputDataFrame should return
- // even though the rest of the data was never sent.
- stream.AbortWithRstStream(net::RST_STREAM_PROTOCOL_ERROR);
- EXPECT_TRUE(stream.is_aborted());
- ExpectRstStream(&output_queue, net::RST_STREAM_PROTOCOL_ERROR);
- EXPECT_TRUE(output_queue.IsEmpty());
- runner.notification()->ExpectSetWithinMillis(100);
-
- // Now that we're aborted, any attempt to send more frames should be ignored.
- stream.SendOutputDataFrame("foobar", false);
- net::SpdyNameValueBlock headers;
- headers["x-foo"] = "bar";
- stream.SendOutputHeaders(headers, true);
- EXPECT_TRUE(output_queue.IsEmpty());
-}
-
-// Test that we abort the stream with FLOW_CONTROL_ERROR if the client
-// incorrectly overflows the 31-bit window size value.
-TEST(SpdyStreamTest, FlowControlOverflow) {
- mod_spdy::SpdyFramePriorityQueue output_queue;
- MockSpdyServerPushInterface pusher;
- mod_spdy::SpdyStream stream(
- mod_spdy::spdy::SPDY_VERSION_3, kStreamId, kAssocStreamId,
- kInitServerPushDepth, kPriority, 0x60000000, &output_queue, NULL,
- &pusher);
-
- // Increase the window size so large that it overflows. We should get a
- // RST_STREAM frame and the stream should be aborted.
- EXPECT_FALSE(stream.is_aborted());
- stream.AdjustOutputWindowSize(0x20000000);
- EXPECT_TRUE(stream.is_aborted());
- ExpectRstStream(&output_queue, net::RST_STREAM_FLOW_CONTROL_ERROR);
- EXPECT_TRUE(output_queue.IsEmpty());
-}
-
-// Test that flow control works correctly even if the window size is
-// temporarily negative.
-TEST(SpdyStreamTest, NegativeWindowSize) {
- mod_spdy::SpdyFramePriorityQueue output_queue;
- MockSpdyServerPushInterface pusher;
- const int32 initial_window_size = 10;
- mod_spdy::SpdyStream stream(
- mod_spdy::spdy::SPDY_VERSION_3, kStreamId, kAssocStreamId,
- kInitServerPushDepth, kPriority, initial_window_size, &output_queue,
- NULL, &pusher);
-
- // Send more data than can fit in the initial window size.
- const base::StringPiece data = "abcdefghijklmnopqrstuvwxyz";
- mod_spdy::testing::AsyncTaskRunner runner(
- new SendDataTask(&stream, data, true));
- ASSERT_TRUE(runner.Start());
-
- // We should get a single frame out with the first initial_window_size=10
- // bytes (and no FLAG_FIN yet), and then the task should be blocked for now.
- ExpectDataFrame(&output_queue, "abcdefghij", false);
- EXPECT_TRUE(output_queue.IsEmpty());
- runner.notification()->ExpectNotSet();
- EXPECT_EQ(0, stream.current_output_window_size());
-
- // Adjust the window size down (as if due to a SETTINGS frame reducing the
- // initial window size). Our current window size should now be negative, and
- // we should still be blocked.
- stream.AdjustOutputWindowSize(-5);
- EXPECT_TRUE(output_queue.IsEmpty());
- runner.notification()->ExpectNotSet();
- EXPECT_EQ(-5, stream.current_output_window_size());
-
- // Adjust the initial window size up, but not enough to be positive. We
- // should still be blocked.
- stream.AdjustOutputWindowSize(4);
- EXPECT_TRUE(output_queue.IsEmpty());
- runner.notification()->ExpectNotSet();
- EXPECT_EQ(-1, stream.current_output_window_size());
-
- // Adjust the initial window size up again. Now we should get a few more
- // bytes out.
- stream.AdjustOutputWindowSize(4);
- ExpectDataFrame(&output_queue, "klm", false);
- EXPECT_TRUE(output_queue.IsEmpty());
- runner.notification()->ExpectNotSet();
- EXPECT_EQ(0, stream.current_output_window_size());
-
- // Finally, open the floodgates; we should get the rest of the data.
- stream.AdjustOutputWindowSize(800);
- ExpectDataFrame(&output_queue, "nopqrstuvwxyz", true);
- EXPECT_TRUE(output_queue.IsEmpty());
- runner.notification()->ExpectSetWithinMillis(100);
- EXPECT_EQ(787, stream.current_output_window_size());
-}
-
-// Test that we handle sending empty DATA frames correctly in SPDY v2.
-TEST(SpdyStreamTest, SendEmptyDataFrameInSpdy2) {
- mod_spdy::SpdyFramePriorityQueue output_queue;
- MockSpdyServerPushInterface pusher;
- mod_spdy::SpdyStream stream(
- mod_spdy::spdy::SPDY_VERSION_2, kStreamId, kAssocStreamId,
- kInitServerPushDepth, kPriority, net::kSpdyStreamInitialWindowSize,
- &output_queue, NULL, &pusher);
-
- // Try to send an empty data frame without FLAG_FIN. It should be
- // suppressed.
- stream.SendOutputDataFrame("", false);
- EXPECT_TRUE(output_queue.IsEmpty());
-
- // Now send an empty data frame _with_ FLAG_FIN. It should _not_ be
- // suppressed.
- stream.SendOutputDataFrame("", true);
- ExpectDataFrame(&output_queue, "", true);
- EXPECT_TRUE(output_queue.IsEmpty());
-}
-
-// Test that we handle sending empty DATA frames correctly in SPDY v3.
-TEST(SpdyStreamTest, SendEmptyDataFrameInSpdy3) {
- mod_spdy::SpdyFramePriorityQueue output_queue;
- MockSpdyServerPushInterface pusher;
- const int32 initial_window_size = 10;
- mod_spdy::SpdyStream stream(
- mod_spdy::spdy::SPDY_VERSION_3, kStreamId, kAssocStreamId,
- kInitServerPushDepth, kPriority, initial_window_size, &output_queue,
- NULL, &pusher);
-
- // Try to send an empty data frame without FLAG_FIN. It should be
- // suppressed.
- stream.SendOutputDataFrame("", false);
- EXPECT_TRUE(output_queue.IsEmpty());
- EXPECT_EQ(initial_window_size, stream.current_output_window_size());
-
- // Send one window's worth of data. It should get sent successfully.
- const std::string data(initial_window_size, 'x');
- stream.SendOutputDataFrame(data, false);
- ExpectDataFrame(&output_queue, data, false);
- EXPECT_TRUE(output_queue.IsEmpty());
- EXPECT_EQ(0, stream.current_output_window_size());
-
- // Try to send another empty data frame without FLAG_FIN. It should be
- // suppressed, and we shouldn't block, even though the window size is zero.
- stream.SendOutputDataFrame("", false);
- EXPECT_TRUE(output_queue.IsEmpty());
- EXPECT_EQ(0, stream.current_output_window_size());
-
- // Now send an empty data frame _with_ FLAG_FIN. It should _not_ be
- // suppressed, and we still shouldn't block.
- stream.SendOutputDataFrame("", true);
- ExpectDataFrame(&output_queue, "", true);
- EXPECT_TRUE(output_queue.IsEmpty());
- EXPECT_EQ(0, stream.current_output_window_size());
-}
-
-TEST(SpdyStreamTest, InputFlowControlInSpdy3) {
- mod_spdy::SpdyFramePriorityQueue output_queue;
- MockSpdyServerPushInterface pusher;
- mod_spdy::SpdyStream stream(
- mod_spdy::spdy::SPDY_VERSION_3, kStreamId, kAssocStreamId,
- kInitServerPushDepth, kPriority, net::kSpdyStreamInitialWindowSize,
- &output_queue, NULL, &pusher);
-
- // The initial window size is 64K.
- EXPECT_EQ(65536, stream.current_input_window_size());
-
- // Post a SYN_STREAM frame to the input. This should not affect the input
- // window size.
- net::SpdyNameValueBlock request_headers;
- request_headers[mod_spdy::http::kContentLength] = "4000";
- request_headers[mod_spdy::spdy::kSpdy3Host] = "www.example.com";
- request_headers[mod_spdy::spdy::kSpdy3Method] = "GET";
- request_headers[mod_spdy::spdy::kSpdy3Path] = "/index.html";
- request_headers[mod_spdy::spdy::kSpdy3Version] = "HTTP/1.1";
- scoped_ptr<net::SpdySynStreamIR> syn_stream(
- new net::SpdySynStreamIR(kStreamId));
- syn_stream->set_associated_to_stream_id(kAssocStreamId);
- syn_stream->set_priority(kPriority);
- syn_stream->GetMutableNameValueBlock()->insert(
- request_headers.begin(), request_headers.end());
- stream.PostInputFrame(syn_stream.release());
- EXPECT_EQ(65536, stream.current_input_window_size());
-
- // Send a little bit of data. This should reduce the input window size.
- const std::string data1("abcdefghij");
- stream.PostInputFrame(new net::SpdyDataIR(kStreamId, data1));
- EXPECT_TRUE(output_queue.IsEmpty());
- EXPECT_EQ(65526, stream.current_input_window_size());
-
- // Inform the stream that we have consumed this data. However, we shouldn't
- // yet send a WINDOW_UPDATE frame for so small an amount, so the window size
- // should stay the same.
- stream.OnInputDataConsumed(10);
- EXPECT_TRUE(output_queue.IsEmpty());
- EXPECT_EQ(65526, stream.current_input_window_size());
-
- // Send the rest of the data. This should further reduce the input window
- // size.
- const std::string data2(9000, 'x');
- scoped_ptr<net::SpdyDataIR> data_frame(
- new net::SpdyDataIR(kStreamId, data2));
- data_frame->set_fin(true);
- stream.PostInputFrame(data_frame.release());
- EXPECT_TRUE(output_queue.IsEmpty());
- EXPECT_EQ(56526, stream.current_input_window_size());
-
- // Inform the stream that we have consumed a bit more of the data. However,
- // we still shouldn't yet send a WINDOW_UPDATE frame, and the window size
- // should still stay the same.
- stream.OnInputDataConsumed(10);
- EXPECT_TRUE(output_queue.IsEmpty());
- EXPECT_EQ(56526, stream.current_input_window_size());
-
- // Now say that we've consumed a whole bunch of data. At this point, we
- // should get a WINDOW_UPDATE frame for everything consumed so far, and the
- // window size should increase accordingly.
- stream.OnInputDataConsumed(8900);
- ExpectWindowUpdate(&output_queue, 8920);
- EXPECT_TRUE(output_queue.IsEmpty());
- EXPECT_EQ(65446, stream.current_input_window_size());
-
- // Consume the last of the data. This is now just a little bit, so no need
- // for a WINDOW_UPDATE here.
- stream.OnInputDataConsumed(90);
- EXPECT_TRUE(output_queue.IsEmpty());
- EXPECT_EQ(65446, stream.current_input_window_size());
-}
-
-TEST(SpdyStreamTest, InputFlowControlInSpdy31) {
- mod_spdy::SpdyFramePriorityQueue output_queue;
- mod_spdy::SharedFlowControlWindow shared_window(
- net::kSpdyStreamInitialWindowSize,
- net::kSpdyStreamInitialWindowSize);
- MockSpdyServerPushInterface pusher;
- mod_spdy::SpdyStream stream(
- mod_spdy::spdy::SPDY_VERSION_3_1, kStreamId, kAssocStreamId,
- kInitServerPushDepth, kPriority, net::kSpdyStreamInitialWindowSize,
- &output_queue, &shared_window, &pusher);
-
- // The initial window size is 64K.
- EXPECT_EQ(65536, stream.current_input_window_size());
-
- // Post a SYN_STREAM frame to the input. This should not affect the input
- // window size.
- net::SpdyHeaderBlock request_headers;
- request_headers[mod_spdy::http::kContentLength] = "4000";
- request_headers[mod_spdy::spdy::kSpdy3Host] = "www.example.com";
- request_headers[mod_spdy::spdy::kSpdy3Method] = "GET";
- request_headers[mod_spdy::spdy::kSpdy3Path] = "/index.html";
- request_headers[mod_spdy::spdy::kSpdy3Version] = "HTTP/1.1";
-
- scoped_ptr<net::SpdySynStreamIR> syn_stream(
- new net::SpdySynStreamIR(kStreamId));
- syn_stream->set_associated_to_stream_id(kAssocStreamId);
- syn_stream->set_priority(kPriority);
- syn_stream->GetMutableNameValueBlock()->insert(
- request_headers.begin(), request_headers.end());
- stream.PostInputFrame(syn_stream.release());
- EXPECT_EQ(65536, stream.current_input_window_size());
-
- // Send a little bit of data. This should reduce the input window size.
- const std::string data1("abcdefghij");
- EXPECT_TRUE(shared_window.OnReceiveInputData(data1.size()));
- stream.PostInputFrame(new net::SpdyDataIR(kStreamId, data1));
- EXPECT_TRUE(output_queue.IsEmpty());
- EXPECT_EQ(65526, stream.current_input_window_size());
-
- // Inform the stream that we have consumed this data. However, we shouldn't
- // yet send a WINDOW_UPDATE frame for so small an amount, so the window size
- // should stay the same.
- stream.OnInputDataConsumed(10);
- EXPECT_TRUE(output_queue.IsEmpty());
- EXPECT_EQ(65526, stream.current_input_window_size());
-
- // Send the rest of the data. This should further reduce the input window
- // size.
- const std::string data2(9000, 'x');
- scoped_ptr<net::SpdyDataIR> data_frame(
- new net::SpdyDataIR(kStreamId, data2));
- data_frame->set_fin(true);
- EXPECT_TRUE(shared_window.OnReceiveInputData(data2.size()));
- stream.PostInputFrame(data_frame.release());
- EXPECT_TRUE(output_queue.IsEmpty());
- EXPECT_EQ(56526, stream.current_input_window_size());
-
- // Inform the stream that we have consumed a bit more of the data. However,
- // we still shouldn't yet send a WINDOW_UPDATE frame, and the window size
- // should still stay the same.
- stream.OnInputDataConsumed(10);
- EXPECT_TRUE(output_queue.IsEmpty());
- EXPECT_EQ(56526, stream.current_input_window_size());
-
- // Now say that we've consumed a whole bunch of data. At this point, we
- // should get a WINDOW_UPDATE frame for everything consumed so far, and the
- // window size should increase accordingly.
- stream.OnInputDataConsumed(8900);
- ExpectSessionWindowUpdate(&output_queue, 8920);
- ExpectWindowUpdate(&output_queue, 8920);
- EXPECT_TRUE(output_queue.IsEmpty());
- EXPECT_EQ(65446, stream.current_input_window_size());
-
- // Consume the last of the data. This is now just a little bit, so no need
- // for a WINDOW_UPDATE here.
- stream.OnInputDataConsumed(90);
- EXPECT_TRUE(output_queue.IsEmpty());
- EXPECT_EQ(65446, stream.current_input_window_size());
-}
-
-TEST(SpdyStreamTest, InputFlowControlError) {
- mod_spdy::SpdyFramePriorityQueue output_queue;
- MockSpdyServerPushInterface pusher;
- mod_spdy::SpdyStream stream(
- mod_spdy::spdy::SPDY_VERSION_3, kStreamId, kAssocStreamId,
- kInitServerPushDepth, kPriority, net::kSpdyStreamInitialWindowSize,
- &output_queue, NULL, &pusher);
-
- // Send a bunch of data. This should reduce the input window size.
- const std::string data1(1000, 'x');
- for (int i = 0; i < 65; ++i) {
- EXPECT_EQ(65536 - i * 1000, stream.current_input_window_size());
- stream.PostInputFrame(new net::SpdyDataIR(kStreamId, data1));
- EXPECT_TRUE(output_queue.IsEmpty());
- }
- EXPECT_EQ(536, stream.current_input_window_size());
- EXPECT_FALSE(stream.is_aborted());
-
- // Send a bit more data than there is room in the window size. This should
- // trigger a RST_STREAM.
- const std::string data2(537, 'y');
- stream.PostInputFrame(new net::SpdyDataIR(kStreamId, data2));
- ExpectRstStream(&output_queue, net::RST_STREAM_FLOW_CONTROL_ERROR);
- EXPECT_TRUE(output_queue.IsEmpty());
- EXPECT_TRUE(stream.is_aborted());
-}
-
-TEST(SpdyStreamTest, NoInputFlowControlInSpdy2) {
- mod_spdy::SpdyFramePriorityQueue output_queue;
- MockSpdyServerPushInterface pusher;
- mod_spdy::SpdyStream stream(
- mod_spdy::spdy::SPDY_VERSION_2, kStreamId, kAssocStreamId,
- kInitServerPushDepth, kPriority, net::kSpdyStreamInitialWindowSize,
- &output_queue, NULL, &pusher);
-
- // Send more data than will fit in the window size. However, we shouldn't
- // get an error, because this is SPDY/2 and there is no flow control.
- const std::string data1(1000, 'x');
- for (int i = 0; i < 70; ++i) {
- stream.PostInputFrame(new net::SpdyDataIR(kStreamId, data1));
- EXPECT_TRUE(output_queue.IsEmpty());
- EXPECT_FALSE(stream.is_aborted());
- }
-}
-
-} // namespace
+++ /dev/null
-// Copyright 2010 Google Inc. All Rights Reserved.
-//
-// 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.
-
-#include "mod_spdy/common/spdy_to_http_converter.h"
-
-#include "base/logging.h"
-#include "base/strings/string_number_conversions.h" // for Int64ToString
-#include "base/strings/string_piece.h"
-#include "mod_spdy/common/http_request_visitor_interface.h"
-#include "mod_spdy/common/protocol_util.h"
-#include "net/spdy/spdy_frame_builder.h"
-#include "net/spdy/spdy_framer.h"
-#include "net/spdy/spdy_protocol.h"
-
-namespace mod_spdy {
-
-namespace {
-
-// Generate an HTTP request line from the given SPDY header block by calling
-// the OnStatusLine() method of the given visitor, and return true. If there's
-// an error, this will return false without calling any methods on the visitor.
-bool GenerateRequestLine(spdy::SpdyVersion spdy_version,
- const net::SpdyHeaderBlock& block,
- HttpRequestVisitorInterface* visitor) {
- const bool spdy2 = spdy_version < spdy::SPDY_VERSION_3;
- net::SpdyHeaderBlock::const_iterator method = block.find(
- spdy2 ? spdy::kSpdy2Method : spdy::kSpdy3Method);
- net::SpdyHeaderBlock::const_iterator scheme = block.find(
- spdy2 ? spdy::kSpdy2Scheme : spdy::kSpdy3Scheme);
- net::SpdyHeaderBlock::const_iterator host = block.find(
- spdy2 ? http::kHost : spdy::kSpdy3Host);
- net::SpdyHeaderBlock::const_iterator path = block.find(
- spdy2 ? spdy::kSpdy2Url : spdy::kSpdy3Path);
- net::SpdyHeaderBlock::const_iterator version = block.find(
- spdy2 ? spdy::kSpdy2Version : spdy::kSpdy3Version);
-
- if (method == block.end() ||
- scheme == block.end() ||
- host == block.end() ||
- path == block.end() ||
- version == block.end()) {
- return false;
- }
-
- visitor->OnRequestLine(method->second, path->second, version->second);
- return true;
-}
-
-// Convert the given SPDY header into HTTP header(s) by splitting on NUL bytes
-// calling the specified method (either OnLeadingHeader or OnTrailingHeader) of
-// the given visitor.
-template <void(HttpRequestVisitorInterface::*OnHeader)(
- const base::StringPiece& key, const base::StringPiece& value)>
-void InsertHeader(const base::StringPiece key,
- const base::StringPiece value,
- HttpRequestVisitorInterface* visitor) {
- // Split header values on null characters, emitting a separate
- // header key-value pair for each substring. Logic from
- // net/spdy/spdy_session.cc
- for (size_t start = 0, end = 0; end != value.npos; start = end) {
- start = value.find_first_not_of('\0', start);
- if (start == value.npos) {
- break;
- }
- end = value.find('\0', start);
- (visitor->*OnHeader)(key, (end != value.npos ?
- value.substr(start, (end - start)) :
- value.substr(start)));
- }
-}
-
-} // namespace
-
-SpdyToHttpConverter::SpdyToHttpConverter(spdy::SpdyVersion spdy_version,
- HttpRequestVisitorInterface* visitor)
- : spdy_version_(spdy_version),
- visitor_(visitor),
- state_(NO_FRAMES_YET),
- use_chunking_(true),
- seen_accept_encoding_(false) {
- DCHECK_NE(spdy::SPDY_VERSION_NONE, spdy_version);
- CHECK(visitor);
-}
-
-SpdyToHttpConverter::~SpdyToHttpConverter() {}
-
-// static
-const char* SpdyToHttpConverter::StatusString(Status status) {
- switch (status) {
- case SPDY_CONVERTER_SUCCESS: return "SPDY_CONVERTER_SUCCESS";
- case FRAME_BEFORE_SYN_STREAM: return "FRAME_BEFORE_SYN_STREAM";
- case FRAME_AFTER_FIN: return "FRAME_AFTER_FIN";
- case EXTRA_SYN_STREAM: return "EXTRA_SYN_STREAM";
- case INVALID_HEADER_BLOCK: return "INVALID_HEADER_BLOCK";
- case BAD_REQUEST: return "BAD_REQUEST";
- default:
- LOG(DFATAL) << "Invalid status value: " << status;
- return "???";
- }
-}
-
-SpdyToHttpConverter::Status SpdyToHttpConverter::ConvertSynStreamFrame(
- const net::SpdySynStreamIR& frame) {
- if (state_ != NO_FRAMES_YET) {
- return EXTRA_SYN_STREAM;
- }
- state_ = RECEIVED_SYN_STREAM;
-
- const net::SpdyHeaderBlock& block = frame.name_value_block();
-
- if (!GenerateRequestLine(spdy_version(), block, visitor_)) {
- return BAD_REQUEST;
- }
-
- // Translate the headers to HTTP.
- GenerateLeadingHeaders(block);
-
- // If this is the last (i.e. only) frame on this stream, finish off the HTTP
- // request.
- if (frame.fin()) {
- FinishRequest();
- }
-
- return SPDY_CONVERTER_SUCCESS;
-}
-
-SpdyToHttpConverter::Status SpdyToHttpConverter::ConvertHeadersFrame(
- const net::SpdyHeadersIR& frame) {
- if (state_ == RECEIVED_FLAG_FIN) {
- return FRAME_AFTER_FIN;
- } else if (state_ == NO_FRAMES_YET) {
- return FRAME_BEFORE_SYN_STREAM;
- }
-
- // Parse the headers from the HEADERS frame. If there have already been any
- // data frames, then we need to save these headers for later and send them as
- // trailing headers. Otherwise, we can send them immediately.
- if (state_ == RECEIVED_DATA) {
- if (use_chunking_) {
- const net::SpdyHeaderBlock& block = frame.name_value_block();
- trailing_headers_.insert(block.begin(), block.end());
- } else {
- LOG(WARNING) << "Client sent trailing headers, "
- << "but we had to ignore them.";
- }
- } else {
- DCHECK(state_ == RECEIVED_SYN_STREAM);
- DCHECK(trailing_headers_.empty());
- // Translate the headers to HTTP.
- GenerateLeadingHeaders(frame.name_value_block());
- }
-
- // If this is the last frame on this stream, finish off the HTTP request.
- if (frame.fin()) {
- FinishRequest();
- }
-
- return SPDY_CONVERTER_SUCCESS;
-}
-
-SpdyToHttpConverter::Status SpdyToHttpConverter::ConvertDataFrame(
- const net::SpdyDataIR& frame) {
- if (state_ == RECEIVED_FLAG_FIN) {
- return FRAME_AFTER_FIN;
- } else if (state_ == NO_FRAMES_YET) {
- return FRAME_BEFORE_SYN_STREAM;
- }
-
- // If this is the first data frame in the stream, we need to close the HTTP
- // headers section (for streams where there are never any data frames, we
- // close the headers section in FinishRequest instead). Just before we do,
- // we may need to add some last-minute headers.
- if (state_ == RECEIVED_SYN_STREAM) {
- state_ = RECEIVED_DATA;
-
- // Unless we're not using chunked encoding (due to having received a
- // Content-Length headers), set Transfer-Encoding: chunked now.
- if (use_chunking_) {
- visitor_->OnLeadingHeader(http::kTransferEncoding, http::kChunked);
- }
-
- // Add any other last minute headers we need, and close the leading headers
- // section.
- EndOfLeadingHeaders();
- }
- DCHECK(state_ == RECEIVED_DATA);
-
- // Translate the SPDY data frame into an HTTP data chunk. However, we must
- // not emit a zero-length chunk, as that would be interpreted as the
- // data-chunks-complete marker.
- if (frame.data().size() > 0) {
- if (use_chunking_) {
- visitor_->OnDataChunk(frame.data());
- } else {
- visitor_->OnRawData(frame.data());
- }
- }
-
- // If this is the last frame on this stream, finish off the HTTP request.
- if (frame.fin()) {
- FinishRequest();
- }
-
- return SPDY_CONVERTER_SUCCESS;
-}
-
-// Convert the given SPDY header block (e.g. from a SYN_STREAM or HEADERS
-// frame) into HTTP headers by calling OnLeadingHeader on the given visitor.
-void SpdyToHttpConverter::GenerateLeadingHeaders(
- const net::SpdyHeaderBlock& block) {
- for (net::SpdyHeaderBlock::const_iterator it = block.begin();
- it != block.end(); ++it) {
- base::StringPiece key = it->first;
- const base::StringPiece value = it->second;
-
- // Skip SPDY-specific (i.e. non-HTTP) headers.
- if (spdy_version() < spdy::SPDY_VERSION_3) {
- if (key == spdy::kSpdy2Method || key == spdy::kSpdy2Scheme ||
- key == spdy::kSpdy2Url || key == spdy::kSpdy2Version) {
- continue;
- }
- } else {
- if (key == spdy::kSpdy3Method || key == spdy::kSpdy3Scheme ||
- key == spdy::kSpdy3Path || key == spdy::kSpdy3Version) {
- continue;
- }
- }
-
- // Skip headers that are ignored by SPDY.
- if (key == http::kConnection || key == http::kKeepAlive) {
- continue;
- }
-
- // If the client sent a Content-Length header, take note, so that we'll
- // know not to used chunked encoding.
- if (key == http::kContentLength) {
- use_chunking_ = false;
- }
-
- // The client shouldn't be sending us a Transfer-Encoding header; it's
- // pretty pointless over SPDY. If they do send one, just ignore it; we may
- // be overriding it later anyway.
- if (key == http::kTransferEncoding) {
- LOG(WARNING) << "Client sent \"transfer-encoding: " << value
- << "\" header over SPDY. Why would they do that?";
- continue;
- }
-
- // For SPDY v3 and later, we need to convert the SPDY ":host" header to an
- // HTTP "host" header.
- if (spdy_version() >= spdy::SPDY_VERSION_3 && key == spdy::kSpdy3Host) {
- key = http::kHost;
- }
-
- // Take note of whether the client has sent an explicit Accept-Encoding
- // header; if they never do, we'll insert on for them later on.
- if (key == http::kAcceptEncoding) {
- // TODO(mdsteele): Ideally, if the client sends something like
- // "Accept-Encoding: lzma", we should change it to "Accept-Encoding:
- // lzma, gzip". However, that's more work (we might need to parse the
- // syntax, to make sure we don't naively break it), and isn't
- // (currently) likely to come up in practice.
- seen_accept_encoding_ = true;
- }
-
- InsertHeader<&HttpRequestVisitorInterface::OnLeadingHeader>(
- key, value, visitor_);
- }
-}
-
-void SpdyToHttpConverter::EndOfLeadingHeaders() {
- // All SPDY clients should be assumed to support both gzip and deflate, even
- // if they don't say so (SPDY draft 2 section 3; SPDY draft 3 section 3.2.1),
- // and indeed some SPDY clients omit the Accept-Encoding header. So if we
- // didn't see that header yet, add one now so that Apache knows it can use
- // gzip/deflate.
- if (!seen_accept_encoding_) {
- visitor_->OnLeadingHeader(http::kAcceptEncoding, http::kGzipDeflate);
- }
-
- visitor_->OnLeadingHeadersComplete();
-}
-
-void SpdyToHttpConverter::FinishRequest() {
- if (state_ == RECEIVED_DATA) {
- if (use_chunking_) {
- // Indicate that there is no more data coming.
- visitor_->OnDataChunksComplete();
-
- // Append whatever trailing headers we've buffered, if any.
- if (!trailing_headers_.empty()) {
- for (net::SpdyHeaderBlock::const_iterator it =
- trailing_headers_.begin();
- it != trailing_headers_.end(); ++it) {
- InsertHeader<&HttpRequestVisitorInterface::OnTrailingHeader>(
- it->first, it->second, visitor_);
- }
- trailing_headers_.clear();
- visitor_->OnTrailingHeadersComplete();
- }
- } else {
- // We don't add to trailing_headers_ if we're in no-chunk mode (we simply
- // ignore trailing HEADERS frames), so trailing_headers_ should still be
- // empty.
- DCHECK(trailing_headers_.empty());
- }
- } else {
- DCHECK(state_ == RECEIVED_SYN_STREAM);
- // We only ever add to trailing_headers_ after receiving at least one data
- // frame, so if we haven't received any data frames then trailing_headers_
- // should still be empty.
- DCHECK(trailing_headers_.empty());
-
- // There were no data frames in this stream, so we haven't closed the
- // normal (non-trailing) headers yet (if there had been any data frames, we
- // would have closed the normal headers in ConvertDataFrame instead). Do
- // so now.
- EndOfLeadingHeaders();
- }
-
- // Indicate that this request is finished.
- visitor_->OnComplete();
- state_ = RECEIVED_FLAG_FIN;
-}
-
-} // namespace mod_spdy
+++ /dev/null
-// 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.
-
-#ifndef MOD_SPDY_SPDY_TO_HTTP_CONVERTER_H_
-#define MOD_SPDY_SPDY_TO_HTTP_CONVERTER_H_
-
-#include "base/basictypes.h"
-#include "mod_spdy/common/protocol_util.h"
-#include "net/spdy/spdy_protocol.h"
-
-namespace mod_spdy {
-
-class HttpRequestVisitorInterface;
-
-// Incrementally converts SPDY frames to HTTP streams, and passes the HTTP
-// stream to the specified HttpRequestVisitorInterface.
-class SpdyToHttpConverter {
- public:
- SpdyToHttpConverter(spdy::SpdyVersion spdy_version,
- HttpRequestVisitorInterface* visitor);
- ~SpdyToHttpConverter();
-
- enum Status {
- SPDY_CONVERTER_SUCCESS,
- FRAME_BEFORE_SYN_STREAM, // first frame was not a SYN_STREAM
- FRAME_AFTER_FIN, // received another frame after a FLAG_FIN
- EXTRA_SYN_STREAM, // received an additional SYN_STREAM after the first
- INVALID_HEADER_BLOCK, // the headers could not be parsed
- BAD_REQUEST // the headers didn't constitute a valid HTTP request
- };
-
- static const char* StatusString(Status status);
-
- // Return the SPDY version from which we are converting.
- spdy::SpdyVersion spdy_version() const { return spdy_version_; }
-
- // Convert the SPDY frame to HTTP and make appropriate calls to the visitor.
- // In some cases data may be buffered, but everything will get flushed out to
- // the visitor by the time the final frame (with FLAG_FIN set) is done.
- Status ConvertSynStreamFrame(const net::SpdySynStreamIR& frame);
- Status ConvertHeadersFrame(const net::SpdyHeadersIR& frame);
- Status ConvertDataFrame(const net::SpdyDataIR& frame);
-
-private:
- // Called to generate leading headers from a SYN_STREAM or HEADERS frame.
- void GenerateLeadingHeaders(const net::SpdyHeaderBlock& block);
- // Called when there are no more leading headers, because we've received
- // either data or a FLAG_FIN. This adds any last-minute needed headers
- // before closing the leading headers section.
- void EndOfLeadingHeaders();
- // Called when we see a FLAG_FIN. This terminates the request and appends
- // whatever trailing headers (if any) we have buffered.
- void FinishRequest();
-
- enum State {
- NO_FRAMES_YET, // We haven't seen any frames yet.
- RECEIVED_SYN_STREAM, // We've seen the SYN_STREAM, but no DATA yet.
- RECEIVED_DATA, // We've seen at least one DATA frame.
- RECEIVED_FLAG_FIN // We've seen the FLAG_FIN; no more frames allowed.
- };
-
- const spdy::SpdyVersion spdy_version_;
- HttpRequestVisitorInterface* const visitor_;
- net::SpdyHeaderBlock trailing_headers_;
- State state_;
- bool use_chunking_;
- bool seen_accept_encoding_;
-
- DISALLOW_COPY_AND_ASSIGN(SpdyToHttpConverter);
-};
-
-} // namespace mod_spdy
-
-#endif // MOD_SPDY_SPDY_TO_HTTP_CONVERTER_H_
+++ /dev/null
-// Copyright 2010 Google Inc. All Rights Reserved.
-//
-// 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.
-
-#include "mod_spdy/common/spdy_to_http_converter.h"
-
-#include "base/memory/scoped_ptr.h"
-#include "base/strings/string_piece.h"
-#include "mod_spdy/common/http_request_visitor_interface.h"
-#include "mod_spdy/common/protocol_util.h"
-#include "net/spdy/spdy_protocol.h"
-#include "testing/gmock/include/gmock/gmock.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace {
-
-using mod_spdy::SpdyToHttpConverter;
-using testing::Eq;
-using testing::InSequence;
-using testing::Sequence;
-
-const char* kMethod = "GET";
-const char* kScheme = "http";
-const char* kHost = "www.example.com";
-const char* kPath = "/";
-const char* kVersion = "HTTP/1.1";
-const char kMultiValue[] = "this\0is\0\0\0four\0\0headers";
-
-class MockHttpRequestVisitor: public mod_spdy::HttpRequestVisitorInterface {
- public:
- MOCK_METHOD3(OnRequestLine, void(const base::StringPiece&,
- const base::StringPiece&,
- const base::StringPiece&));
- MOCK_METHOD2(OnLeadingHeader, void(const base::StringPiece&,
- const base::StringPiece&));
- MOCK_METHOD0(OnLeadingHeadersComplete, void());
- MOCK_METHOD1(OnRawData, void(const base::StringPiece&));
- MOCK_METHOD1(OnDataChunk, void(const base::StringPiece&));
- MOCK_METHOD0(OnDataChunksComplete, void());
- MOCK_METHOD2(OnTrailingHeader, void(const base::StringPiece&,
- const base::StringPiece&));
- MOCK_METHOD0(OnTrailingHeadersComplete, void());
- MOCK_METHOD0(OnComplete, void());
-};
-
-class SpdyToHttpConverterTest :
- public testing::TestWithParam<mod_spdy::spdy::SpdyVersion> {
- public:
- SpdyToHttpConverterTest() : converter_(GetParam(), &visitor_) {}
-
- protected:
- void AddRequiredHeaders() {
- if (converter_.spdy_version() < mod_spdy::spdy::SPDY_VERSION_3) {
- headers_[mod_spdy::spdy::kSpdy2Method] = kMethod;
- headers_[mod_spdy::spdy::kSpdy2Scheme] = kScheme;
- headers_[mod_spdy::http::kHost] = kHost;
- headers_[mod_spdy::spdy::kSpdy2Url] = kPath;
- headers_[mod_spdy::spdy::kSpdy2Version] = kVersion;
- } else {
- headers_[mod_spdy::spdy::kSpdy3Method] = kMethod;
- headers_[mod_spdy::spdy::kSpdy3Scheme] = kScheme;
- headers_[mod_spdy::spdy::kSpdy3Host] = kHost;
- headers_[mod_spdy::spdy::kSpdy3Path] = kPath;
- headers_[mod_spdy::spdy::kSpdy3Version] = kVersion;
- }
- }
-
- MockHttpRequestVisitor visitor_;
- SpdyToHttpConverter converter_;
- net::SpdyHeaderBlock headers_;
-};
-
-TEST_P(SpdyToHttpConverterTest, MultiFrameStream) {
- // We expect all calls to happen in the specified order.
- InSequence seq;
-
- const net::SpdyStreamId stream_id = 1;
- AddRequiredHeaders();
-
- EXPECT_CALL(visitor_, OnRequestLine(Eq(kMethod), Eq(kPath), Eq(kVersion)));
- EXPECT_CALL(visitor_, OnLeadingHeader(Eq("host"), Eq(kHost)));
- EXPECT_CALL(visitor_, OnLeadingHeader(Eq("transfer-encoding"),
- Eq("chunked")));
- EXPECT_CALL(visitor_, OnLeadingHeader(Eq(mod_spdy::http::kAcceptEncoding),
- Eq(mod_spdy::http::kGzipDeflate)));
- EXPECT_CALL(visitor_, OnLeadingHeadersComplete());
- scoped_ptr<net::SpdySynStreamIR> syn_stream_frame(
- new net::SpdySynStreamIR(stream_id));
- syn_stream_frame->set_priority(1);
- syn_stream_frame->GetMutableNameValueBlock()->insert(
- headers_.begin(), headers_.end());
- EXPECT_EQ(SpdyToHttpConverter::SPDY_CONVERTER_SUCCESS,
- converter_.ConvertSynStreamFrame(*syn_stream_frame));
-
- EXPECT_CALL(visitor_, OnDataChunk(Eq(kHost)));
- scoped_ptr<net::SpdyDataIR> data_frame_1(
- new net::SpdyDataIR(stream_id, kHost));
- EXPECT_EQ(SpdyToHttpConverter::SPDY_CONVERTER_SUCCESS,
- converter_.ConvertDataFrame(*data_frame_1));
-
- // Should be no call to OnDataChunk for an empty data frame.
- scoped_ptr<net::SpdyDataIR> data_frame_empty(
- new net::SpdyDataIR(stream_id, ""));
- EXPECT_EQ(SpdyToHttpConverter::SPDY_CONVERTER_SUCCESS,
- converter_.ConvertDataFrame(*data_frame_empty));
-
- EXPECT_CALL(visitor_, OnDataChunk(Eq(kVersion)));
- EXPECT_CALL(visitor_, OnDataChunksComplete());
- EXPECT_CALL(visitor_, OnComplete());
- scoped_ptr<net::SpdyDataIR> data_frame_2(
- new net::SpdyDataIR(stream_id, kVersion));
- data_frame_2->set_fin(true);
- EXPECT_EQ(SpdyToHttpConverter::SPDY_CONVERTER_SUCCESS,
- converter_.ConvertDataFrame(*data_frame_2));
-}
-
-TEST_P(SpdyToHttpConverterTest, SynFrameWithHeaders) {
- AddRequiredHeaders();
- headers_["foo"] = "bar";
- headers_[mod_spdy::http::kAcceptEncoding] = "deflate, gzip, lzma";
-
- // Create a multi-valued header to verify that it's processed
- // properly.
- std::string multi_values(kMultiValue, sizeof(kMultiValue));
- headers_["multi"] = multi_values;
-
- // Also make sure "junk" headers get skipped over.
- headers_["empty"] = std::string("\0\0\0", 3);
-
- scoped_ptr<net::SpdySynStreamIR> syn_frame(new net::SpdySynStreamIR(1));
- syn_frame->set_priority(1);
- syn_frame->set_fin(true);
- syn_frame->GetMutableNameValueBlock()->insert(
- headers_.begin(), headers_.end());
-
- // We expect a call to OnRequestLine(), followed by several calls to
- // OnLeadingHeader() (the order of the calls to OnLeadingHeader() is
- // non-deterministic so we put each in its own Sequence), followed by a final
- // call to OnLeadingHeadersComplete() and OnComplete().
- Sequence s1, s2, s3, s4;
- EXPECT_CALL(visitor_,
- OnRequestLine(Eq(kMethod), Eq(kPath), Eq(kVersion)))
- .InSequence(s1, s2, s3, s4);
-
- EXPECT_CALL(visitor_, OnLeadingHeader(Eq("foo"), Eq("bar")))
- .InSequence(s1);
-
- EXPECT_CALL(visitor_, OnLeadingHeader(Eq(mod_spdy::http::kAcceptEncoding),
- Eq("deflate, gzip, lzma")))
- .InSequence(s2);
-
- EXPECT_CALL(visitor_, OnLeadingHeader(Eq("multi"), Eq("this")))
- .InSequence(s3);
- EXPECT_CALL(visitor_, OnLeadingHeader(Eq("multi"), Eq("is")))
- .InSequence(s3);
- EXPECT_CALL(visitor_, OnLeadingHeader(Eq("multi"), Eq("four")))
- .InSequence(s3);
- EXPECT_CALL(visitor_, OnLeadingHeader(Eq("multi"), Eq("headers")))
- .InSequence(s3);
-
- EXPECT_CALL(visitor_, OnLeadingHeader(Eq("host"), Eq(kHost)))
- .InSequence(s4);
-
- EXPECT_CALL(visitor_, OnLeadingHeadersComplete()).InSequence(s1, s2, s3, s4);
-
- EXPECT_CALL(visitor_, OnComplete()).InSequence(s1, s2, s3, s4);
-
- // Trigger the calls to the mock object by passing the frame to the
- // converter.
- EXPECT_EQ(SpdyToHttpConverter::SPDY_CONVERTER_SUCCESS,
- converter_.ConvertSynStreamFrame(*syn_frame));
-}
-
-TEST_P(SpdyToHttpConverterTest, TrailingHeaders) {
- // First, send a SYN_STREAM frame without FLAG_FIN set. We should get the
- // headers out that we sent, but no call yet to OnLeadingHeadersComplete,
- // because there might still be a HEADERS frame.
- AddRequiredHeaders();
- headers_["foo"] = "bar";
- scoped_ptr<net::SpdySynStreamIR> syn_frame(new net::SpdySynStreamIR(1));
- syn_frame->set_priority(1);
- syn_frame->GetMutableNameValueBlock()->insert(
- headers_.begin(), headers_.end());
-
- Sequence s1, s2;
- EXPECT_CALL(visitor_, OnRequestLine(Eq(kMethod), Eq(kPath), Eq(kVersion)))
- .InSequence(s1, s2);
- EXPECT_CALL(visitor_, OnLeadingHeader(Eq("foo"), Eq("bar")))
- .InSequence(s1);
- EXPECT_CALL(visitor_, OnLeadingHeader(Eq("host"), Eq(kHost)))
- .InSequence(s2);
-
- EXPECT_EQ(SpdyToHttpConverter::SPDY_CONVERTER_SUCCESS,
- converter_.ConvertSynStreamFrame(*syn_frame));
-
- // Next, send a DATA frame. This should trigger the accept-encoding and
- // transfer-encoding headers, and the end of the leading headers (along with
- // the data itself, of course).
- scoped_ptr<net::SpdyDataIR> data_frame(
- new net::SpdyDataIR(1, "Hello, world!\n"));
-
- EXPECT_CALL(visitor_, OnLeadingHeader(Eq("transfer-encoding"),
- Eq("chunked"))).InSequence(s1, s2);
- EXPECT_CALL(visitor_, OnLeadingHeader(
- Eq(mod_spdy::http::kAcceptEncoding),
- Eq(mod_spdy::http::kGzipDeflate))).InSequence(s1, s2);
- EXPECT_CALL(visitor_, OnLeadingHeadersComplete()).InSequence(s1, s2);
- EXPECT_CALL(visitor_, OnDataChunk(Eq("Hello, world!\n"))).InSequence(s1, s2);
-
- EXPECT_EQ(SpdyToHttpConverter::SPDY_CONVERTER_SUCCESS,
- converter_.ConvertDataFrame(*data_frame));
-
- // Finally, send a HEADERS frame with FLAG_FIN set. Since this is the end of
- // the stream, we should get out a trailing header and the HTTP stream should
- // be closed.
- headers_.clear();
- headers_["quux"] = "baz";
- scoped_ptr<net::SpdyHeadersIR> headers_frame(new net::SpdyHeadersIR(1));
- headers_frame->set_fin(true);
- headers_frame->GetMutableNameValueBlock()->insert(
- headers_.begin(), headers_.end());
-
- EXPECT_CALL(visitor_, OnDataChunksComplete()).InSequence(s1, s2);
- EXPECT_CALL(visitor_, OnTrailingHeader(Eq("quux"), Eq("baz")))
- .InSequence(s1, s2);
- EXPECT_CALL(visitor_, OnTrailingHeadersComplete()).InSequence(s1, s2);
- EXPECT_CALL(visitor_, OnComplete()).InSequence(s1, s2);
-
- EXPECT_EQ(SpdyToHttpConverter::SPDY_CONVERTER_SUCCESS,
- converter_.ConvertHeadersFrame(*headers_frame));
-}
-
-TEST_P(SpdyToHttpConverterTest, WithContentLength) {
- // First, send a SYN_STREAM frame without FLAG_FIN set. We should get the
- // headers out that we sent, but no call yet to OnLeadingHeadersComplete,
- // because there might still be a HEADERS frame.
- AddRequiredHeaders();
- headers_["content-length"] = "11";
- scoped_ptr<net::SpdySynStreamIR> syn_frame(new net::SpdySynStreamIR(1));
- syn_frame->set_priority(1);
- syn_frame->GetMutableNameValueBlock()->insert(
- headers_.begin(), headers_.end());
-
- Sequence s1, s2;
- EXPECT_CALL(visitor_, OnRequestLine(Eq(kMethod), Eq(kPath), Eq(kVersion)))
- .InSequence(s1, s2);
- EXPECT_CALL(visitor_, OnLeadingHeader(Eq("content-length"), Eq("11")))
- .InSequence(s1);
- EXPECT_CALL(visitor_, OnLeadingHeader(Eq("host"), Eq(kHost)))
- .InSequence(s2);
-
- EXPECT_EQ(SpdyToHttpConverter::SPDY_CONVERTER_SUCCESS,
- converter_.ConvertSynStreamFrame(*syn_frame));
-
- // Next, send a DATA frame. This should trigger the end of the leading
- // headers (along with the data itself, of course), but because we sent a
- // content-length, the data should not be chunked.
- scoped_ptr<net::SpdyDataIR> data_frame(
- new net::SpdyDataIR(1, "foobar=quux"));
-
- EXPECT_CALL(visitor_, OnLeadingHeader(
- Eq(mod_spdy::http::kAcceptEncoding),
- Eq(mod_spdy::http::kGzipDeflate))).InSequence(s1, s2);
- EXPECT_CALL(visitor_, OnLeadingHeadersComplete()).InSequence(s1, s2);
- EXPECT_CALL(visitor_, OnRawData(Eq("foobar=quux"))).InSequence(s1, s2);
-
- EXPECT_EQ(SpdyToHttpConverter::SPDY_CONVERTER_SUCCESS,
- converter_.ConvertDataFrame(*data_frame));
-
- // Finally, send a HEADERS frame with FLAG_FIN set. Since we're not chunking
- // this stream, the trailing headers should be ignored.
- headers_.clear();
- headers_["x-metadata"] = "baz";
- scoped_ptr<net::SpdyHeadersIR> headers_frame(new net::SpdyHeadersIR(1));
- headers_frame->set_fin(true);
- headers_frame->GetMutableNameValueBlock()->insert(
- headers_.begin(), headers_.end());
-
- EXPECT_CALL(visitor_, OnComplete()).InSequence(s1, s2);
-
- EXPECT_EQ(SpdyToHttpConverter::SPDY_CONVERTER_SUCCESS,
- converter_.ConvertHeadersFrame(*headers_frame));
-}
-
-TEST_P(SpdyToHttpConverterTest, DoubleSynStreamFrame) {
- AddRequiredHeaders();
- scoped_ptr<net::SpdySynStreamIR> syn_frame(
- new net::SpdySynStreamIR(1));
- syn_frame->set_priority(1);
- syn_frame->set_fin(true);
- syn_frame->GetMutableNameValueBlock()->insert(
- headers_.begin(), headers_.end());
-
- InSequence seq;
- EXPECT_CALL(visitor_, OnRequestLine(Eq(kMethod), Eq(kPath), Eq(kVersion)));
- EXPECT_CALL(visitor_, OnLeadingHeader(Eq("host"), Eq(kHost)));
- EXPECT_CALL(visitor_, OnLeadingHeader(
- Eq(mod_spdy::http::kAcceptEncoding),
- Eq(mod_spdy::http::kGzipDeflate)));
- EXPECT_CALL(visitor_, OnLeadingHeadersComplete());
- EXPECT_CALL(visitor_, OnComplete());
-
- EXPECT_EQ(SpdyToHttpConverter::SPDY_CONVERTER_SUCCESS,
- converter_.ConvertSynStreamFrame(*syn_frame));
- EXPECT_EQ(SpdyToHttpConverter::EXTRA_SYN_STREAM,
- converter_.ConvertSynStreamFrame(*syn_frame));
-}
-
-TEST_P(SpdyToHttpConverterTest, HeadersFrameBeforeSynStreamFrame) {
- headers_["x-foo"] = "bar";
- scoped_ptr<net::SpdyHeadersIR> headers_frame(new net::SpdyHeadersIR(1));
- headers_frame->GetMutableNameValueBlock()->insert(
- headers_.begin(), headers_.end());
- EXPECT_EQ(SpdyToHttpConverter::FRAME_BEFORE_SYN_STREAM,
- converter_.ConvertHeadersFrame(*headers_frame));
-}
-
-TEST_P(SpdyToHttpConverterTest, DataFrameBeforeSynStreamFrame) {
- scoped_ptr<net::SpdyDataIR> data_frame(
- new net::SpdyDataIR(1, kHost));
- EXPECT_EQ(SpdyToHttpConverter::FRAME_BEFORE_SYN_STREAM,
- converter_.ConvertDataFrame(*data_frame));
-}
-
-// Run each test over both SPDY v2 and SPDY v3.
-INSTANTIATE_TEST_CASE_P(Spdy2And3, SpdyToHttpConverterTest, testing::Values(
- mod_spdy::spdy::SPDY_VERSION_2, mod_spdy::spdy::SPDY_VERSION_3,
- mod_spdy::spdy::SPDY_VERSION_3_1));
-
-} // namespace
+++ /dev/null
-// Copyright 2012 Google Inc. All Rights Reserved.
-//
-// 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.
-
-#include "mod_spdy/common/testing/async_task_runner.h"
-
-#include "base/basictypes.h"
-#include "base/logging.h"
-#include "mod_spdy/common/executor.h"
-#include "mod_spdy/common/testing/notification.h"
-#include "mod_spdy/common/thread_pool.h"
-#include "net/instaweb/util/public/function.h"
-
-namespace mod_spdy {
-
-namespace testing {
-
-namespace {
-
-class TaskFunction : public net_instaweb::Function {
- public:
- TaskFunction(AsyncTaskRunner::Task* task, Notification* done)
- : task_(task), done_(done) {}
- virtual ~TaskFunction() {}
- protected:
- // net_instaweb::Function methods:
- virtual void Run() {
- task_->Run();
- done_->Set();
- }
- virtual void Cancel() {}
- private:
- AsyncTaskRunner::Task* const task_;
- Notification* const done_;
- DISALLOW_COPY_AND_ASSIGN(TaskFunction);
-};
-
-} // namespace
-
-AsyncTaskRunner::Task::Task() {}
-
-AsyncTaskRunner::Task::~Task() {}
-
-AsyncTaskRunner::AsyncTaskRunner(Task* task)
- : task_(task), thread_pool_(1, 1) {}
-
-AsyncTaskRunner::~AsyncTaskRunner() {}
-
-bool AsyncTaskRunner::Start() {
- // Make sure we haven't started yet.
- DCHECK(executor_ == NULL);
-
- if (!thread_pool_.Start()) {
- return false;
- }
- executor_.reset(thread_pool_.NewExecutor());
- executor_->AddTask(new TaskFunction(task_.get(), ¬ification_), 0);
- return true;
-}
-
-} // namespace testing
-
-} // namespace mod_spdy
+++ /dev/null
-// Copyright 2012 Google Inc. All Rights Reserved.
-//
-// 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.
-
-#ifndef MOD_SPDY_COMMON_TESTING_ASYNC_TASK_RUNNER_H_
-#define MOD_SPDY_COMMON_TESTING_ASYNC_TASK_RUNNER_H_
-
-#include "base/basictypes.h"
-#include "base/memory/scoped_ptr.h"
-#include "mod_spdy/common/testing/notification.h"
-#include "mod_spdy/common/thread_pool.h"
-
-namespace mod_spdy {
-
-class Executor;
-
-namespace testing {
-
-// An AsyncTaskRunner is a testing utility class to make it very easy to run a
-// single piece of code concurrently, in order to write tests for concurrency
-// features of other classes. Standard usage is:
-//
-// class FooTask : public AsyncTaskRunner::Task { ... };
-//
-// AsyncTaskRunner runner(new FooTask(...));
-// ASSERT_TRUE(runner.Start());
-// ... stuff goes here ...
-// runner.notification()->ExpectSetWithin(...); // or whatever
-//
-// Note that the implementation of this class is not particularly efficient,
-// and is suitable only for testing purposes.
-class AsyncTaskRunner {
- public:
- // A closure to be run by the AsyncTaskRunner. If we had a simple closure
- // class available already, we'd use that instead.
- class Task {
- public:
- Task();
- virtual ~Task();
- virtual void Run() = 0;
- private:
- DISALLOW_COPY_AND_ASSIGN(Task);
- };
-
- // Construct an AsyncTaskRunner that will run the given task once started.
- // The AsyncTaskRunner gains ownership of the task.
- explicit AsyncTaskRunner(Task* task);
-
- ~AsyncTaskRunner();
-
- // Start the task running and return true. If this fails, it returns false,
- // and the test should be aborted.
- bool Start();
-
- // Get the notification that will be set when the task completes.
- Notification* notification() { return ¬ification_; }
-
- private:
- const scoped_ptr<Task> task_;
- mod_spdy::ThreadPool thread_pool_;
- scoped_ptr<Executor> executor_;
- Notification notification_;
-
- DISALLOW_COPY_AND_ASSIGN(AsyncTaskRunner);
-};
-
-} // namespace testing
-
-} // namespace mod_spdy
-
-#endif // MOD_SPDY_COMMON_TESTING_ASYNC_TASK_RUNNER_H_
+++ /dev/null
-// Copyright 2012 Google Inc. All Rights Reserved.
-//
-// 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.
-
-#include "mod_spdy/common/testing/notification.h"
-
-#include "base/time/time.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace mod_spdy {
-
-namespace testing {
-
-Notification::Notification() : condvar_(&lock_), is_set_(false) {}
-
-Notification::~Notification() {
- Set();
-}
-
-void Notification::Set() {
- base::AutoLock autolock(lock_);
- is_set_ = true;
- condvar_.Broadcast();
-}
-
-void Notification::Wait() {
- base::AutoLock autolock(lock_);
- while (!is_set_) {
- condvar_.Wait();
- }
-}
-
-void Notification::ExpectNotSet() {
- base::AutoLock autolock(lock_);
- EXPECT_FALSE(is_set_);
-}
-
-void Notification::ExpectSetWithin(const base::TimeDelta& timeout) {
- base::AutoLock autolock(lock_);
- const base::TimeDelta zero = base::TimeDelta();
- base::TimeDelta time_remaining = timeout;
- while (time_remaining > zero && !is_set_) {
- const base::TimeTicks start = base::TimeTicks::HighResNow();
- condvar_.TimedWait(time_remaining);
- time_remaining -= base::TimeTicks::HighResNow() - start;
- }
- EXPECT_TRUE(is_set_);
-}
-
-void Notification::ExpectSetWithinMillis(int millis) {
- ExpectSetWithin(base::TimeDelta::FromMilliseconds(millis));
-}
-
-} // namespace testing
-
-} // namespace mod_spdy
+++ /dev/null
-// Copyright 2012 Google Inc. All Rights Reserved.
-//
-// 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.
-
-#ifndef MOD_SPDY_COMMON_TESTING_NOTIFICATION_H_
-#define MOD_SPDY_COMMON_TESTING_NOTIFICATION_H_
-
-#include "base/basictypes.h"
-#include "base/synchronization/condition_variable.h"
-#include "base/synchronization/lock.h"
-
-namespace base { class TimeDelta; }
-
-namespace mod_spdy {
-
-namespace testing {
-
-// A Notification allows one thread to Wait() until another thread calls Set()
-// at least once. In order to help avoid deadlock, Set() is also called by the
-// destructor.
-class Notification {
- public:
- Notification();
- ~Notification();
-
- // Set the notification.
- void Set();
- // Block until the notification is set.
- void Wait();
- // In a unit test, expect that the notification has not yet been set.
- void ExpectNotSet();
- // In a unit test, expect that the notification is currently set, or becomes
- // set by another thread within the give time delta.
- void ExpectSetWithin(const base::TimeDelta& delay);
- void ExpectSetWithinMillis(int millis);
-
- private:
- base::Lock lock_;
- base::ConditionVariable condvar_;
- bool is_set_;
-
- DISALLOW_COPY_AND_ASSIGN(Notification);
-};
-
-} // namespace testing
-
-} // namespace mod_spdy
-
-#endif // MOD_SPDY_COMMON_TESTING_NOTIFICATION_H_
+++ /dev/null
-// Copyright 2012 Google Inc. All Rights Reserved.
-//
-// 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.
-
-#include "mod_spdy/common/testing/spdy_frame_matchers.h"
-
-#include <iostream>
-#include <string>
-
-#include "base/basictypes.h"
-#include "base/strings/stringprintf.h"
-#include "mod_spdy/common/protocol_util.h"
-#include "net/spdy/spdy_framer.h"
-#include "net/spdy/spdy_protocol.h"
-#include "testing/gmock/include/gmock/gmock.h"
-
-namespace {
-
-void AppendHeadersString(const net::SpdyNameValueBlock& headers,
- std::string* out) {
- out->append("{ ");
- bool comma = false;
- for (net::SpdyNameValueBlock::const_iterator iter = headers.begin();
- iter != headers.end(); ++iter) {
- if (comma) {
- out->append(", ");
- }
- base::StringAppendF(out, "'%s': '%s'", iter->first.c_str(),
- iter->second.c_str());
- comma = true;
- }
- out->append(" }");
-}
-
-class FrameToStringVisitor : public net::SpdyFrameVisitor {
- public:
- explicit FrameToStringVisitor(std::string* out)
- : out_(out) {
- CHECK(out_);
- }
- virtual ~FrameToStringVisitor() {}
-
- virtual void VisitSynStream(const net::SpdySynStreamIR& syn_stream) {
- // TODO(mdsteele): include other fields
- base::StringAppendF(
- out_, "SYN_STREAM(%u p%u%s%s)",
- static_cast<unsigned>(syn_stream.stream_id()),
- static_cast<unsigned>(syn_stream.priority()),
- (syn_stream.fin() ? " fin" : ""),
- (syn_stream.unidirectional() ? " unidirectional" : ""));
- AppendHeadersString(syn_stream.name_value_block(), out_);
- }
- virtual void VisitSynReply(const net::SpdySynReplyIR& syn_reply) {
- base::StringAppendF(
- out_, "SYN_REPLY(%u%s)",
- static_cast<unsigned>(syn_reply.stream_id()),
- (syn_reply.fin() ? " fin" : ""));
- AppendHeadersString(syn_reply.name_value_block(), out_);
- }
- virtual void VisitRstStream(const net::SpdyRstStreamIR& rst_stream) {
- base::StringAppendF(
- out_, "RST_STREAM(%u %s)",
- static_cast<unsigned>(rst_stream.stream_id()),
- mod_spdy::RstStreamStatusCodeToString(rst_stream.status()));
- }
- virtual void VisitSettings(const net::SpdySettingsIR& settings) {
- base::StringAppendF(
- out_, "SETTINGS(%s",
- (settings.clear_settings() ? "clear " : ""));
- bool comma = false;
- for (net::SpdySettingsIR::ValueMap::const_iterator iter =
- settings.values().begin(), end = settings.values().end();
- iter != end; ++iter) {
- if (comma) {
- out_->append(", ");
- }
- base::StringAppendF(
- out_, "%s%s%s: %d",
- (iter->second.persist_value ? "persist " : ""),
- (iter->second.persisted ? "persisted " : ""),
- mod_spdy::SettingsIdToString(iter->first),
- static_cast<int>(iter->second.value));
- }
- out_->append(")");
- }
- virtual void VisitPing(const net::SpdyPingIR& ping) {
- base::StringAppendF(
- out_, "PING(%u)", static_cast<unsigned>(ping.id()));
- }
- virtual void VisitGoAway(const net::SpdyGoAwayIR& goaway) {
- base::StringAppendF(
- out_, "GOAWAY(%u %s)",
- static_cast<unsigned>(goaway.last_good_stream_id()),
- mod_spdy::GoAwayStatusCodeToString(goaway.status()));
- }
- virtual void VisitHeaders(const net::SpdyHeadersIR& headers) {
- base::StringAppendF(
- out_, "HEADERS(%u%s)", static_cast<unsigned>(headers.stream_id()),
- (headers.fin() ? " fin" : ""));
- AppendHeadersString(headers.name_value_block(), out_);
- }
- virtual void VisitWindowUpdate(const net::SpdyWindowUpdateIR& window) {
- base::StringAppendF(
- out_, "WINDOW_UPDATE(%u %+d)",
- static_cast<unsigned>(window.stream_id()),
- static_cast<int>(window.delta()));
- }
- virtual void VisitCredential(const net::SpdyCredentialIR& credential) {
- // TODO(mdsteele): include other fields
- base::StringAppendF(
- out_, "CREDENTIAL(%d)", static_cast<int>(credential.slot()));
- }
- virtual void VisitBlocked(const net::SpdyBlockedIR& blocked) {
- base::StringAppendF(
- out_, "BLOCKED(%u)", static_cast<unsigned>(blocked.stream_id()));
- }
- virtual void VisitPushPromise(const net::SpdyPushPromiseIR& push_promise) {
- base::StringAppendF(
- out_, "PUSH_PROMISE(%u, %u)",
- static_cast<unsigned>(push_promise.stream_id()),
- static_cast<unsigned>(push_promise.promised_stream_id()));
- }
- virtual void VisitData(const net::SpdyDataIR& data) {
- base::StringAppendF(
- out_, "DATA(%u%s \"", static_cast<unsigned>(data.stream_id()),
- (data.fin() ? " fin" : ""));
- out_->append(data.data().data(), data.data().size());
- out_->append("\")");
- }
-
- private:
- std::string* out_;
-
- DISALLOW_COPY_AND_ASSIGN(FrameToStringVisitor);
-};
-
-void AppendSpdyFrameToString(const net::SpdyFrameIR& frame, std::string* out) {
- FrameToStringVisitor visitor(out);
- frame.Visit(&visitor);
-}
-
-class IsEquivalentFrameMatcher :
- public ::testing::MatcherInterface<const net::SpdyFrameIR&> {
- public:
- explicit IsEquivalentFrameMatcher(const net::SpdyFrameIR& frame);
- virtual ~IsEquivalentFrameMatcher();
- virtual bool MatchAndExplain(const net::SpdyFrameIR& frame,
- ::testing::MatchResultListener* listener) const;
- virtual void DescribeTo(std::ostream* out) const;
- virtual void DescribeNegationTo(std::ostream* out) const;
-
- private:
- std::string expected_;
-
- DISALLOW_COPY_AND_ASSIGN(IsEquivalentFrameMatcher);
-};
-
-IsEquivalentFrameMatcher::IsEquivalentFrameMatcher(
- const net::SpdyFrameIR& frame) {
- AppendSpdyFrameToString(frame, &expected_);
-}
-
-IsEquivalentFrameMatcher::~IsEquivalentFrameMatcher() {}
-
-bool IsEquivalentFrameMatcher::MatchAndExplain(
- const net::SpdyFrameIR& frame,
- ::testing::MatchResultListener* listener) const {
- std::string actual;
- AppendSpdyFrameToString(frame, &actual);
- if (actual != expected_) {
- *listener << "is a " << actual << " frame";
- return false;
- }
- return true;
-}
-
-void IsEquivalentFrameMatcher::DescribeTo(std::ostream* out) const {
- *out << "is a " << expected_ << " frame";
-}
-
-void IsEquivalentFrameMatcher::DescribeNegationTo(std::ostream* out) const {
- *out << "isn't a " << expected_ << " frame";
-}
-
-} // namespace
-
-namespace mod_spdy {
-
-namespace testing {
-
-::testing::Matcher<const net::SpdyFrameIR&> IsSynStream(
- net::SpdyStreamId stream_id, net::SpdyStreamId assoc_stream_id,
- net::SpdyPriority priority, bool fin, bool unidirectional,
- const net::SpdyNameValueBlock& headers) {
- net::SpdySynStreamIR frame(stream_id);
- frame.set_associated_to_stream_id(assoc_stream_id);
- frame.set_priority(priority);
- frame.set_fin(fin);
- frame.set_unidirectional(unidirectional);
- frame.GetMutableNameValueBlock()->insert(headers.begin(), headers.end());
- return ::testing::MakeMatcher(new IsEquivalentFrameMatcher(frame));
-}
-
-::testing::Matcher<const net::SpdyFrameIR&> IsSynReply(
- net::SpdyStreamId stream_id, bool fin,
- const net::SpdyNameValueBlock& headers) {
- net::SpdySynReplyIR frame(stream_id);
- frame.set_fin(fin);
- frame.GetMutableNameValueBlock()->insert(headers.begin(), headers.end());
- return ::testing::MakeMatcher(new IsEquivalentFrameMatcher(frame));
-}
-
-::testing::Matcher<const net::SpdyFrameIR&> IsRstStream(
- net::SpdyStreamId stream_id, net::SpdyRstStreamStatus status) {
- net::SpdyRstStreamIR frame(stream_id, status);
- return ::testing::MakeMatcher(new IsEquivalentFrameMatcher(frame));
-}
-
-::testing::Matcher<const net::SpdyFrameIR&> IsSettings(
- net::SpdySettingsIds id, int32 value) {
- net::SpdySettingsIR frame;
- frame.AddSetting(id, false, false, value);
- return ::testing::MakeMatcher(new IsEquivalentFrameMatcher(frame));
-}
-
-::testing::Matcher<const net::SpdyFrameIR&> IsPing(net::SpdyPingId ping_id) {
- net::SpdyPingIR frame(ping_id);
- return ::testing::MakeMatcher(new IsEquivalentFrameMatcher(frame));
-}
-
-::testing::Matcher<const net::SpdyFrameIR&> IsGoAway(
- net::SpdyStreamId last_good_stream_id, net::SpdyGoAwayStatus status) {
- net::SpdyGoAwayIR frame(last_good_stream_id, status);
- return ::testing::MakeMatcher(new IsEquivalentFrameMatcher(frame));
-}
-
-::testing::Matcher<const net::SpdyFrameIR&> IsHeaders(
- net::SpdyStreamId stream_id, bool fin,
- const net::SpdyNameValueBlock& headers) {
- net::SpdyHeadersIR frame(stream_id);
- frame.set_fin(fin);
- frame.GetMutableNameValueBlock()->insert(headers.begin(), headers.end());
- return ::testing::MakeMatcher(new IsEquivalentFrameMatcher(frame));
-}
-
-::testing::Matcher<const net::SpdyFrameIR&> IsWindowUpdate(
- net::SpdyStreamId stream_id, uint32 delta) {
- net::SpdyWindowUpdateIR frame(stream_id, delta);
- return ::testing::MakeMatcher(new IsEquivalentFrameMatcher(frame));
-}
-
-::testing::Matcher<const net::SpdyFrameIR&> IsDataFrame(
- net::SpdyStreamId stream_id, bool fin, base::StringPiece payload) {
- net::SpdyDataIR frame(stream_id, payload);
- frame.set_fin(fin);
- return ::testing::MakeMatcher(new IsEquivalentFrameMatcher(frame));
-}
-
-} // namespace testing
-
-} // namespace mod_spdy
+++ /dev/null
-// Copyright 2012 Google Inc. All Rights Reserved.
-//
-// 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.
-
-#ifndef MOD_SPDY_TESTING_SPDY_FRAME_MATCHERS_H_
-#define MOD_SPDY_TESTING_SPDY_FRAME_MATCHERS_H_
-
-#include "base/basictypes.h"
-#include "base/strings/string_piece.h"
-#include "net/spdy/spdy_protocol.h"
-#include "testing/gmock/include/gmock/gmock.h"
-
-namespace mod_spdy {
-
-namespace testing {
-
-// Make a matcher that requires the argument to be a SYN_STREAM frame with the
-// given stream ID, associated stream ID, priority, flag_fin,
-// flag_unidirectional, and headers.
-::testing::Matcher<const net::SpdyFrameIR&> IsSynStream(
- net::SpdyStreamId stream_id, net::SpdyStreamId assoc_stream_id,
- net::SpdyPriority priority, bool fin, bool unidirectional,
- const net::SpdyNameValueBlock& headers);
-
-// Make a matcher that requires the argument to be a SYN_REPLY frame with the
-// given stream ID, flag_fin, and headers.
-::testing::Matcher<const net::SpdyFrameIR&> IsSynReply(
- net::SpdyStreamId stream_id, bool fin,
- const net::SpdyNameValueBlock& headers);
-
-// Make a matcher that requires the argument to be a RST_STREAM frame with the
-// given stream ID and status code.
-::testing::Matcher<const net::SpdyFrameIR&> IsRstStream(
- net::SpdyStreamId stream_id, net::SpdyRstStreamStatus status);
-
-// Make a matcher that requires the argument to be a SETTINGS frame with the
-// given setting.
-::testing::Matcher<const net::SpdyFrameIR&> IsSettings(
- net::SpdySettingsIds id, int32 value);
-
-// Make a matcher that requires the argument to be a PING frame with the
-// given ID.
-::testing::Matcher<const net::SpdyFrameIR&> IsPing(net::SpdyPingId ping_id);
-
-// Make a matcher that requires the argument to be a GOAWAY frame with the
-// given last-good-stream-ID and status code.
-::testing::Matcher<const net::SpdyFrameIR&> IsGoAway(
- net::SpdyStreamId last_good_stream_id, net::SpdyGoAwayStatus status);
-
-// Make a matcher that requires the argument to be a HEADERS frame with the
-// given stream ID, flag_fin, and headers.
-::testing::Matcher<const net::SpdyFrameIR&> IsHeaders(
- net::SpdyStreamId stream_id, bool fin,
- const net::SpdyNameValueBlock& headers);
-
-// Make a matcher that requires the argument to be a WINDOW_UPDATE frame with
-// the given window-size-delta.
-::testing::Matcher<const net::SpdyFrameIR&> IsWindowUpdate(
- net::SpdyStreamId stream_id, uint32 delta);
-
-// Make a matcher that requires the argument to be a DATA frame.
-::testing::Matcher<const net::SpdyFrameIR&> IsDataFrame(
- net::SpdyStreamId stream_id, bool fin, base::StringPiece payload);
-
-} // namespace testing
-
-} // namespace mod_spdy
-
-#endif // MOD_SPDY_TESTING_SPDY_FRAME_MATCHERS_H_
+++ /dev/null
-// 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.
-
-#include "mod_spdy/common/thread_pool.h"
-
-#include <map>
-#include <set>
-#include <vector>
-
-#include "base/basictypes.h"
-#include "base/memory/scoped_ptr.h"
-#include "base/synchronization/condition_variable.h"
-#include "base/synchronization/lock.h"
-#include "base/threading/platform_thread.h"
-#include "base/time/time.h"
-#include "mod_spdy/common/executor.h"
-#include "net/instaweb/util/public/function.h"
-#include "net/spdy/spdy_protocol.h"
-
-namespace {
-
-// Shut down a worker thread after it has been idle for this many seconds:
-const int64 kDefaultMaxWorkerIdleSeconds = 60;
-
-} // namespace
-
-namespace mod_spdy {
-
-// An executor that uses the ThreadPool to execute tasks. Returned by
-// ThreadPool::NewExecutor.
-class ThreadPool::ThreadPoolExecutor : public Executor {
- public:
- explicit ThreadPoolExecutor(ThreadPool* master)
- : master_(master),
- stopping_condvar_(&master_->lock_),
- stopped_(false) {}
- virtual ~ThreadPoolExecutor() { Stop(); }
-
- // Executor methods:
- virtual void AddTask(net_instaweb::Function* task,
- net::SpdyPriority priority);
- virtual void Stop();
-
- private:
- friend class ThreadPool;
- ThreadPool* const master_;
- base::ConditionVariable stopping_condvar_;
- bool stopped_; // protected by master_->lock_
-
- DISALLOW_COPY_AND_ASSIGN(ThreadPoolExecutor);
-};
-
-// Add a task to the executor; if the executor has already been stopped, just
-// cancel the task immediately.
-void ThreadPool::ThreadPoolExecutor::AddTask(net_instaweb::Function* task,
- net::SpdyPriority priority) {
- {
- base::AutoLock autolock(master_->lock_);
-
- // Clean up any zombie WorkerThreads in the ThreadPool that are waiting for
- // reaping. If the OS process we're in accumulates too many unjoined
- // zombie threads over time, the OS might not be able to spawn a new thread
- // below. So right now is a good time to clean them up.
- if (!master_->zombies_.empty()) {
- std::set<WorkerThread*> zombies;
- zombies.swap(master_->zombies_);
- // Joining these threads should be basically instant, since they've
- // already terminated. But to be safe, let's unlock while we join them.
- base::AutoUnlock autounlock(master_->lock_);
- ThreadPool::JoinThreads(zombies);
- }
-
- // The thread pool shouldn't be shutting down until all executors are
- // destroyed. Since this executor clearly still exists, the thread pool
- // must still be open.
- DCHECK(!master_->shutting_down_);
-
- // If the executor hasn't been stopped, add the task to the queue and
- // notify a worker that there's a new task ready to be taken.
- if (!stopped_) {
- master_->task_queue_.insert(std::make_pair(priority, Task(task, this)));
- master_->worker_condvar_.Signal();
- master_->StartNewWorkerIfNeeded();
- return;
- }
- }
-
- // If this executor has already been stopped, just cancel the task (after
- // releasing the lock).
- task->CallCancel();
-}
-
-// Stop the executor. Cancel all pending tasks in the thread pool owned by
-// this executor, and then block until all active tasks owned by this executor
-// complete. Stopping the executor more than once has no effect.
-void ThreadPool::ThreadPoolExecutor::Stop() {
- std::vector<net_instaweb::Function*> functions_to_cancel;
- {
- base::AutoLock autolock(master_->lock_);
- if (stopped_) {
- return;
- }
- stopped_ = true;
-
- // Remove all tasks owned by this executor from the queue, and collect up
- // the function objects to be cancelled.
- TaskQueue::iterator next_iter = master_->task_queue_.begin();
- while (next_iter != master_->task_queue_.end()) {
- TaskQueue::iterator iter = next_iter;
- const Task& task = iter->second;
- ++next_iter; // Increment next_iter _before_ we might erase iter.
- if (task.owner == this) {
- functions_to_cancel.push_back(task.function);
- master_->task_queue_.erase(iter);
- }
- }
- }
-
- // Unlock while we cancel the functions, so we're not hogging the lock for
- // too long, and to avoid potential deadlock if the cancel method tries to do
- // anything with the thread pool.
- for (std::vector<net_instaweb::Function*>::const_iterator iter =
- functions_to_cancel.begin();
- iter != functions_to_cancel.end(); ++iter) {
- (*iter)->CallCancel();
- }
- // CallCancel deletes the Function objects, invalidating the pointers in this
- // list, so let's go ahead and clear it (which also saves a little memory
- // while we're blocked below).
- functions_to_cancel.clear();
-
- // Block until all our active tasks are completed.
- {
- base::AutoLock autolock(master_->lock_);
- while (master_->active_task_counts_.count(this) > 0) {
- stopping_condvar_.Wait();
- }
- }
-}
-
-// A WorkerThread object wraps a platform-specific thread handle, and provides
-// the method run by that thread (ThreadMain).
-class ThreadPool::WorkerThread : public base::PlatformThread::Delegate {
- public:
- explicit WorkerThread(ThreadPool* master);
- virtual ~WorkerThread();
-
- // Start the thread running. Return false on failure. If this succeeds,
- // then you must call Join() before deleting this object.
- bool Start();
-
- // Block until the thread completes. You must set master_->shutting_down_ to
- // true before calling this method, or the thread will never terminate.
- // You shouldn't be holding master_->lock_ when calling this.
- void Join();
-
- // base::PlatformThread::Delegate method:
- virtual void ThreadMain();
-
- private:
- enum ThreadState { NOT_STARTED, STARTED, JOINED };
-
- ThreadPool* const master_;
- // If two master threads are sharing the same ThreadPool, then Start() and
- // Join() might get called by different threads. So to be safe we use a lock
- // to protect the two below fields.
- base::Lock thread_lock_;
- ThreadState state_;
- base::PlatformThreadHandle thread_id_;
-
- DISALLOW_COPY_AND_ASSIGN(WorkerThread);
-};
-
-ThreadPool::WorkerThread::WorkerThread(ThreadPool* master)
- : master_(master), state_(NOT_STARTED), thread_id_() {}
-
-ThreadPool::WorkerThread::~WorkerThread() {
- base::AutoLock autolock(thread_lock_);
- // If we started the thread, we _must_ join it before deleting this object,
- // or else the thread won't get cleaned up by the OS.
- DCHECK(state_ == NOT_STARTED || state_ == JOINED);
-}
-
-bool ThreadPool::WorkerThread::Start() {
- base::AutoLock autolock(thread_lock_);
- DCHECK_EQ(NOT_STARTED, state_);
- if (base::PlatformThread::Create(0, this, &thread_id_)) {
- state_ = STARTED;
- return true;
- }
- return false;
-}
-
-void ThreadPool::WorkerThread::Join() {
- base::AutoLock autolock(thread_lock_);
- DCHECK_EQ(STARTED, state_);
- base::PlatformThread::Join(thread_id_);
- state_ = JOINED;
-}
-
-// This is the code executed by the thread; when this method returns, the
-// thread will terminate.
-void ThreadPool::WorkerThread::ThreadMain() {
- // We start by grabbing the master lock, but we release it below whenever we
- // are 1) waiting for a new task or 2) executing a task. So in fact most of
- // the time we are not holding the lock.
- base::AutoLock autolock(master_->lock_);
- while (true) {
- // Wait until there's a task available (or we're shutting down), but don't
- // stay idle for more than kMaxWorkerIdleSeconds seconds.
- base::TimeDelta time_remaining = master_->max_thread_idle_time_;
- while (!master_->shutting_down_ && master_->task_queue_.empty() &&
- time_remaining.InSecondsF() > 0.0) {
- // Note that TimedWait can wake up spuriously before the time runs out,
- // so we need to measure how long we actually waited for.
- const base::Time start = base::Time::Now();
- master_->worker_condvar_.TimedWait(time_remaining);
- const base::Time end = base::Time::Now();
- // Note that the system clock can go backwards if it is reset, so make
- // sure we never _increase_ time_remaining.
- if (end > start) {
- time_remaining -= end - start;
- }
- }
-
- // If the thread pool is shutting down, terminate this thread; the master
- // is about to join/delete us (in its destructor).
- if (master_->shutting_down_) {
- return;
- }
-
- // If we ran out of time without getting a task, maybe this thread should
- // shut itself down.
- if (master_->task_queue_.empty()) {
- DCHECK_LE(time_remaining.InSecondsF(), 0.0);
- // Ask the master if we should stop. If this returns true, this worker
- // has been zombified, so we're free to terminate the thread.
- if (master_->TryZombifyIdleThread(this)) {
- return; // Yes, we should stop; terminate the thread.
- } else {
- continue; // No, we shouldn't stop; jump to the top of the while loop.
- }
- }
-
- // Otherwise, there must be at least one task available now. Grab one from
- // the master, who will then treat us as busy until we complete it.
- const Task task = master_->GetNextTask();
- // Release the lock while we execute the task. Note that we use AutoUnlock
- // here rather than one AutoLock for the above code and another for the
- // below code, so that we don't have to release and reacquire the lock at
- // the edge of the while-loop.
- {
- base::AutoUnlock autounlock(master_->lock_);
- task.function->CallRun();
- }
- // Inform the master we have completed the task and are no longer busy.
- master_->OnTaskComplete(task);
- }
-}
-
-ThreadPool::ThreadPool(int min_threads, int max_threads)
- : min_threads_(min_threads),
- max_threads_(max_threads),
- max_thread_idle_time_(
- base::TimeDelta::FromSeconds(kDefaultMaxWorkerIdleSeconds)),
- worker_condvar_(&lock_),
- num_busy_workers_(0),
- shutting_down_(false) {
- DCHECK_GE(max_thread_idle_time_.InSecondsF(), 0.0);
- // Note that we check e.g. min_threads rather than min_threads_ (which is
- // unsigned), in order to catch negative numbers.
- DCHECK_GE(min_threads, 1);
- DCHECK_GE(max_threads, 1);
- DCHECK_LE(min_threads_, max_threads_);
-}
-
-ThreadPool::ThreadPool(int min_threads, int max_threads,
- base::TimeDelta max_thread_idle_time)
- : min_threads_(min_threads),
- max_threads_(max_threads),
- max_thread_idle_time_(max_thread_idle_time),
- worker_condvar_(&lock_),
- num_busy_workers_(0),
- shutting_down_(false) {
- DCHECK_GE(max_thread_idle_time_.InSecondsF(), 0.0);
- DCHECK_GE(min_threads, 1);
- DCHECK_GE(max_threads, 1);
- DCHECK_LE(min_threads_, max_threads_);
-}
-
-ThreadPool::~ThreadPool() {
- base::AutoLock autolock(lock_);
-
- // If we're doing things right, all the Executors should have been
- // destroyed before the ThreadPool is destroyed, so there should be no
- // pending or active tasks.
- DCHECK(task_queue_.empty());
- DCHECK(active_task_counts_.empty());
-
- // Wake up all the worker threads and tell them to shut down.
- shutting_down_ = true;
- worker_condvar_.Broadcast();
-
- // Clean up all our threads.
- std::set<WorkerThread*> threads;
- zombies_.swap(threads);
- threads.insert(workers_.begin(), workers_.end());
- workers_.clear();
- {
- base::AutoUnlock autounlock(lock_);
- JoinThreads(threads);
- }
-
- // Because we had shutting_down_ set to true, nothing should have been added
- // to our WorkerThread sets while we were unlocked. So we should be all
- // cleaned up now.
- DCHECK(workers_.empty());
- DCHECK(zombies_.empty());
- DCHECK(task_queue_.empty());
- DCHECK(active_task_counts_.empty());
-}
-
-bool ThreadPool::Start() {
- base::AutoLock autolock(lock_);
- DCHECK(task_queue_.empty());
- DCHECK(workers_.empty());
- // Start up min_threads_ workers; if any of the worker threads fail to start,
- // then this method fails and the ThreadPool should be deleted.
- for (unsigned int i = 0; i < min_threads_; ++i) {
- scoped_ptr<WorkerThread> worker(new WorkerThread(this));
- if (!worker->Start()) {
- return false;
- }
- workers_.insert(worker.release());
- }
- DCHECK_EQ(min_threads_, workers_.size());
- return true;
-}
-
-Executor* ThreadPool::NewExecutor() {
- return new ThreadPoolExecutor(this);
-}
-
-int ThreadPool::GetNumWorkersForTest() {
- base::AutoLock autolock(lock_);
- return workers_.size();
-}
-
-int ThreadPool::GetNumIdleWorkersForTest() {
- base::AutoLock autolock(lock_);
- DCHECK_GE(num_busy_workers_, 0u);
- DCHECK_LE(num_busy_workers_, workers_.size());
- return workers_.size() - num_busy_workers_;
-}
-
-int ThreadPool::GetNumZombiesForTest() {
- base::AutoLock autolock(lock_);
- return zombies_.size();
-}
-
-// This method is called each time we add a new task to the thread pool.
-void ThreadPool::StartNewWorkerIfNeeded() {
- lock_.AssertAcquired();
- DCHECK_GE(num_busy_workers_, 0u);
- DCHECK_LE(num_busy_workers_, workers_.size());
- DCHECK_GE(workers_.size(), min_threads_);
- DCHECK_LE(workers_.size(), max_threads_);
-
- // We create a new worker to handle the task _unless_ either 1) we're already
- // at the maximum number of threads, or 2) there are already enough idle
- // workers sitting around to take on this task (and all other pending tasks
- // that the idle workers haven't yet had a chance to pick up).
- if (workers_.size() >= max_threads_ ||
- task_queue_.size() <= workers_.size() - num_busy_workers_) {
- return;
- }
-
- scoped_ptr<WorkerThread> worker(new WorkerThread(this));
- if (worker->Start()) {
- workers_.insert(worker.release());
- } else {
- LOG(ERROR) << "Failed to start new worker thread.";
- }
-}
-
-// static
-void ThreadPool::JoinThreads(const std::set<WorkerThread*>& threads) {
- for (std::set<WorkerThread*>::const_iterator iter = threads.begin();
- iter != threads.end(); ++iter) {
- WorkerThread* thread = *iter;
- thread->Join();
- delete thread;
- }
-}
-
-// Call when the worker thread has been idle for a while. Either return false
-// (worker should continue waiting for tasks), or zombify the worker and return
-// true (worker thread should immediately terminate).
-bool ThreadPool::TryZombifyIdleThread(WorkerThread* thread) {
- lock_.AssertAcquired();
-
- // Don't terminate the thread if the thread pool is already at the minimum
- // number of threads.
- DCHECK_GE(workers_.size(), min_threads_);
- if (workers_.size() <= min_threads_) {
- return false;
- }
-
- // Remove this thread from the worker set.
- DCHECK_EQ(1u, workers_.count(thread));
- workers_.erase(thread);
-
- // When a (joinable) thread terminates, it must still be cleaned up, either
- // by another thread joining it, or by detatching it. However, the thread
- // pool's not shutting down here, so the master thread doesn't know to join
- // this thread that we're in now, and the Chromium thread abstraction we're
- // using doesn't currently allow us to detach a thread. So instead, we place
- // this WorkerThread object into a "zombie" set, which the master thread can
- // reap later on. Threads that have terminated but that haven't been joined
- // yet use up only a small amount of memory (I think), so it's okay if we
- // don't reap it right away, as long as we don't try to spawn new threads
- // while there's still lots of zombies.
- DCHECK(!shutting_down_);
- DCHECK_EQ(0u, zombies_.count(thread));
- zombies_.insert(thread);
- return true;
-}
-
-// Get and return the next task from the queue (which must be non-empty), and
-// update our various counters to indicate that the calling worker is busy
-// executing this task.
-ThreadPool::Task ThreadPool::GetNextTask() {
- lock_.AssertAcquired();
-
- // Pop the highest-priority task from the queue. Note that smaller values
- // correspond to higher priorities (SPDY draft 3 section 2.3.3), so
- // task_queue_.begin() gets us the highest-priority pending task.
- DCHECK(!task_queue_.empty());
- TaskQueue::iterator task_iter = task_queue_.begin();
- const Task task = task_iter->second;
- task_queue_.erase(task_iter);
-
- // Increment the count of active tasks for the executor that owns this
- // task; we'll decrement it again when the task completes.
- ++(active_task_counts_[task.owner]);
-
- // The worker that takes this task will be busy until it completes it.
- DCHECK_LT(num_busy_workers_, workers_.size());
- ++num_busy_workers_;
-
- return task;
-}
-
-// Call to indicate that the task has been completed; update our various
-// counters to indicate that the calling worker is no longer busy executing
-// this task.
-void ThreadPool::OnTaskComplete(Task task) {
- lock_.AssertAcquired();
-
- // The worker that just finished this task is no longer busy.
- DCHECK_GE(num_busy_workers_, 1u);
- --num_busy_workers_;
-
- // We've completed the task and reaquired the lock, so decrement the count
- // of active tasks for this owner.
- OwnerMap::iterator count_iter = active_task_counts_.find(task.owner);
- DCHECK(count_iter != active_task_counts_.end());
- DCHECK(count_iter->second > 0);
- --(count_iter->second);
-
- // If this was the last active task for the owner, notify anyone who might be
- // waiting for the owner to stop.
- if (count_iter->second == 0) {
- active_task_counts_.erase(count_iter);
- task.owner->stopping_condvar_.Broadcast();
- }
-}
-
-} // namespace mod_spdy
+++ /dev/null
-// 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.
-
-#ifndef MOD_SPDY_COMMON_THREAD_POOL_H_
-#define MOD_SPDY_COMMON_THREAD_POOL_H_
-
-#include <map>
-#include <set>
-
-#include "base/basictypes.h"
-#include "base/synchronization/condition_variable.h"
-#include "base/synchronization/lock.h"
-#include "base/time/time.h"
-#include "net/spdy/spdy_protocol.h" // for net::SpdyPriority
-
-namespace net_instaweb { class Function; }
-
-namespace mod_spdy {
-
-class Executor;
-
-// A ThreadPool keeps a pool of threads waiting to perform tasks. One can
-// create any number of Executor objects, using the NewExecutor method, which
-// will all share the threads for executing tasks. If more tasks are queued
-// than there are threads in the pool, these executors will respect task
-// priorities when deciding which tasks to execute first.
-class ThreadPool {
- public:
- // Create a new thread pool that uses at least min_threads threads, and at
- // most max_threads threads, at a time. min_threads must be no greater than
- // max_threads, and both must be positive.
- ThreadPool(int min_threads, int max_threads);
-
- // As above, but specify the amount of time after which to kill idle threads,
- // rather than using the default value (this is primarily for testing).
- // max_thread_idle_time must be non-negative.
- ThreadPool(int min_threads, int max_threads,
- base::TimeDelta max_thread_idle_time);
-
- // The destructor will block until all threads in the pool have shut down.
- // The ThreadPool must not be destroyed until all Executor objects returned
- // from the NewExecutor method have first been deleted.
- ~ThreadPool();
-
- // Start up the thread pool. Must be called exactly one before using the
- // thread pool; returns true on success, or false on failure. If startup
- // fails, the ThreadPool must be immediately deleted.
- bool Start();
-
- // Return a new Executor object that uses this thread pool to perform tasks.
- // The caller gains ownership of the returned Executor, and the ThreadPool
- // must outlive the returned Executor.
- Executor* NewExecutor();
-
- // Return the current total number of worker threads. This is provided for
- // testing purposes only.
- int GetNumWorkersForTest();
- // Return the number of worker threads currently idle. This is provided for
- // testing purposes only.
- int GetNumIdleWorkersForTest();
- // Return the number of terminated (zombie) threads that have yet to be
- // reaped. This is provided for testing purposes only.
- int GetNumZombiesForTest();
-
- private:
- class ThreadPoolExecutor;
- class WorkerThread;
-
- // A Task is a simple pair of the Function to run, and the executor to which
- // the task was added.
- struct Task {
- Task(net_instaweb::Function* fun, ThreadPoolExecutor* own)
- : function(fun), owner(own) {}
- net_instaweb::Function* function;
- ThreadPoolExecutor* owner;
- };
-
- typedef std::multimap<net::SpdyPriority, Task> TaskQueue;
- typedef std::map<const ThreadPoolExecutor*, int> OwnerMap;
-
- // Start a new worker thread if 1) the task queue is larger than the number
- // of currently idle workers, and 2) we have fewer than the maximum number of
- // workers. Otherwise, do nothing. Must be holding lock_ when calling this.
- void StartNewWorkerIfNeeded();
-
- // Join and delete all worker threads in the given set. This will block
- // until all the threads have terminated and been cleaned up, so don't call
- // this while holding the lock_.
- static void JoinThreads(const std::set<WorkerThread*>& threads);
-
- // These calls are used to implement the WorkerThread's main function. Must
- // be holding lock_ when calling any of these.
- bool TryZombifyIdleThread(WorkerThread* thread);
- Task GetNextTask();
- void OnTaskComplete(Task task);
-
- // The min and max number of threads passed to the constructor. Although the
- // constructor takes signed ints (for convenience), we store these unsigned
- // to avoid the need for static_casts when comparing against workers_.size().
- const unsigned int min_threads_;
- const unsigned int max_threads_;
- const base::TimeDelta max_thread_idle_time_;
- // This single master lock protects all of the below fields, as well as any
- // mutable data and condition variables in the worker threads and executors.
- // Having just one lock makes everything much easier to understand.
- base::Lock lock_;
- // Workers wait on this condvar when waiting for a new task. We signal it
- // when a new task becomes available, or when we need to shut down.
- base::ConditionVariable worker_condvar_;
- // The list of running worker threads. We keep this around so that we can
- // join the threads on shutdown.
- std::set<WorkerThread*> workers_;
- // Worker threads that have shut themselves down (due to being idle), and are
- // awaiting cleanup by the master thread.
- std::set<WorkerThread*> zombies_;
- // How many workers do we have that are actually executing tasks?
- unsigned int num_busy_workers_;
- // We set this to true to tell the worker threads to terminate.
- bool shutting_down_;
- // The priority queue of pending tasks. Invariant: all Function objects in
- // the queue have neither been started nor cancelled yet.
- TaskQueue task_queue_;
- // This maps executors to the number of currently running tasks for that
- // executor; we increment when we start a task, and decrement when we finish
- // it. If the number is zero, we remove the entry from the map; thus, as an
- // invariant the map only contains entries for executors with active tasks.
- OwnerMap active_task_counts_;
-
- DISALLOW_COPY_AND_ASSIGN(ThreadPool);
-};
-
-} // namespace mod_spdy
-
-#endif // MOD_SPDY_COMMON_THREAD_POOL_H_
+++ /dev/null
-// 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.
-
-#include "mod_spdy/common/thread_pool.h"
-
-#include <vector>
-
-#include "base/basictypes.h"
-#include "base/memory/scoped_ptr.h"
-#include "base/synchronization/condition_variable.h"
-#include "base/synchronization/lock.h"
-#include "base/threading/platform_thread.h"
-#include "base/time/time.h"
-#include "mod_spdy/common/executor.h"
-#include "mod_spdy/common/testing/notification.h"
-#include "net/instaweb/util/public/function.h"
-#include "net/spdy/spdy_protocol.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-// When adding tests here, try to keep them robust against thread scheduling
-// differences from run to run. In particular, they shouldn't fail just
-// because you're running under Valgrind.
-
-namespace {
-
-// When run, a TestFunction waits for `wait` millis, then sets `*result` to
-// RAN. When cancelled, it sets *result to CANCELLED.
-class TestFunction : public net_instaweb::Function {
- public:
- enum Result { NOTHING, RAN, CANCELLED };
- TestFunction(int wait, base::Lock* lock, Result* result)
- : wait_(wait), lock_(lock), result_(result) {}
- virtual ~TestFunction() {}
- protected:
- // net_instaweb::Function methods:
- virtual void Run() {
- base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(wait_));
- base::AutoLock autolock(*lock_);
- *result_ = RAN;
- }
- virtual void Cancel() {
- base::AutoLock autolock(*lock_);
- *result_ = CANCELLED;
- }
- private:
- const int wait_;
- base::Lock* const lock_;
- Result* const result_;
- DISALLOW_COPY_AND_ASSIGN(TestFunction);
-};
-
-// Test that we execute tasks concurrently, that that we respect priorities
-// when pulling tasks from the queue.
-TEST(ThreadPoolTest, ConcurrencyAndPrioritization) {
- // Create a thread pool with 2 threads, and an executor.
- mod_spdy::ThreadPool thread_pool(2, 2);
- ASSERT_TRUE(thread_pool.Start());
- scoped_ptr<mod_spdy::Executor> executor(thread_pool.NewExecutor());
-
- base::Lock lock;
- TestFunction::Result result0 = TestFunction::NOTHING;
- TestFunction::Result result1 = TestFunction::NOTHING;
- TestFunction::Result result2 = TestFunction::NOTHING;
- TestFunction::Result result3 = TestFunction::NOTHING;
-
- // Create a high-priority TestFunction, which waits for 200 millis then
- // records that it ran.
- executor->AddTask(new TestFunction(200, &lock, &result0), 0);
- // Create several TestFunctions at different priorities. Each waits 100
- // millis then records that it ran.
- executor->AddTask(new TestFunction(100, &lock, &result1), 1);
- executor->AddTask(new TestFunction(100, &lock, &result3), 3);
- executor->AddTask(new TestFunction(100, &lock, &result2), 2);
-
- // Wait 150 millis, then stop the executor.
- base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(150));
- executor->Stop();
-
- // Only TestFunctions that _started_ within the first 150 millis should have
- // run; the others should have been cancelled.
- // - The priority-0 function should have started first, on the first
- // thread. It finishes after 200 millis.
- // - The priority-1 function should run on the second thread. It finishes
- // after 100 millis.
- // - The priority-2 function should run on the second thread after the
- // priority-1 function finishes, even though it was pushed last, because
- // it's higher-priority than the priority-3 function. It finishes at the
- // 200-milli mark.
- // - The priority-3 function should not get a chance to run, because we
- // stop the executor after 150 millis, and the soonest it could start is
- // the 200-milli mark.
- base::AutoLock autolock(lock);
- EXPECT_EQ(TestFunction::RAN, result0);
- EXPECT_EQ(TestFunction::RAN, result1);
- EXPECT_EQ(TestFunction::RAN, result2);
- EXPECT_EQ(TestFunction::CANCELLED, result3);
-}
-
-// Test that stopping one executor doesn't affect tasks on another executor
-// from the same ThreadPool.
-TEST(ThreadPoolTest, MultipleExecutors) {
- // Create a thread pool with 3 threads, and two executors.
- mod_spdy::ThreadPool thread_pool(3, 3);
- ASSERT_TRUE(thread_pool.Start());
- scoped_ptr<mod_spdy::Executor> executor1(thread_pool.NewExecutor());
- scoped_ptr<mod_spdy::Executor> executor2(thread_pool.NewExecutor());
-
- base::Lock lock;
- TestFunction::Result e1r1 = TestFunction::NOTHING;
- TestFunction::Result e1r2 = TestFunction::NOTHING;
- TestFunction::Result e1r3 = TestFunction::NOTHING;
- TestFunction::Result e2r1 = TestFunction::NOTHING;
- TestFunction::Result e2r2 = TestFunction::NOTHING;
- TestFunction::Result e2r3 = TestFunction::NOTHING;
-
- // Add some tasks to the executors. Each one takes 50 millis to run.
- executor1->AddTask(new TestFunction(50, &lock, &e1r1), 0);
- executor2->AddTask(new TestFunction(50, &lock, &e2r1), 0);
- executor1->AddTask(new TestFunction(50, &lock, &e1r2), 0);
- executor2->AddTask(new TestFunction(50, &lock, &e2r2), 1);
- executor1->AddTask(new TestFunction(50, &lock, &e1r3), 3);
- executor2->AddTask(new TestFunction(50, &lock, &e2r3), 1);
-
- // Wait 20 millis (to make sure the first few tasks got picked up), then
- // destroy executor2, which should stop it. Finally, sleep another 100
- // millis to give the remaining tasks a chance to finish.
- base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(20));
- executor2.reset();
- base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(100));
-
- // The three high priority tasks should have all run. The other two tasks on
- // executor2 should have been cancelled when we stopped executor2, but the
- // low-priority task on executor1 should have been left untouched, and
- // allowed to finish.
- base::AutoLock autolock(lock);
- EXPECT_EQ(TestFunction::RAN, e1r1);
- EXPECT_EQ(TestFunction::RAN, e2r1);
- EXPECT_EQ(TestFunction::RAN, e1r2);
- EXPECT_EQ(TestFunction::CANCELLED, e2r2);
- EXPECT_EQ(TestFunction::RAN, e1r3);
- EXPECT_EQ(TestFunction::CANCELLED, e2r3);
-}
-
-// When run, a WaitFunction blocks until the notification is set.
-class WaitFunction : public net_instaweb::Function {
- public:
- WaitFunction(mod_spdy::testing::Notification* notification)
- : notification_(notification) {}
- virtual ~WaitFunction() {}
- protected:
- // net_instaweb::Function methods:
- virtual void Run() {
- notification_->Wait();
- }
- virtual void Cancel() {}
- private:
- mod_spdy::testing::Notification* const notification_;
- DISALLOW_COPY_AND_ASSIGN(WaitFunction);
-};
-
-// When run, an IdFunction pushes its ID onto the vector.
-class IdFunction : public net_instaweb::Function {
- public:
- IdFunction(int id, base::Lock* lock, base::ConditionVariable* condvar,
- std::vector<int>* output)
- : id_(id), lock_(lock), condvar_(condvar), output_(output) {}
- virtual ~IdFunction() {}
- protected:
- // net_instaweb::Function methods:
- virtual void Run() {
- base::AutoLock autolock(*lock_);
- output_->push_back(id_);
- condvar_->Broadcast();
- }
- virtual void Cancel() {}
- private:
- const int id_;
- base::Lock* const lock_;
- base::ConditionVariable* const condvar_;
- std::vector<int>* const output_;
- DISALLOW_COPY_AND_ASSIGN(IdFunction);
-};
-
-// Test that if many tasks of the same priority are added, they are run in the
-// order they were added.
-TEST(ThreadPoolTest, SamePriorityTasksAreFIFO) {
- // Create a thread pool with just one thread, and an executor.
- mod_spdy::ThreadPool thread_pool(1, 1);
- ASSERT_TRUE(thread_pool.Start());
- scoped_ptr<mod_spdy::Executor> executor(thread_pool.NewExecutor());
-
- // First, make sure no other tasks will get started until we set the
- // notification.
- mod_spdy::testing::Notification start;
- executor->AddTask(new WaitFunction(&start), 0);
-
- // Add many tasks to the executor, of varying priorities.
- const int num_tasks_each_priority = 1000;
- const int total_num_tasks = 3 * num_tasks_each_priority;
- base::Lock lock;
- base::ConditionVariable condvar(&lock);
- std::vector<int> ids; // protected by lock
- for (int id = 0; id < num_tasks_each_priority; ++id) {
- executor->AddTask(new IdFunction(id, &lock, &condvar, &ids), 1);
- executor->AddTask(new IdFunction(id + num_tasks_each_priority,
- &lock, &condvar, &ids), 2);
- executor->AddTask(new IdFunction(id + 2 * num_tasks_each_priority,
- &lock, &condvar, &ids), 3);
- }
-
- // Start us off, then wait for all tasks to finish.
- start.Set();
- base::AutoLock autolock(lock);
- while (static_cast<int>(ids.size()) < total_num_tasks) {
- condvar.Wait();
- }
-
- // Check that the tasks were executed in order by the one worker thread.
- for (int index = 0; index < total_num_tasks; ++index) {
- ASSERT_EQ(index, ids[index])
- << "Task " << ids[index] << " finished in position " << index;
- }
-}
-
-// Add a test failure if the thread pool does not stabilize to the expected
-// total/idle number of worker threads withing the given timeout.
-void ExpectWorkersWithinTimeout(int expected_num_workers,
- int expected_num_idle_workers,
- mod_spdy::ThreadPool* thread_pool,
- int timeout_millis) {
- int millis_remaining = timeout_millis;
- while (true) {
- const int actual_num_workers = thread_pool->GetNumWorkersForTest();
- const int actual_num_idle_workers =
- thread_pool->GetNumIdleWorkersForTest();
- if (actual_num_workers == expected_num_workers &&
- actual_num_idle_workers == expected_num_idle_workers) {
- return;
- }
- if (millis_remaining <= 0) {
- ADD_FAILURE() << "Timed out; expected " << expected_num_workers
- << " worker(s) with " << expected_num_idle_workers
- <<" idle; still at " << actual_num_workers
- << " worker(s) with " << actual_num_idle_workers
- << " idle after " << timeout_millis << "ms";
- return;
- }
- base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(10));
- millis_remaining -= 10;
- }
-}
-
-// Test that we spawn new threads as needed, and allow them to die off after
-// being idle for a while.
-TEST(ThreadPoolTest, CreateAndRetireWorkers) {
- // Create a thread pool with min_threads < max_threads, and give it a short
- // max_thread_idle_time.
- const int idle_time_millis = 100;
- mod_spdy::ThreadPool thread_pool(
- 2, 4, base::TimeDelta::FromMilliseconds(idle_time_millis));
- ASSERT_TRUE(thread_pool.Start());
- // As soon as we start the thread pool, there should be the minimum number of
- // workers (two), both counted as idle.
- EXPECT_EQ(2, thread_pool.GetNumWorkersForTest());
- EXPECT_EQ(2, thread_pool.GetNumIdleWorkersForTest());
-
- scoped_ptr<mod_spdy::Executor> executor(thread_pool.NewExecutor());
-
- // Start up three tasks. That should push us up to three workers
- // immediately. If we make sure to give those threads a chance to run, they
- // should soon pick up the tasks and all be busy.
- mod_spdy::testing::Notification done1;
- executor->AddTask(new WaitFunction(&done1), 0);
- executor->AddTask(new WaitFunction(&done1), 1);
- executor->AddTask(new WaitFunction(&done1), 2);
- EXPECT_EQ(3, thread_pool.GetNumWorkersForTest());
- ExpectWorkersWithinTimeout(3, 0, &thread_pool, 100);
-
- // Add three more tasks. We should now be at the maximum number of workers,
- // and that fourth worker should be busy soon.
- mod_spdy::testing::Notification done2;
- executor->AddTask(new WaitFunction(&done2), 1);
- executor->AddTask(new WaitFunction(&done2), 2);
- executor->AddTask(new WaitFunction(&done2), 3);
- EXPECT_EQ(4, thread_pool.GetNumWorkersForTest());
- ExpectWorkersWithinTimeout(4, 0, &thread_pool, 100);
-
- // Allow the first group of tasks to finish. There are now only three tasks
- // running, so one of our four threads should go idle. If we wait for a
- // while after that, that thread should terminate and enter zombie mode.
- done1.Set();
- ExpectWorkersWithinTimeout(4, 1, &thread_pool, idle_time_millis / 2);
- ExpectWorkersWithinTimeout(3, 0, &thread_pool, 2 * idle_time_millis);
- EXPECT_EQ(1, thread_pool.GetNumZombiesForTest());
-
- // Allow the second group of tasks to finish. There are no tasks left, so
- // all three threads should go idle. If we wait for a while after that,
- // exactly one of the three should shut down, bringing us back down to the
- // minimum number of threads. We should now have two zombie threads.
- done2.Set();
- ExpectWorkersWithinTimeout(3, 3, &thread_pool, idle_time_millis / 2);
- ExpectWorkersWithinTimeout(2, 2, &thread_pool, 2 * idle_time_millis);
- EXPECT_EQ(2, thread_pool.GetNumZombiesForTest());
-
- // Start some new new tasks. This should cause us to immediately reap the
- // zombie threads, and soon, we should have three busy threads.
- mod_spdy::testing::Notification done3;
- executor->AddTask(new WaitFunction(&done3), 0);
- executor->AddTask(new WaitFunction(&done3), 2);
- executor->AddTask(new WaitFunction(&done3), 1);
- EXPECT_EQ(0, thread_pool.GetNumZombiesForTest());
- EXPECT_EQ(3, thread_pool.GetNumWorkersForTest());
- ExpectWorkersWithinTimeout(3, 0, &thread_pool, 100);
-
- // Let those tasks finish. Once again, the threads should go idle, and then
- // one of them should terminate and enter zombie mode.
- done3.Set();
- ExpectWorkersWithinTimeout(3, 3, &thread_pool, idle_time_millis / 2);
- ExpectWorkersWithinTimeout(2, 2, &thread_pool, 2 * idle_time_millis);
- EXPECT_EQ(1, thread_pool.GetNumZombiesForTest());
-
- // When we exit the test, the thread pool's destructor should reap the zombie
- // thread (as well as shutting down the still-running workers). We can
- // verify this by running this test under valgrind and making sure that no
- // memory is leaked.
-}
-
-} // namespace
+++ /dev/null
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// version.h is generated from version.h.in. Edit the source!
-
-#pragma once
-
-// Version Information
-
-#define MOD_SPDY_VERSION @MAJOR@,@MINOR@,@BUILD@,@PATCH@
-#define MOD_SPDY_VERSION_STRING "@MAJOR@.@MINOR@.@BUILD@.@PATCH@"
-
-// Branding Information
-
-#define COMPANY_FULLNAME_STRING "@COMPANY_FULLNAME@"
-#define COMPANY_SHORTNAME_STRING "@COMPANY_SHORTNAME@"
-#define PRODUCT_FULLNAME_STRING "@PRODUCT_FULLNAME@"
-#define PRODUCT_SHORTNAME_STRING "@PRODUCT_SHORTNAME@"
-#define COPYRIGHT_STRING "@COPYRIGHT@"
-#define OFFICIAL_BUILD_STRING "@OFFICIAL_BUILD@"
-
-// Changelist Information
-
-#define LASTCHANGE_STRING "@LASTCHANGE@"
+++ /dev/null
-// 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_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/spdy_server_config.h"
-#include "mod_spdy/common/spdy_session.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"
-};
-
-// This global variable stores the filter handle for our push filter. 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;
-
-// 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;
-
-// 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);
-}
-
-// 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.
- bool spdy_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();
- 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.";
- }
-}
-
-// 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;
- }
-
- // 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));
-
- // 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"
+++ /dev/null
-# 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',
- ],
- '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/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',
- ],
- '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',
- ],
- 'include_dirs': [
- '<(DEPTH)',
- ],
- 'sources': [
- 'apache/filters/http_to_spdy_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',
- ],
- },
- ],
-}
+++ /dev/null
-/* 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_ */
+++ /dev/null
-# 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.
-
-vars = {
- "chromium_trunk": "http://src.chromium.org/svn/trunk",
- "chromium_revision": "@228939",
- "chromium_deps_root": "src/third_party/chromium_deps",
- "apr_src": "http://svn.apache.org/repos/asf/apr/apr/tags/1.4.2",
- "apr_revision": "@head",
- "aprutil_src": "http://svn.apache.org/repos/asf/apr/apr-util/tags/1.3.9",
- "aprutil_revision": "@head",
- "apache_httpd_src": "http://svn.apache.org/repos/asf/httpd/httpd/tags/2.2.15",
- "apache_httpd_revision": "@head",
- "mod_pagespeed_root": "http://modpagespeed.googlecode.com/svn/tags/0.10.19.5",
- "mod_pagespeed_revision": "@head",
-}
-
-deps = {
- # Fetch chromium DEPS so we can sync our other dependencies relative
- # to it.
- Var("chromium_deps_root"):
- File(Var("chromium_trunk") + "/src/DEPS" + Var("chromium_revision")),
-
- "src/net/instaweb/util":
- Var("mod_pagespeed_root") + "/src/net/instaweb/util" +
- Var("mod_pagespeed_revision"),
-
- "src/testing":
- Var("chromium_trunk") + "/src/testing" + Var("chromium_revision"),
-
- "src/third_party/chromium/src/build":
- Var("chromium_trunk") + "/src/build" + Var("chromium_revision"),
-
- "src/third_party/chromium/src/base":
- Var("chromium_trunk") + "/src/base" + Var("chromium_revision"),
-
- "src/third_party/chromium/src/chrome/tools/build":
- Var("chromium_trunk") + "/src/chrome/tools/build" +
- Var("chromium_revision"),
-
- "src/third_party/chromium/src/net/base":
- Var("chromium_trunk") + "/src/net/base" + Var("chromium_revision"),
-
- "src/third_party/chromium/src/net/socket":
- Var("chromium_trunk") + "/src/net/socket" + Var("chromium_revision"),
-
- "src/third_party/chromium/src/net/spdy":
- Var("chromium_trunk") + "/src/net/spdy" + Var("chromium_revision"),
-
- "src/third_party/chromium/src/net/tools/flip_server":
- Var("chromium_trunk") + "/src/net/tools/flip_server" +
- Var("chromium_revision"),
-
- "src/build/linux":
- Var("chromium_trunk") + "/src/build/linux" + Var("chromium_revision"),
- "src/build/mac":
- Var("chromium_trunk") + "/src/build/mac" + Var("chromium_revision"),
- "src/build/win":
- Var("chromium_trunk") + "/src/build/win" + Var("chromium_revision"),
- "src/build/internal":
- Var("chromium_trunk") + "/src/build/internal" + Var("chromium_revision"),
-
- # lastchange.py changed its behavior at some point in a way that it
- # stopped working for us. Thus we continue to sync just that file at
- # a known good revision. We do not sync all of src/build/util so as
- # to make sure that we don't accidentally depend on something else
- # at that old revision.
- "src/build/util":
- File(Var("chromium_trunk") + "/src/build/util/lastchange.py" + "@90205"),
-
- "src/third_party/apache/apr/src":
- Var("apr_src") + Var("apr_revision"),
-
- "src/third_party/apache/aprutil/src":
- Var("aprutil_src") + Var("aprutil_revision"),
-
- "src/third_party/apache/httpd/src/include":
- Var("apache_httpd_src") + "/include" + Var("apache_httpd_revision"),
-
- "src/third_party/apache/httpd/src/os":
- Var("apache_httpd_src") + "/os" + Var("apache_httpd_revision"),
-
- "src/third_party/modp_b64":
- Var("chromium_trunk") + "/src/third_party/modp_b64" +
- Var("chromium_revision"),
-
- "src/third_party/protobuf":
- (Var("chromium_trunk") + "/src/third_party/protobuf" +
- Var("chromium_revision")),
-
- "src/third_party/zlib":
- Var("chromium_trunk") + "/src/third_party/zlib" + Var("chromium_revision"),
-
- "src/testing/gmock": From(Var("chromium_deps_root")),
- "src/testing/gtest": From(Var("chromium_deps_root")),
- "src/tools/gyp": From(Var("chromium_deps_root")),
-}
-
-
-deps_os = {
- "win": {
- "src/third_party/cygwin": From(Var("chromium_deps_root")),
- "src/third_party/python_26": From(Var("chromium_deps_root")),
- },
- "mac": {
- },
- "unix": {
- },
-}
-
-
-include_rules = [
- # Everybody can use some things.
- "+base",
- "+build",
-]
-
-
-# checkdeps.py shouldn't check include paths for files in these dirs:
-skip_child_includes = [
- "testing",
-]
-
-
-hooks = [
- {
- # A change to a .gyp, .gypi, or to GYP itself should run the generator.
- "pattern": ".",
- "action": ["python", "src/build/gyp_chromium"],
- },
-]
+++ /dev/null
-# 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.
-
-# Base was branched from the chromium version to reduce the number of
-# dependencies of this package. Specifically, we would like to avoid
-# depending on the chrome directory, which contains the chrome version
-# and branding information.
-# TODO: push this refactoring to chronium trunk.
-
-{
- 'variables': {
- 'chromium_code': 1,
- 'chromium_root': '<(DEPTH)/third_party/chromium/src',
- },
- 'targets': [
- {
- 'target_name': 'base',
- 'type': '<(component)',
- 'dependencies': [
- '<(DEPTH)/third_party/modp_b64/modp_b64.gyp:modp_b64',
- '<(chromium_root)/base/third_party/dynamic_annotations/dynamic_annotations.gyp:dynamic_annotations',
- ],
- 'sources': [
- '<(chromium_root)/base/at_exit.cc',
- '<(chromium_root)/base/atomicops_internals_x86_gcc.cc',
- '<(chromium_root)/base/base_switches.cc',
- '<(chromium_root)/base/callback_internal.cc',
- '<(chromium_root)/base/command_line.cc',
- '<(chromium_root)/base/debug/alias.cc',
- '<(chromium_root)/base/debug/debugger.cc',
- '<(chromium_root)/base/debug/debugger_posix.cc',
- '<(chromium_root)/base/debug/debugger_win.cc',
- '<(chromium_root)/base/debug/stack_trace.cc',
- '<(chromium_root)/base/debug/stack_trace_posix.cc',
- '<(chromium_root)/base/debug/stack_trace_win.cc',
- '<(chromium_root)/base/files/file_path.cc',
- '<(chromium_root)/base/files/file_path_constants.cc',
- '<(chromium_root)/base/lazy_instance.cc',
- '<(chromium_root)/base/location.cc',
- '<(chromium_root)/base/logging.cc',
- '<(chromium_root)/base/logging_win.cc',
- '<(chromium_root)/base/mac/foundation_util.mm',
- '<(chromium_root)/base/memory/ref_counted.cc',
- '<(chromium_root)/base/memory/singleton.cc',
- '<(chromium_root)/base/metrics/stats_counters.cc',
- 'metrics/stats_table.cc',
- '<(chromium_root)/base/pickle.cc',
- '<(chromium_root)/base/process/process_handle_linux.cc',
- '<(chromium_root)/base/process/process_handle_mac.cc',
- '<(chromium_root)/base/process/process_handle_posix.cc',
- '<(chromium_root)/base/process/process_handle_win.cc',
- '<(chromium_root)/base/profiler/alternate_timer.cc',
- '<(chromium_root)/base/profiler/tracked_time.cc',
- '<(chromium_root)/base/safe_strerror_posix.cc',
- '<(chromium_root)/base/strings/string16.cc',
- '<(chromium_root)/base/strings/string16.h',
- '<(chromium_root)/base/strings/string_number_conversions.cc',
- '<(chromium_root)/base/strings/string_piece.cc',
- '<(chromium_root)/base/strings/string_split.cc',
- '<(chromium_root)/base/strings/string_util.cc',
- '<(chromium_root)/base/strings/string_util_constants.cc',
- '<(chromium_root)/base/strings/stringprintf.cc',
- '<(chromium_root)/base/strings/sys_string_conversions_posix.cc',
- '<(chromium_root)/base/strings/sys_string_conversions_mac.mm',
- '<(chromium_root)/base/strings/sys_string_conversions_win.cc',
- '<(chromium_root)/base/strings/utf_string_conversion_utils.cc',
- '<(chromium_root)/base/strings/utf_string_conversions.cc',
- '<(chromium_root)/base/synchronization/condition_variable_posix.cc',
- '<(chromium_root)/base/synchronization/condition_variable_win.cc',
- '<(chromium_root)/base/synchronization/lock.cc',
- '<(chromium_root)/base/synchronization/lock_impl_posix.cc',
- '<(chromium_root)/base/synchronization/lock_impl_win.cc',
- '<(chromium_root)/base/synchronization/waitable_event_posix.cc',
- '<(chromium_root)/base/synchronization/waitable_event_win.cc',
- '<(chromium_root)/base/third_party/dmg_fp/g_fmt.cc',
- '<(chromium_root)/base/third_party/dmg_fp/dtoa_wrapper.cc',
- '<(chromium_root)/base/third_party/icu/icu_utf.cc',
- '<(chromium_root)/base/third_party/nspr/prtime.cc',
- '<(chromium_root)/base/threading/platform_thread_mac.mm',
- '<(chromium_root)/base/threading/platform_thread_linux.cc',
- '<(chromium_root)/base/threading/platform_thread_posix.cc',
- '<(chromium_root)/base/threading/platform_thread_win.cc',
- '<(chromium_root)/base/threading/thread_collision_warner.cc',
- '<(chromium_root)/base/threading/thread_id_name_manager.cc',
- '<(chromium_root)/base/threading/thread_local_posix.cc',
- '<(chromium_root)/base/threading/thread_local_win.cc',
- '<(chromium_root)/base/threading/thread_local_storage_posix.cc',
- '<(chromium_root)/base/threading/thread_local_storage_win.cc',
- '<(chromium_root)/base/threading/thread_restrictions.cc',
- '<(chromium_root)/base/time/time.cc',
- '<(chromium_root)/base/time/time_mac.cc',
- '<(chromium_root)/base/time/time_posix.cc',
- '<(chromium_root)/base/time/time_win.cc',
- '<(chromium_root)/base/tracked_objects.cc',
- '<(chromium_root)/base/vlog.cc',
- '<(chromium_root)/base/win/registry.cc',
- '<(chromium_root)/base/win/win_util.cc',
- '<(chromium_root)/base/win/windows_version.cc',
- ],
- 'include_dirs': [
- '<(chromium_root)',
- '<(DEPTH)',
- ],
- 'direct_dependent_settings': {
- 'include_dirs': [
- '<(chromium_root)',
- '<(DEPTH)',
- ],
- },
- 'conditions': [
- ['OS != "win"', {
- 'sources/': [ ['exclude', '^win/'] ],
- }],
- [ 'OS == "win"', {
- 'sources!': [
- '<(chromium_root)/base/string16.cc',
- ],
- }],
- ['OS == "linux"', {
- 'cflags': [
- '-Wno-write-strings',
- '-Wno-error',
- ],
- 'link_settings': {
- 'libraries': [
- # We need rt for clock_gettime().
- '-lrt',
- ],
- },
- }],
- ],
- },
- ],
-}
+++ /dev/null
-// Copyright (c) 2006-2008 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.
-
-// A stubbed version of stats_table.cc that doesn't do anything. These
-// functions must be defined in order to link with code that updates
-// stats (such as spdy_framer.cc).
-
-#include "base/metrics/stats_table.h"
-
-namespace base {
-
-StatsTable* StatsTable::current() { return NULL; }
-
-int StatsTable::RegisterThread(const std::string& name) {
- return 0;
-}
-
-int StatsTable::GetSlot() const {
- return 0;
-}
-
-int StatsTable::FindCounter(const std::string& name) {
- return 0;
-}
-
-int* StatsTable::GetLocation(int counter_id, int slot_id) const {
- return NULL;
-}
-
-} // namespace base
+++ /dev/null
-# 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.
-
-{
- 'targets': [
- {
- 'target_name': 'All',
- 'type': 'none',
- 'xcode_create_dependents_test_runner': 1,
- 'dependencies': [
- '../base/base.gyp:*',
- '../mod_spdy/mod_spdy.gyp:*',
- '../net/net.gyp:*',
- '../third_party/mod_diagnostics/mod_diagnostics.gyp:*',
- 'install.gyp:*',
- ],} ]
-}
+++ /dev/null
-#include "third_party/chromium/src/build/build_config.h"
+++ /dev/null
-# 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': {
- 'version_py_path': 'version.py',
- 'mod_spdy_path': '<(DEPTH)/mod_spdy',
- 'version_path': '<(mod_spdy_path)/common/VERSION',
- 'version_h_in_path': '<(mod_spdy_path)/common/version.h.in',
- 'version_h_path': '<(SHARED_INTERMEDIATE_DIR)/mod_spdy/common/version.h',
- 'lastchange_out_path': '<(SHARED_INTERMEDIATE_DIR)/build/LASTCHANGE',
- },
- 'targets': [
- {
- 'target_name': 'lastchange',
- 'type': 'none',
- 'variables': {
- 'default_lastchange_path': '../LASTCHANGE.in',
- },
- 'actions': [
- {
- 'action_name': 'lastchange',
- 'inputs': [
- # Note: <(default_lastchange_path) is optional,
- # so it doesn't show up in inputs.
- 'util/lastchange.py',
- ],
- 'outputs': [
- '<(lastchange_out_path).always',
- '<(lastchange_out_path)',
- ],
- 'action': [
- 'python', '<@(_inputs)',
- '-o', '<(lastchange_out_path)',
- '-d', '<(default_lastchange_path)',
- ],
- 'message': 'Extracting last change to <(lastchange_out_path)',
- 'process_outputs_as_sources': '1',
- },
- ],
- },
- {
- 'target_name': 'mod_spdy_version_header',
- 'type': 'none',
- 'dependencies': [
- 'lastchange',
- ],
- 'actions': [
- {
- 'action_name': 'version_header',
- 'inputs': [
- '<(version_path)',
- '<(lastchange_out_path)',
- '<(version_h_in_path)',
- ],
- 'outputs': [
- '<(version_h_path)',
- ],
- 'action': [
- 'python',
- '<(version_py_path)',
- '-f', '<(version_path)',
- '-f', '<(lastchange_out_path)',
- '<(version_h_in_path)',
- '<@(_outputs)',
- ],
- 'message': 'Generating version header file: <@(_outputs)',
- },
- ],
- 'direct_dependent_settings': {
- 'include_dirs': [
- '<(SHARED_INTERMEDIATE_DIR)',
- ],
- },
- },
- ]
-}
-
-# Local Variables:
-# tab-width:2
-# indent-tabs-mode:nil
-# End:
-# vim: set expandtab tabstop=2 shiftwidth=2:
+++ /dev/null
-# 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.
-#
-# mod_spdy common gyp configuration.
-{
- 'variables': {
- 'library%': 'static_library',
-
- # Don't use the gold linker:
- 'linux_use_gold_binary': 0,
- 'linux_use_gold_flags': 0,
-
- # Don't use the system Apache dev files by default:
- 'use_system_apache_dev%': 0,
-
- # Turn these off to prevent Chromium's build config from bothering us about
- # things we don't care about for mod_spdy:
- 'clang_use_chrome_plugins': 0,
- 'incremental_chrome_dll': 0,
- 'use_official_google_api_keys': 0,
- },
-
- # Import Chromium's common.gypi to inherit their build configuration.
- 'includes': [
- '../third_party/chromium/src/build/common.gypi',
- ],
-
- # Modify the Chromium configuration as needed:
- 'target_defaults': {
- # Make sure our shadow view of chromium source is available to
- # targets that don't explicitly declare their dependencies and
- # assume chromium source headers are available from the root
- # (third_party/modp_b64 is one such target).
- 'include_dirs': [
- '<(DEPTH)/third_party/chromium/src',
- ],
- },
-}
+++ /dev/null
-#!/usr/bin/python
-
-# 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.
-
-# This script is wrapper for the Chromium version of compiler_version.py.
-
-import os
-
-script_dir = os.path.dirname(__file__)
-chrome_src = os.path.normpath(os.path.join(script_dir, os.pardir, 'third_party', 'chromium', 'src'))
-
-execfile(os.path.join(chrome_src, 'build', 'compiler_version.py'))
+++ /dev/null
-#!/usr/bin/python
-
-# 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.
-
-# This script is wrapper for the Chromium version of dir_exists.py.
-
-import os
-
-script_dir = os.path.dirname(__file__)
-chrome_src = os.path.normpath(os.path.join(script_dir, os.pardir, 'third_party', 'chromium', 'src'))
-
-execfile(os.path.join(chrome_src, 'build', 'dir_exists.py'))
+++ /dev/null
-# 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.
-
-# Chromium expects this file to be here, but for our purposes, it
-# doesn't need to actually do anything.
-
-{}
+++ /dev/null
-#!/usr/bin/python
-
-# 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.
-
-# This script is wrapper for the Chromium version of gyp_chromium.
-
-import os
-import sys
-
-script_dir = os.path.dirname(__file__)
-chrome_src = os.path.normpath(os.path.join(script_dir, os.pardir, 'third_party', 'chromium', 'src'))
-
-# The Chromium gyp_chromium defaults to ninja on linux. We want to default to
-# make instead.
-if sys.platform.startswith('linux') and not os.environ.get('GYP_GENERATORS'):
- os.environ['GYP_GENERATORS'] = 'make'
-
-execfile(os.path.join(chrome_src, 'build', 'gyp_chromium'))
+++ /dev/null
-#!/usr/bin/python
-
-# 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.
-
-# This script is wrapper for the Chromium version of gyp_helper.py.
-
-import os
-
-script_dir = os.path.dirname(__file__)
-chrome_src = os.path.normpath(os.path.join(script_dir, os.pardir, 'third_party', 'chromium', 'src'))
-
-execfile(os.path.join(chrome_src, 'build', 'gyp_helper.py'))
+++ /dev/null
-# Copyright (c) 2010 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': {
- 'install_path': '<(DEPTH)/install',
- 'version_py_path': '<(DEPTH)/build/version.py',
- 'version_path': '<(DEPTH)/mod_spdy/common/VERSION',
- 'lastchange_path': '<(SHARED_INTERMEDIATE_DIR)/build/LASTCHANGE',
- 'branding_path': '<(install_path)/common/BRANDING',
- },
- 'conditions': [
- ['OS=="linux"', {
- 'variables': {
- 'version' : '<!(python <(version_py_path) -f <(version_path) -t "@MAJOR@.@MINOR@.@BUILD@.@PATCH@")',
- 'revision' : '<!(python <(DEPTH)/build/util/lastchange.py | cut -d "=" -f 2)',
- 'packaging_files_common': [
- '<(install_path)/common/apt.include',
- '<(install_path)/common/mod-spdy.info',
- '<(install_path)/common/installer.include',
- '<(install_path)/common/repo.cron',
- '<(install_path)/common/rpm.include',
- '<(install_path)/common/rpmrepo.cron',
- '<(install_path)/common/updater',
- '<(install_path)/common/variables.include',
- '<(install_path)/common/BRANDING',
- '<(install_path)/common/spdy.load.template',
- '<(install_path)/common/spdy.conf.template',
- '<(install_path)/common/ssl.load.template',
- ],
- 'packaging_files_deb': [
- '<(install_path)/debian/build.sh',
- '<(install_path)/debian/changelog.template',
- '<(install_path)/debian/conffiles.template',
- '<(install_path)/debian/control.template',
- '<(install_path)/debian/postinst',
- '<(install_path)/debian/postrm',
- '<(install_path)/debian/preinst',
- '<(install_path)/debian/prerm',
- ],
- 'packaging_files_rpm': [
- '<(install_path)/rpm/build.sh',
- '<(install_path)/rpm/mod-spdy.spec.template',
- ],
- 'packaging_files_binaries': [
- '<(PRODUCT_DIR)/libmod_spdy.so',
- ],
- 'flock_bash': ['flock', '--', '/tmp/linux_package_lock', 'bash'],
- 'deb_build': '<(PRODUCT_DIR)/install/debian/build.sh',
- 'rpm_build': '<(PRODUCT_DIR)/install/rpm/build.sh',
- 'deb_cmd': ['<@(flock_bash)', '<(deb_build)', '-o' '<(PRODUCT_DIR)',
- '-b', '<(PRODUCT_DIR)', '-a', '<(target_arch)'],
- 'rpm_cmd': ['<@(flock_bash)', '<(rpm_build)', '-o' '<(PRODUCT_DIR)',
- '-b', '<(PRODUCT_DIR)', '-a', '<(target_arch)'],
- 'conditions': [
- ['target_arch=="ia32"', {
- 'deb_arch': 'i386',
- 'rpm_arch': 'i386',
- }],
- ['target_arch=="x64"', {
- 'deb_arch': 'amd64',
- 'rpm_arch': 'x86_64',
- }],
- ],
- },
- 'targets': [
- {
- 'target_name': 'linux_installer_configs',
- 'suppress_wildcard': 1,
- 'type': 'none',
- # Add these files to the build output so the build archives will be
- # "hermetic" for packaging.
- 'copies': [
- {
- 'destination': '<(PRODUCT_DIR)/install/debian/',
- 'files': [
- '<@(packaging_files_deb)',
- ]
- },
- {
- 'destination': '<(PRODUCT_DIR)/install/rpm/',
- 'files': [
- '<@(packaging_files_rpm)',
- ]
- },
- {
- 'destination': '<(PRODUCT_DIR)/install/common/',
- 'files': [
- '<@(packaging_files_common)',
- ]
- },
- {
- 'destination': '<(PRODUCT_DIR)/',
- 'files': [
- '<(DEPTH)/mod_ssl.so',
- ]
- },
- ],
- 'actions': [
- {
- 'action_name': 'save_build_info',
- 'inputs': [
- '<(branding_path)',
- '<(version_path)',
- '<(lastchange_path)',
- ],
- 'outputs': [
- '<(PRODUCT_DIR)/installer/version.txt',
- ],
- # Just output the default version info variables.
- 'action': [
- 'python', '<(version_py_path)',
- '-f', '<(branding_path)',
- '-f', '<(version_path)',
- '-f', '<(lastchange_path)',
- '-o', '<@(_outputs)'
- ],
- },
- ],
- },
- {
- 'target_name': 'linux_packages',
- 'suppress_wildcard': 1,
- 'type': 'none',
- 'dependencies': [
- 'linux_package_deb',
- 'linux_package_rpm',
- ],
- },
- {
- 'target_name': 'linux_package_deb',
- 'suppress_wildcard': 1,
- 'type': 'none',
- 'dependencies': [
- '<(DEPTH)/mod_spdy/mod_spdy.gyp:mod_spdy',
- 'linux_installer_configs',
- ],
- 'actions': [
- {
- 'variables': {
- 'channel': 'beta',
- },
- 'action_name': 'deb_package_<(channel)',
- 'process_outputs_as_sources': 1,
- 'inputs': [
- '<(deb_build)',
- '<@(packaging_files_binaries)',
- '<@(packaging_files_common)',
- '<@(packaging_files_deb)',
- ],
- 'outputs': [
- '<(PRODUCT_DIR)/mod-spdy-<(channel)_<(version)-r<(revision)_<(deb_arch).deb',
- ],
- 'action': [ '<@(deb_cmd)', '-c', '<(channel)', ],
- },
- ],
- },
- {
- 'target_name': 'linux_package_rpm',
- 'suppress_wildcard': 1,
- 'type': 'none',
- 'dependencies': [
- '<(DEPTH)/mod_spdy/mod_spdy.gyp:mod_spdy',
- 'linux_installer_configs',
- ],
- 'actions': [
- {
- 'variables': {
- 'channel': 'beta',
- },
- 'action_name': 'rpm_package_<(channel)',
- 'process_outputs_as_sources': 1,
- 'inputs': [
- '<(rpm_build)',
- '<(PRODUCT_DIR)/install/rpm/mod-spdy.spec.template',
- '<@(packaging_files_binaries)',
- '<@(packaging_files_common)',
- '<@(packaging_files_rpm)',
- ],
- 'outputs': [
- '<(PRODUCT_DIR)/mod-spdy-<(channel)-<(version)-r<(revision).<(rpm_arch).rpm',
- ],
- 'action': [ '<@(rpm_cmd)', '-c', '<(channel)', ],
- },
- ],
- },
- ],
- },{
- 'targets': [
- ],
- }],
- ],
-}
-
-# Local Variables:
-# tab-width:2
-# indent-tabs-mode:nil
-# End:
-# vim: set expandtab tabstop=2 shiftwidth=2:
+++ /dev/null
-<?xml version="1.0" encoding="utf-8"?>
-<VisualStudioToolFile
- Name="Output DLL copy"
- Version="8.00"
- >
- <Rules>
- <CustomBuildRule
- Name="Output DLL copy"
- CommandLine="xcopy /R /C /Y $(InputPath) $(OutDir)"
- Outputs="$(OutDir)\$(InputFileName)"
- FileExtensions="*.dll"
- >
- <Properties>
- </Properties>
- </CustomBuildRule>
- </Rules>
-</VisualStudioToolFile>
+++ /dev/null
-{
- 'conditions': [
- # Handle build types.
- ['buildtype=="Dev"', {
- 'includes': ['internal/release_impl.gypi'],
- }],
- ['buildtype=="Official"', {
- 'includes': ['internal/release_impl_official.gypi'],
- }],
- # TODO(bradnelson): may also need:
- # checksenabled
- # coverage
- # dom_stats
- # pgo_instrument
- # pgo_optimize
- # purify
- ],
-}
-
+++ /dev/null
-#!/usr/bin/python
-
-# 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.
-
-# This script is wrapper for the Chromium version of compiler_version.py.
-
-import os
-
-script_dir = os.path.dirname(__file__)
-chrome_src = os.path.normpath(os.path.join(script_dir, os.pardir, 'third_party',
- 'chromium', 'src'))
-
-execfile(os.path.join(chrome_src, 'chrome', 'tools', 'build', 'version.py'))
+++ /dev/null
-#!/bin/bash
-#
-# This script builds mod_ssl.so for Apache 2.2.x, with SSL NPN
-# support.
-#
-# NPN is not yet supported in Apache HTTPD mod_ssl. A patch has been
-# submitted to Apache to enable NPN in mod_ssl:
-# https://issues.apache.org/bugzilla/show_bug.cgi?id=52210
-#
-# Thus, we download the 1.0.1 release of OpenSSL and the most recent
-# release of Apache 2.2, and apply a patch to enable NPN support in
-# Apache mod_ssl.
-#
-# We currently statically link OpenSSL with mod_ssl, which results in
-# a large (several megabyte) mod_ssl.so. If you prefer, you can
-# install NPN-enabled OpenSSL as a shared library system-wide, by
-# building OpenSSL like so:
-#
-# ./config shared -fPIC # -fPIC is only needed on some architectures
-# make
-# sudo make install
-#
-# And Apache like so (after applying the NPN patch):
-#
-# ./configure --enable-ssl=shared
-# make
-
-MODSSL_SO_DESTPATH=$(pwd)/mod_ssl.so
-
-if [ -f $MODSSL_SO_DESTPATH ]; then
- echo "mod_ssl already exists at $MODSSL_SO_DESTPATH. Please remove."
- exit 1
-fi
-
-if [ -z "$BUILDROOT" ]; then
- BUILDROOT=$(mktemp -d)
- REMOVE_BUILDROOT=1
-else
- REMOVE_BUILDROOT=0
-fi
-
-if [ ! -d "$BUILDROOT" ]; then
- echo "Not a directory: $BUILDROOT"
- exit 1
-fi
-
-# Convert BUILDROOT to an absolute path.
-BUILDROOT="$(cd $(dirname $BUILDROOT); pwd)/$(basename $BUILDROOT)"
-echo "Using buildroot: $BUILDROOT"
-echo ""
-
-function do_cleanup {
- echo ""
- echo "Build aborted."
- if [ $REMOVE_BUILDROOT -eq 1 ]; then
- echo -n "Cleaning up ... "
- rm -rf "$BUILDROOT"
- echo "done"
- fi
- exit 1
-}
-
-trap 'do_cleanup' SIGINT SIGTERM
-
-PROGRESS_DIR=$BUILDROOT/progress
-mkdir -p $PROGRESS_DIR
-if [ $? -ne 0 ]; then
- do_cleanup
-fi
-
-function download_file {
- if [ ! -f "$PROGRESS_DIR/$2.downloaded" ]; then
- echo "Downloading $1"
- curl -f -# "$1" -o $2 || do_cleanup
- if [[ $(md5sum $2 | cut -d\ -f1) != $3 ]]; then
- echo "md5sum mismatch for $2"
- do_cleanup
- fi
- touch "$PROGRESS_DIR/$2.downloaded"
- else
- echo "Already downloaded $1"
- fi
-}
-
-function uncompress_file {
- if [ ! -f "$PROGRESS_DIR/$1.uncompressed" ]; then
- echo -n "Uncompressing $1 ... "
- tar xzf $1 || do_cleanup
- echo "done"
- touch "$PROGRESS_DIR/$1.uncompressed"
- else
- echo "Already uncompressed $1"
- fi
-}
-
-OPENSSL_SRC_TGZ_URL="https://www.openssl.org/source/openssl-1.0.1g.tar.gz"
-APACHE_HTTPD_SRC_TGZ_URL="https://archive.apache.org/dist/httpd/httpd-2.2.27.tar.gz"
-APACHE_HTTPD_MODSSL_NPN_PATCH_PATH="$(dirname $0)/scripts/mod_ssl_with_npn.patch"
-
-OPENSSL_SRC_TGZ=$(basename $OPENSSL_SRC_TGZ_URL)
-APACHE_HTTPD_SRC_TGZ=$(basename $APACHE_HTTPD_SRC_TGZ_URL)
-APACHE_HTTPD_MODSSL_NPN_PATCH="mod_ssl_npn.patch"
-
-OPENSSL_SRC_ROOT=${OPENSSL_SRC_TGZ%.tar.gz}
-OPENSSL_INST_ROOT=${OPENSSL_SRC_ROOT}_install
-APACHE_HTTPD_SRC_ROOT=${APACHE_HTTPD_SRC_TGZ%.tar.gz}
-
-OPENSSL_BUILDLOG=$(mktemp -p /tmp openssl_buildlog.XXXXXXXXXX)
-APACHE_HTTPD_BUILDLOG=$(mktemp -p /tmp httpd_buildlog.XXXXXXXXXX)
-
-cp $APACHE_HTTPD_MODSSL_NPN_PATCH_PATH $BUILDROOT/$APACHE_HTTPD_MODSSL_NPN_PATCH
-
-pushd $BUILDROOT >/dev/null
-
-download_file $OPENSSL_SRC_TGZ_URL $OPENSSL_SRC_TGZ de62b43dfcd858e66a74bee1c834e959
-download_file $APACHE_HTTPD_SRC_TGZ_URL $APACHE_HTTPD_SRC_TGZ 148eb08e731916a43a33a6ffa25f17c0
-
-echo ""
-
-uncompress_file $OPENSSL_SRC_TGZ
-uncompress_file $APACHE_HTTPD_SRC_TGZ
-
-if [ ! -f "$PROGRESS_DIR/modssl_patched" ]; then
- pushd $APACHE_HTTPD_SRC_ROOT >/dev/null
- echo "Applying Apache mod_ssl NPN patch ... "
- patch -p0 < $BUILDROOT/$APACHE_HTTPD_MODSSL_NPN_PATCH
- if [ $? -ne 0 ]; then
- echo "Failed to patch."
- do_cleanup
- fi
- echo "done"
- popd >/dev/null # $APACHE_HTTPD_SRC_ROOT
- touch "$PROGRESS_DIR/modssl_patched"
-else
- echo "Already applied Apache mod_ssl NPN patch."
-fi
-
-echo ""
-
-if [ ! -f "$PROGRESS_DIR/openssl_configured" ]; then
- pushd $OPENSSL_SRC_ROOT >/dev/null
- echo -n "Configuring OpenSSL ... "
- ./config no-shared -fPIC --openssldir=$BUILDROOT/$OPENSSL_INST_ROOT >> $OPENSSL_BUILDLOG
- if [ $? -ne 0 ]; then
- echo "Failed. Build log at $OPENSSL_BUILDLOG."
- do_cleanup
- fi
- echo "done"
- popd >/dev/null # $OPENSSL_SRC_ROOT
- touch "$PROGRESS_DIR/openssl_configured"
-else
- echo "Already configured OpenSSL."
-fi
-
-if [ ! -f "$PROGRESS_DIR/openssl_built" ]; then
- pushd $OPENSSL_SRC_ROOT >/dev/null
- echo -n "Building OpenSSL (this may take a while) ... "
- make install >> $OPENSSL_BUILDLOG 2>&1
- if [ $? -ne 0 ]; then
- echo "Failed. Build log at $OPENSSL_BUILDLOG."
- do_cleanup
- fi
- # A hacky fix that helps things build on CentOS:
- if grep -q CentOS /etc/issue; then
- sed --in-place 's/^Libs\.private: -ldl$/& -lcrypto/' \
- $BUILDROOT/$OPENSSL_INST_ROOT/lib/pkgconfig/openssl.pc
- fi
- echo "done"
- popd >/dev/null # $OPENSSL_SRC_ROOT
- touch "$PROGRESS_DIR/openssl_built"
-else
- echo "Already built OpenSSL."
-fi
-
-rm -f "$OPENSSL_BUILDLOG"
-
-echo ""
-
-if [ ! -f "$PROGRESS_DIR/modssl_configured" ]; then
- pushd $APACHE_HTTPD_SRC_ROOT >/dev/null
- echo -n "Configuring Apache mod_ssl ... "
-
- # OpenSSL, as of version 1.0.1, changed its pkg-config file to list
- # its dependent libraries in Libs.private. Prior to this, dependent
- # libraries were listed in Libs. This change in 1.0.1 is the right
- # thing for OpenSSL, but it breaks the Apache 2.2.x configure when
- # linking statically against OpenSSL, since it assumes that all
- # dependent libs are provided in the pkg config Libs directive. We
- # run a search-replace on the configure script to tell it to include
- # not only libraries in Libs, but also those in Libs.private:
- mv configure configure.bak
- sed 's/--libs-only-l openssl/--libs-only-l --static openssl/' configure.bak > configure
- chmod --reference=configure.bak configure
-
- ./configure --enable-ssl=shared --with-ssl=$BUILDROOT/$OPENSSL_INST_ROOT >> $APACHE_HTTPD_BUILDLOG
- if [ $? -ne 0 ]; then
- echo "Failed. Build log at $APACHE_HTTPD_BUILDLOG."
- do_cleanup
- fi
- echo "done"
- popd >/dev/null # $APACHE_HTTPD_SRC_ROOT
- touch "$PROGRESS_DIR/modssl_configured"
-else
- echo "Already configured Apache mod_ssl."
-fi
-
-if [ ! -f "$PROGRESS_DIR/modssl_built" ]; then
- pushd $APACHE_HTTPD_SRC_ROOT >/dev/null
- echo -n "Building Apache mod_ssl (this may take a while) ... "
- make >> $APACHE_HTTPD_BUILDLOG 2>&1
- if [ $? -ne 0 ]; then
- echo "Failed. Build log at $APACHE_HTTPD_BUILDLOG."
- do_cleanup
- fi
- echo "done"
- popd >/dev/null # $APACHE_HTTPD_SRC_ROOT
- touch "$PROGRESS_DIR/modssl_built"
-else
- echo "Already built Apache mod_ssl."
-fi
-
-rm -f "$APACHE_HTTPD_BUILDLOG"
-
-popd >/dev/null # $BUILDROOT
-
-MODSSL_SO_SRCPATH=$(find $BUILDROOT/$APACHE_HTTPD_SRC_ROOT -name mod_ssl.so)
-if [ $(echo $MODSSL_SO_SRCPATH | wc -l) -ne 1 ]; then
- echo "Found multiple mod_ssl.so's:"
- echo $MODSSL_SO_SRCPATH
- do_cleanup
-fi
-
-cp $MODSSL_SO_SRCPATH $MODSSL_SO_DESTPATH
-
-if [ $REMOVE_BUILDROOT -eq 1 ]; then
- rm -rf "$BUILDROOT"
-fi
-
-echo ""
-echo "Generated mod_ssl.so at $MODSSL_SO_DESTPATH."
+++ /dev/null
-COMPANY_FULLNAME=Google Inc.
-COMPANY_SHORTNAME=Google Inc.
-PRODUCT_FULLNAME=mod_spdy
-PRODUCT_SHORTNAME=mod_spdy
-COPYRIGHT=Copyright (C) 2012.
+++ /dev/null
-@@include@@variables.include
-
-APT_GET="`which apt-get 2> /dev/null`"
-APT_CONFIG="`which apt-config 2> /dev/null`"
-
-SOURCES_PREAMBLE="### THIS FILE IS AUTOMATICALLY CONFIGURED ###
-# You may comment out this entry, but any other modifications may be lost.\n"
-
-# Parse apt configuration and return requested variable value.
-apt_config_val() {
- APTVAR="$1"
- if [ -x "$APT_CONFIG" ]; then
- "$APT_CONFIG" dump | sed -e "/^$APTVAR /"'!d' -e "s/^$APTVAR \"\(.*\)\".*/\1/"
- fi
-}
-
-# Install the repository signing key (see also:
-# http://www.google.com/linuxrepositories/aboutkey.html)
-install_key() {
- APT_KEY="`which apt-key 2> /dev/null`"
- if [ -x "$APT_KEY" ]; then
- "$APT_KEY" add - >/dev/null 2>&1 <<KEYDATA
------BEGIN PGP PUBLIC KEY BLOCK-----
-Version: GnuPG v1.4.2.2 (GNU/Linux)
-
-mQGiBEXwb0YRBADQva2NLpYXxgjNkbuP0LnPoEXruGmvi3XMIxjEUFuGNCP4Rj/a
-kv2E5VixBP1vcQFDRJ+p1puh8NU0XERlhpyZrVMzzS/RdWdyXf7E5S8oqNXsoD1z
-fvmI+i9b2EhHAA19Kgw7ifV8vMa4tkwslEmcTiwiw8lyUl28Wh4Et8SxzwCggDcA
-feGqtn3PP5YAdD0km4S4XeMEAJjlrqPoPv2Gf//tfznY2UyS9PUqFCPLHgFLe80u
-QhI2U5jt6jUKN4fHauvR6z3seSAsh1YyzyZCKxJFEKXCCqnrFSoh4WSJsbFNc4PN
-b0V0SqiTCkWADZyLT5wll8sWuQ5ylTf3z1ENoHf+G3um3/wk/+xmEHvj9HCTBEXP
-78X0A/0Tqlhc2RBnEf+AqxWvM8sk8LzJI/XGjwBvKfXe+l3rnSR2kEAvGzj5Sg0X
-4XmfTg4Jl8BNjWyvm2Wmjfet41LPmYJKsux3g0b8yzQxeOA4pQKKAU3Z4+rgzGmf
-HdwCG5MNT2A5XxD/eDd+L4fRx0HbFkIQoAi1J3YWQSiTk15fw7RMR29vZ2xlLCBJ
-bmMuIExpbnV4IFBhY2thZ2UgU2lnbmluZyBLZXkgPGxpbnV4LXBhY2thZ2VzLWtl
-eW1hc3RlckBnb29nbGUuY29tPohjBBMRAgAjAhsDBgsJCAcDAgQVAggDBBYCAwEC
-HgECF4AFAkYVdn8CGQEACgkQoECDD3+sWZHKSgCfdq3HtNYJLv+XZleb6HN4zOcF
-AJEAniSFbuv8V5FSHxeRimHx25671az+uQINBEXwb0sQCACuA8HT2nr+FM5y/kzI
-A51ZcC46KFtIDgjQJ31Q3OrkYP8LbxOpKMRIzvOZrsjOlFmDVqitiVc7qj3lYp6U
-rgNVaFv6Qu4bo2/ctjNHDDBdv6nufmusJUWq/9TwieepM/cwnXd+HMxu1XBKRVk9
-XyAZ9SvfcW4EtxVgysI+XlptKFa5JCqFM3qJllVohMmr7lMwO8+sxTWTXqxsptJo
-pZeKz+UBEEqPyw7CUIVYGC9ENEtIMFvAvPqnhj1GS96REMpry+5s9WKuLEaclWpd
-K3krttbDlY1NaeQUCRvBYZ8iAG9YSLHUHMTuI2oea07Rh4dtIAqPwAX8xn36JAYG
-2vgLAAMFB/wKqaycjWAZwIe98Yt0qHsdkpmIbarD9fGiA6kfkK/UxjL/k7tmS4Vm
-CljrrDZkPSQ/19mpdRcGXtb0NI9+nyM5trweTvtPw+HPkDiJlTaiCcx+izg79Fj9
-KcofuNb3lPdXZb9tzf5oDnmm/B+4vkeTuEZJ//IFty8cmvCpzvY+DAz1Vo9rA+Zn
-cpWY1n6z6oSS9AsyT/IFlWWBZZ17SpMHu+h4Bxy62+AbPHKGSujEGQhWq8ZRoJAT
-G0KSObnmZ7FwFWu1e9XFoUCt0bSjiJWTIyaObMrWu/LvJ3e9I87HseSJStfw6fki
-5og9qFEkMrIrBCp3QGuQWBq/rTdMuwNFiEkEGBECAAkFAkXwb0sCGwwACgkQoECD
-D3+sWZF/WACfeNAu1/1hwZtUo1bR+MWiCjpvHtwAnA1R3IHqFLQ2X3xJ40XPuAyY
-/FJG
-=Quqp
------END PGP PUBLIC KEY BLOCK-----
-KEYDATA
- fi
-}
-
-# Set variables for the locations of the apt sources lists.
-find_apt_sources() {
- APTDIR=$(apt_config_val Dir)
- APTETC=$(apt_config_val 'Dir::Etc')
- APT_SOURCES="$APTDIR$APTETC$(apt_config_val 'Dir::Etc::sourcelist')"
- APT_SOURCESDIR="$APTDIR$APTETC$(apt_config_val 'Dir::Etc::sourceparts')"
-}
-
-# Update the Google repository if it's not set correctly.
-# Note: this doesn't necessarily enable the repository, it just makes sure the
-# correct settings are available in the sources list.
-# Returns:
-# 0 - no update necessary
-# 2 - error
-update_bad_sources() {
- if [ ! "$REPOCONFIG" ]; then
- return 0
- fi
-
- find_apt_sources
-
- SOURCELIST="$APT_SOURCESDIR/@@PACKAGE@@.list"
- # Don't do anything if the file isn't there, since that probably means the
- # user disabled it.
- if [ ! -r "$SOURCELIST" ]; then
- return 0
- fi
-
- # Basic check for active configurations (non-blank, non-comment lines).
- ACTIVECONFIGS=$(grep -v "^[[:space:]]*\(#.*\)\?$" "$SOURCELIST" 2>/dev/null)
-
- # Check if the correct repository configuration is in there.
- REPOMATCH=$(grep "^[[:space:]#]*\b$REPOCONFIG\b" "$SOURCELIST" \
- 2>/dev/null)
-
- # Check if the correct repository is disabled.
- MATCH_DISABLED=$(echo "$REPOMATCH" | grep "^[[:space:]]*#" 2>/dev/null)
-
- # Now figure out if we need to fix things.
- BADCONFIG=1
- if [ "$REPOMATCH" ]; then
- # If it's there and active, that's ideal, so nothing to do.
- if [ ! "$MATCH_DISABLED" ]; then
- BADCONFIG=0
- else
- # If it's not active, but neither is anything else, that's fine too.
- if [ ! "$ACTIVECONFIGS" ]; then
- BADCONFIG=0
- fi
- fi
- fi
-
- if [ $BADCONFIG -eq 0 ]; then
- return 0
- fi
-
- # At this point, either the correct configuration is completely missing, or
- # the wrong configuration is active. In that case, just abandon the mess and
- # recreate the file with the correct configuration. If there were no active
- # configurations before, create the new configuration disabled.
- DISABLE=""
- if [ ! "$ACTIVECONFIGS" ]; then
- DISABLE="#"
- fi
- printf "$SOURCES_PREAMBLE" > "$SOURCELIST"
- printf "$DISABLE$REPOCONFIG\n" >> "$SOURCELIST"
- if [ $? -eq 0 ]; then
- return 0
- fi
- return 2
-}
-
-# Add the Google repository to the apt sources.
-# Returns:
-# 0 - sources list was created
-# 2 - error
-create_sources_lists() {
- if [ ! "$REPOCONFIG" ]; then
- return 0
- fi
-
- find_apt_sources
-
- SOURCELIST="$APT_SOURCESDIR/@@PACKAGE@@.list"
- if [ -d "$APT_SOURCESDIR" ]; then
- printf "$SOURCES_PREAMBLE" > "$SOURCELIST"
- printf "$REPOCONFIG\n" >> "$SOURCELIST"
- if [ $? -eq 0 ]; then
- return 0
- fi
- fi
- return 2
-}
-
-# Remove our custom sources list file.
-# Returns:
-# 0 - successfully removed, or not configured
-# !0 - failed to remove
-clean_sources_lists() {
- if [ ! "$REPOCONFIG" ]; then
- return 0
- fi
-
- find_apt_sources
-
- rm -f "$APT_SOURCESDIR/@@PACKAGE@@.list" \
- "$APT_SOURCESDIR/@@PACKAGE@@-@@CHANNEL@@.list"
-}
-
-# Detect if the repo config was disabled by distro upgrade and enable if
-# necessary.
-handle_distro_upgrade() {
- if [ ! "$REPOCONFIG" ]; then
- return 0
- fi
-
- find_apt_sources
- SOURCELIST="$APT_SOURCESDIR/@@PACKAGE@@.list"
- if [ -r "$SOURCELIST" ]; then
- REPOLINE=$(grep -E "^[[:space:]]*#[[:space:]]*$REPOCONFIG[[:space:]]*# disabled on upgrade to .*" "$SOURCELIST")
- if [ $? -eq 0 ]; then
- sed -i -e "s,^[[:space:]]*#[[:space:]]*\($REPOCONFIG\)[[:space:]]*# disabled on upgrade to .*,\1," \
- "$SOURCELIST"
- LOGGER=$(which logger 2> /dev/null)
- if [ "$LOGGER" ]; then
- "$LOGGER" -t "$0" "Reverted repository modification: $REPOLINE."
- fi
- fi
- fi
-}
-
+++ /dev/null
-# Recursively replace @@include@@ template variables with the referenced file,
-# and write the resulting text to stdout.
-process_template_includes() {
- INCSTACK+="$1->"
- # Includes are relative to the file that does the include.
- INCDIR=$(dirname $1)
- # Clear IFS so 'read' doesn't trim whitespace
- local OLDIFS="$IFS"
- IFS=''
- while read -r LINE
- do
- INCLINE=$(sed -e '/^[[:space:]]*@@include@@/!d' <<<$LINE)
- if [ -n "$INCLINE" ]; then
- INCFILE=$(echo $INCLINE | sed -e "s#@@include@@\(.*\)#\1#")
- # Simple filename match to detect cyclic includes.
- CYCLE=$(sed -e "\#$INCFILE#"'!d' <<<$INCSTACK)
- if [ "$CYCLE" ]; then
- echo "ERROR: Possible cyclic include detected." 1>&2
- echo "$INCSTACK$INCFILE" 1>&2
- exit 1
- fi
- if [ ! -r "$INCDIR/$INCFILE" ]; then
- echo "ERROR: Couldn't read include file: $INCDIR/$INCFILE" 1>&2
- exit 1
- fi
- process_template_includes "$INCDIR/$INCFILE"
- else
- echo "$LINE"
- fi
- done < "$1"
- IFS="$OLDIFS"
- INCSTACK=${INCSTACK%"$1->"}
-}
-
-# Replace template variables (@@VARNAME@@) in the given template file. If a
-# second argument is given, save the processed text to that filename, otherwise
-# modify the template file in place.
-process_template() (
- # Don't worry if some of these substitution variables aren't set.
- # Note that this function is run in a sub-shell so we don't leak this
- # setting, since we still want unbound variables to be an error elsewhere.
- set +u
-
- local TMPLIN="$1"
- if [ -z "$2" ]; then
- local TMPLOUT="$TMPLIN"
- else
- local TMPLOUT="$2"
- fi
- # Process includes first so included text also gets substitutions.
- TMPLINCL="$(process_template_includes "$TMPLIN")"
- sed \
- -e "s#@@PACKAGE@@#${PACKAGE}#g" \
- -e "s#@@CHANNEL@@#${CHANNEL}#g" \
- -e "s#@@COMPANY_FULLNAME@@#${COMPANY_FULLNAME}#g" \
- -e "s#@@VERSION@@#${VERSION}#g" \
- -e "s#@@REVISION@@#${REVISION}#g" \
- -e "s#@@VERSIONFULL@@#${VERSIONFULL}#g" \
- -e "s#@@BUILDDIR@@#${BUILDDIR}#g" \
- -e "s#@@STAGEDIR@@#${STAGEDIR}#g" \
- -e "s#@@SCRIPTDIR@@#${SCRIPTDIR}#g" \
- -e "s#@@PRODUCTURL@@#${PRODUCTURL}#g" \
- -e "s#@@PREDEPENDS@@#${PREDEPENDS}#g" \
- -e "s#@@DEPENDS@@#${DEPENDS}#g" \
- -e "s#@@PROVIDES@@#${PROVIDES}#g" \
- -e "s#@@REPLACES@@#${REPLACES}#g" \
- -e "s#@@CONFLICTS@@#${CONFLICTS}#g" \
- -e "s#@@ARCHITECTURE@@#${HOST_ARCH}#g" \
- -e "s#@@MAINTNAME@@#${MAINTNAME}#g" \
- -e "s#@@MAINTMAIL@@#${MAINTMAIL}#g" \
- -e "s#@@REPOCONFIG@@#${REPOCONFIG}#g" \
- -e "s#@@SHORTDESC@@#${SHORTDESC}#g" \
- -e "s#@@FULLDESC@@#${FULLDESC}#g" \
- -e "s#@@APACHE_CONFDIR@@#${APACHE_CONFDIR}#g" \
- -e "s#@@APACHE_MODULEDIR@@#${APACHE_MODULEDIR}#g" \
- -e "s#@@APACHE_USER@@#${APACHE_USER}#g" \
- -e "s#@@MODSPDY_ENABLE_UPDATES@@#${MODSPDY_ENABLE_UPDATES}#g" \
- -e "s#@@COMMENT_OUT_DEFLATE@@#${COMMENT_OUT_DEFLATE}#g" \
- > "$TMPLOUT" <<< "$TMPLINCL"
-)
-
-# Setup the installation directory hierachy in the package staging area.
-prep_staging_common() {
- install -m 755 -d \
- "${STAGEDIR}${APACHE_CONFDIR}" \
- "${STAGEDIR}${APACHE_MODULEDIR}"
-}
-
-get_version_info() {
- # Default to a bogus low version, so if somebody creates and installs
- # a package with no version info, it won't prevent upgrading when
- # trying to install a properly versioned package (i.e. a proper
- # package will always be "newer").
- VERSION="0.0.0.0"
- # Use epoch timestamp so packages with bogus versions still increment
- # and will upgrade older bogus-versioned packages.
- REVISION=$(date +"%s")
- # Default to non-official build since official builds set this
- # properly.
- OFFICIAL_BUILD=0
-
- VERSIONFILE="${BUILDDIR}/installer/version.txt"
- if [ -f "${VERSIONFILE}" ]; then
- source "${VERSIONFILE}"
- VERSION="${MAJOR}.${MINOR}.${BUILD}.${PATCH}"
- REVISION="${LASTCHANGE}"
- fi
-}
-
-stage_install_common() {
- echo "Staging common install files in '${STAGEDIR}'..."
-
- # app and resources
- install -m 644 -s "${BUILDDIR}/libmod_spdy.so" "${STAGEDIR}${APACHE_MODULEDIR}/mod_spdy.so"
- install -m 644 -s "${BUILDDIR}/mod_ssl.so" "${STAGEDIR}${APACHE_MODULEDIR}/mod_ssl_with_npn.so"
-}
+++ /dev/null
-# 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.
-#
-# This file provides common configuration information for building
-# mod-spdy packages for various platforms.
-
-# Base name of the package.
-PACKAGE="mod-spdy"
-
-# Brief package description.
-SHORTDESC="Apache 2 module to enable SPDY support."
-
-# Detailed package description.
-FULLDESC="mod_spdy is an Apache module that allows an Apache server to support the SPDY protocol for serving HTTP resources."
-
-# Package maintainer information.
-MAINTNAME="mod_spdy developers"
-MAINTMAIL="mod-spdy-dev@googlegroups.com"
-PRODUCTURL="http://code.google.com/p/mod-spdy/"
+++ /dev/null
-#!/bin/sh
-#
-# 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.
-#
-# This script is part of the @@PACKAGE@@ package.
-#
-# It creates the repository configuration file for package updates, and it
-# monitors that config to see if it has been disabled by the overly aggressive
-# distro upgrade process (e.g. intrepid -> jaunty). When this situation is
-# detected, the respository will be re-enabled. If the respository is disabled
-# for any other reason, this won't re-enable it.
-#
-# This functionality can be controlled by creating the $DEFAULTS_FILE and
-# setting "repo_add_once" and/or "repo_reenable_on_distupgrade" to "true" or
-# "false" as desired. An empty $DEFAULTS_FILE is the same as setting both values
-# to "false".
-
-@@include@@apt.include
-
-## MAIN ##
-DEFAULTS_FILE="/etc/default/@@PACKAGE@@"
-if [ -r "$DEFAULTS_FILE" ]; then
- . "$DEFAULTS_FILE"
-fi
-
-if [ "$repo_add_once" = "true" ]; then
- install_key
- create_sources_lists
- RES=$?
- # Sources creation succeeded, so stop trying.
- if [ $RES -ne 2 ]; then
- sed -i -e 's/[[:space:]]*repo_add_once=.*/repo_add_once="false"/' "$DEFAULTS_FILE"
- fi
-else
- update_bad_sources
-fi
-
-if [ "$repo_reenable_on_distupgrade" = "true" ]; then
- handle_distro_upgrade
-fi
+++ /dev/null
-@@include@@variables.include
-
-# Install the repository signing key (see also:
-# http://www.google.com/linuxrepositories/aboutkey.html)
-install_rpm_key() {
- # Check to see if key already exists.
- rpm -q gpg-pubkey-7fac5991-4615767f > /dev/null 2>&1
- if [ "$?" -eq "0" ]; then
- # Key already exists
- return 0
- fi
- # This is to work around a bug in RPM 4.7.0. (see http://crbug.com/22312)
- rpm -q gpg-pubkey-7fac5991-45f06f46 > /dev/null 2>&1
- if [ "$?" -eq "0" ]; then
- # Key already exists
- return 0
- fi
-
- # RPM on Mandriva 2009 is dumb and does not understand "rpm --import -"
- TMPKEY=$(mktemp /tmp/google.sig.XXXXXX)
- if [ -n "$TMPKEY" ]; then
- cat > "$TMPKEY" <<KEYDATA
------BEGIN PGP PUBLIC KEY BLOCK-----
-Version: GnuPG v1.4.2.2 (GNU/Linux)
-
-mQGiBEXwb0YRBADQva2NLpYXxgjNkbuP0LnPoEXruGmvi3XMIxjEUFuGNCP4Rj/a
-kv2E5VixBP1vcQFDRJ+p1puh8NU0XERlhpyZrVMzzS/RdWdyXf7E5S8oqNXsoD1z
-fvmI+i9b2EhHAA19Kgw7ifV8vMa4tkwslEmcTiwiw8lyUl28Wh4Et8SxzwCggDcA
-feGqtn3PP5YAdD0km4S4XeMEAJjlrqPoPv2Gf//tfznY2UyS9PUqFCPLHgFLe80u
-QhI2U5jt6jUKN4fHauvR6z3seSAsh1YyzyZCKxJFEKXCCqnrFSoh4WSJsbFNc4PN
-b0V0SqiTCkWADZyLT5wll8sWuQ5ylTf3z1ENoHf+G3um3/wk/+xmEHvj9HCTBEXP
-78X0A/0Tqlhc2RBnEf+AqxWvM8sk8LzJI/XGjwBvKfXe+l3rnSR2kEAvGzj5Sg0X
-4XmfTg4Jl8BNjWyvm2Wmjfet41LPmYJKsux3g0b8yzQxeOA4pQKKAU3Z4+rgzGmf
-HdwCG5MNT2A5XxD/eDd+L4fRx0HbFkIQoAi1J3YWQSiTk15fw7RMR29vZ2xlLCBJ
-bmMuIExpbnV4IFBhY2thZ2UgU2lnbmluZyBLZXkgPGxpbnV4LXBhY2thZ2VzLWtl
-eW1hc3RlckBnb29nbGUuY29tPohjBBMRAgAjAhsDBgsJCAcDAgQVAggDBBYCAwEC
-HgECF4AFAkYVdn8CGQEACgkQoECDD3+sWZHKSgCfdq3HtNYJLv+XZleb6HN4zOcF
-AJEAniSFbuv8V5FSHxeRimHx25671az+uQINBEXwb0sQCACuA8HT2nr+FM5y/kzI
-A51ZcC46KFtIDgjQJ31Q3OrkYP8LbxOpKMRIzvOZrsjOlFmDVqitiVc7qj3lYp6U
-rgNVaFv6Qu4bo2/ctjNHDDBdv6nufmusJUWq/9TwieepM/cwnXd+HMxu1XBKRVk9
-XyAZ9SvfcW4EtxVgysI+XlptKFa5JCqFM3qJllVohMmr7lMwO8+sxTWTXqxsptJo
-pZeKz+UBEEqPyw7CUIVYGC9ENEtIMFvAvPqnhj1GS96REMpry+5s9WKuLEaclWpd
-K3krttbDlY1NaeQUCRvBYZ8iAG9YSLHUHMTuI2oea07Rh4dtIAqPwAX8xn36JAYG
-2vgLAAMFB/wKqaycjWAZwIe98Yt0qHsdkpmIbarD9fGiA6kfkK/UxjL/k7tmS4Vm
-CljrrDZkPSQ/19mpdRcGXtb0NI9+nyM5trweTvtPw+HPkDiJlTaiCcx+izg79Fj9
-KcofuNb3lPdXZb9tzf5oDnmm/B+4vkeTuEZJ//IFty8cmvCpzvY+DAz1Vo9rA+Zn
-cpWY1n6z6oSS9AsyT/IFlWWBZZ17SpMHu+h4Bxy62+AbPHKGSujEGQhWq8ZRoJAT
-G0KSObnmZ7FwFWu1e9XFoUCt0bSjiJWTIyaObMrWu/LvJ3e9I87HseSJStfw6fki
-5og9qFEkMrIrBCp3QGuQWBq/rTdMuwNFiEkEGBECAAkFAkXwb0sCGwwACgkQoECD
-D3+sWZF/WACfeNAu1/1hwZtUo1bR+MWiCjpvHtwAnA1R3IHqFLQ2X3xJ40XPuAyY
-/FJG
-=Quqp
------END PGP PUBLIC KEY BLOCK-----
-KEYDATA
- rpm --import "$TMPKEY"
- rc=$?
- rm -f "$TMPKEY"
- if [ "$rc" -eq "0" ]; then
- return 0
- fi
- fi
- return 1
-}
-
-determine_rpm_package_manager() {
- local RELEASE
- LSB_RELEASE="$(which lsb_release 2> /dev/null)"
- if [ -x "$LSB_RELEASE" ]; then
- RELEASE=$(lsb_release -i 2> /dev/null)
- case $DISTRIB_ID in
- "Fedora")
- PACKAGEMANAGER=yum
- ;;
- "MandrivaLinux")
- PACKAGEMANAGER=urpmi
- ;;
- "SUSE LINUX")
- PACKAGEMANAGER=yast
- ;;
- esac
- fi
-
- if [ "$PACKAGEMANAGER" ]; then
- return
- fi
-
- # Fallback methods that are probably unnecessary on modern systems.
- if [ -f "/etc/lsb-release" ]; then
- # file missing on Fedora, does not contain DISTRIB_ID on OpenSUSE.
- eval $(sed -e '/DISTRIB_ID/!d' /etc/lsb-release)
- case $DISTRIB_ID in
- MandrivaLinux)
- PACKAGEMANAGER=urpmi
- ;;
- esac
- fi
-
- if [ "$PACKAGEMANAGER" ]; then
- return
- fi
-
- if [ -f "/etc/fedora-release" ] || [ -f "/etc/redhat-release" ]; then
- PACKAGEMANAGER=yum
- elif [ -f "/etc/SuSE-release" ]; then
- PACKAGEMANAGER=yast
- elif [ -f "/etc/mandriva-release" ]; then
- PACKAGEMANAGER=urpmi
- fi
-}
-
-DEFAULT_ARCH="@@ARCHITECTURE@@"
-YUM_REPO_FILE="/etc/yum.repos.d/@@PACKAGE@@.repo"
-ZYPPER_REPO_FILE="/etc/zypp/repos.d/@@PACKAGE@@.repo"
-URPMI_REPO_FILE="/etc/urpmi/urpmi.cfg"
-
-install_yum() {
- install_rpm_key
-
- if [ ! "$REPOCONFIG" ]; then
- return 0
- fi
-
- if [ -d "/etc/yum.repos.d" ]; then
-cat > "$YUM_REPO_FILE" << REPOCONTENT
-[@@PACKAGE@@]
-name=@@PACKAGE@@
-baseurl=$REPOCONFIG/$DEFAULT_ARCH
-enabled=1
-gpgcheck=1
-REPOCONTENT
- fi
-}
-
-# This is called by the cron job, rather than in the RPM postinstall.
-# We cannot do this during the install when urpmi is running due to
-# database locking. We also need to enable the repository, and we can
-# only do that while we are online.
-# see: https://qa.mandriva.com/show_bug.cgi?id=31893
-configure_urpmi() {
- if [ ! "$REPOCONFIG" ]; then
- return 0
- fi
-
- urpmq --list-media | grep -q -s "^@@PACKAGE@@$"
- if [ "$?" -eq "0" ]; then
- # Repository already configured
- return 0
- fi
- urpmi.addmedia --update \
- "@@PACKAGE@@" "$REPOCONFIG/$DEFAULT_ARCH"
-}
-
-install_urpmi() {
- # urpmi not smart enough to pull media_info/pubkey from the repository?
- install_rpm_key
-
- # Defer urpmi.addmedia to configure_urpmi() in the cron job.
- # See comment there.
- #
- # urpmi.addmedia --update \
- # "@@PACKAGE@@" "$REPOCONFIG/$DEFAULT_ARCH"
-}
-
-install_yast() {
- if [ ! "$REPOCONFIG" ]; then
- return 0
- fi
-
- # We defer adding the key to later. See comment in the cron job.
-
- # Ideally, we would run: zypper addrepo -t YUM -f \
- # "$REPOCONFIG/$DEFAULT_ARCH" "@@PACKAGE@@"
- # but that does not work when zypper is running.
- if [ -d "/etc/zypp/repos.d" ]; then
-cat > "$ZYPPER_REPO_FILE" << REPOCONTENT
-[@@PACKAGE@@]
-name=@@PACKAGE@@
-enabled=1
-autorefresh=1
-baseurl=$REPOCONFIG/$DEFAULT_ARCH
-type=rpm-md
-keeppackages=0
-REPOCONTENT
- fi
-}
-
-# Check if the automatic repository configuration is done, so we know when to
-# stop trying.
-verify_install() {
- # It's probably enough to see that the repo configs have been created. If they
- # aren't configured properly, update_bad_repo should catch that when it's run.
- case $1 in
- "yum")
- [ -f "$YUM_REPO_FILE" ]
- ;;
- "yast")
- [ -f "$ZYPPER_REPO_FILE" ]
- ;;
- "urpmi")
- urpmq --list-url | grep -q -s "\b@@PACKAGE@@\b"
- ;;
- esac
-}
-
-# Update the Google repository if it's not set correctly.
-update_bad_repo() {
- if [ ! "$REPOCONFIG" ]; then
- return 0
- fi
-
- determine_rpm_package_manager
-
- case $PACKAGEMANAGER in
- "yum")
- update_repo_file "$YUM_REPO_FILE"
- ;;
- "yast")
- update_repo_file "$ZYPPER_REPO_FILE"
- ;;
- "urpmi")
- update_urpmi_cfg
- ;;
- esac
-}
-
-update_repo_file() {
- REPO_FILE="$1"
-
- # Don't do anything if the file isn't there, since that probably means the
- # user disabled it.
- if [ ! -r "$REPO_FILE" ]; then
- return 0
- fi
-
- # Check if the correct repository configuration is in there.
- REPOMATCH=$(grep "^baseurl=$REPOCONFIG/$DEFAULT_ARCH" "$REPO_FILE" \
- 2>/dev/null)
- # If it's there, nothing to do
- if [ "$REPOMATCH" ]; then
- return 0
- fi
-
- # Check if it's there but disabled by commenting out (as opposed to using the
- # 'enabled' setting).
- MATCH_DISABLED=$(grep "^[[:space:]]*#.*baseurl=$REPOCONFIG/$DEFAULT_ARCH" \
- "$REPO_FILE" 2>/dev/null)
- if [ "$MATCH_DISABLED" ]; then
- # It's OK for it to be disabled, as long as nothing bogus is enabled in its
- # place.
- ACTIVECONFIGS=$(grep "^baseurl=.*" "$REPO_FILE" 2>/dev/null)
- if [ ! "$ACTIVECONFIGS" ]; then
- return 0
- fi
- fi
-
- # If we get here, the correct repository wasn't found, or something else is
- # active, so fix it. This assumes there is a 'baseurl' setting, but if not,
- # then that's just another way of disabling, so we won't try to add it.
- sed -i -e "s,^baseurl=.*,baseurl=$REPOCONFIG/$DEFAULT_ARCH," "$REPO_FILE"
-}
-
-update_urpmi_cfg() {
- REPOCFG=$(urpmq --list-url | grep "\b@@PACKAGE@@\b")
- if [ ! "$REPOCFG" ]; then
- # Don't do anything if the repo isn't there, since that probably means the
- # user deleted it.
- return 0
- fi
-
- # See if it's the right repo URL
- REPOMATCH=$(echo "$REPOCFG" | grep "\b$REPOCONFIG/$DEFAULT_ARCH\b")
- # If so, nothing to do
- if [ "$REPOMATCH" ]; then
- return 0
- fi
-
- # Looks like it's the wrong URL, so recreate it.
- urpmi.removemedia "@@PACKAGE@@" && \
- urpmi.addmedia --update "@@PACKAGE@@" "$REPOCONFIG/$DEFAULT_ARCH"
-}
-
-# We only remove the repository configuration during a purge. Since RPM has
-# no equivalent to dpkg --purge, the code below is actually never used. We
-# keep it only for reference purposes, should we ever need it.
-#
-#remove_yum() {
-# rm -f "$YUM_REPO_FILE"
-#}
-#
-#remove_urpmi() {
-# # Ideally, we would run: urpmi.removemedia "@@PACKAGE@@"
-# # but that does not work when urpmi is running.
-# # Sentinel comment text does not work either because urpmi.update removes
-# # all comments. So we just delete the entry that matches what we originally
-# # inserted. If such an entry was added manually, that's tough luck.
-# if [ -f "$URPMI_REPO_FILE" ]; then
-# sed -i '\_^@@PACKAGE@@ $REPOCONFIG/$DEFAULT_ARCH {$_,/^}$/d' "$URPMI_REPO_FILE"
-# fi
-#}
-#
-#remove_yast() {
-# # Ideally, we would run: zypper removerepo "@@PACKAGE@@"
-# # but that does not work when zypper is running.
-# rm -f /etc/zypp/repos.d/@@PACKAGE@@.repo
-#}
+++ /dev/null
-#!/bin/sh
-#
-# 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.
-#
-# This script is part of the @@PACKAGE@@ package.
-#
-# It creates the repository configuration file for package updates, since
-# we cannot do this during the @@PACKAGE@@ installation since the repository
-# is locked.
-#
-# This functionality can be controlled by creating the $DEFAULTS_FILE and
-# setting "repo_add_once" to "true" or "false" as desired. An empty
-# $DEFAULTS_FILE is the same as setting the value to "false".
-
-@@include@@rpm.include
-
-## MAIN ##
-DEFAULTS_FILE="/etc/default/@@PACKAGE@@"
-if [ -r "$DEFAULTS_FILE" ]; then
- . "$DEFAULTS_FILE"
-fi
-
-if [ "$repo_add_once" = "true" ]; then
- determine_rpm_package_manager
-
- case $PACKAGEMANAGER in
- "urpmi")
- # We need to configure urpmi after the install has finished.
- # See configure_urpmi() for details.
- configure_urpmi
- ;;
- "yast")
- # It looks as though yast/zypper has a lock on the RPM DB during
- # postinstall, so we cannot add the signing key with install_rpm_key().
- # Instead, we attempt to do this here. If the user attempt to update before
- # the cron job imports the key, Yast will grab the key from our server and
- # prompt the user to accept the key.
- install_rpm_key
- ;;
- esac
-
- if [ $? -eq 0 ]; then
- # Before we quit auto-configuration, check that everything looks sane, since
- # part of this happened during package install and we don't have the return
- # value of that process.
- verify_install $PACKAGEMANAGER
- if [ $? -eq 0 ]; then
- sed -i -e 's/[[:space:]]*repo_add_once=.*/repo_add_once="false"/' \
- "$DEFAULTS_FILE"
- fi
- fi
-else
- update_bad_repo
-fi
+++ /dev/null
-<IfModule spdy_module>
- # Turn on mod_spdy. To completely disable mod_spdy, you can set
- # this to "off".
- SpdyEnabled on
-
- # In order to support concurrent multiplexing of requests over a
- # single connection, mod_spdy maintains its own thread pool in
- # each Apache child process for processing requests. The default
- # size of this thread pool is very conservative; you can override
- # it with a larger value (as below) to increase concurrency, at
- # the possible cost of increased memory usage.
- #
- #SpdyMaxThreadsPerProcess 30
-
- # Memory usage can also be affected by the maximum number of
- # simultaneously open SPDY streams permitted for each client
- # connection. Ideally, this limit should be set as high as
- # possible, but you can tweak it as necessary to limit memory
- # consumption.
- #
- #SpdyMaxStreamsPerConnection 100
-</IfModule>
+++ /dev/null
-LoadModule spdy_module @@APACHE_MODULEDIR@@/mod_spdy.so
+++ /dev/null
-# This version of ssl.load was placed here because you installed mod_spdy.
-
-# Using mod_spdy requires using a patched version of mod_ssl that provides
-# hooks into the Next Protocol Negotiation (NPN) data from the SSL handshake.
-# Thus, the mod_spdy package installs mod_ssl_with_npn.so, which is exactly
-# mod_ssl but with the following (small) patch applied:
-# https://issues.apache.org/bugzilla/attachment.cgi?id=27969
-
-LoadModule ssl_module @@APACHE_MODULEDIR@@/mod_ssl_with_npn.so
-
-# If you'd like to go back to using the original, unpatched version of mod_ssl,
-# simply comment out the above line and uncomment the below line. However,
-# beware that mod_spdy will probably then cease to function.
-
-#LoadModule ssl_module @@APACHE_MODULEDIR@@/mod_ssl.so
+++ /dev/null
-#!/bin/sh
-#
-# 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.
-
-# TODO
-# - handle other distros (e.g. non-apt).
-
-@@include@@apt.include
-
-if [ -x "$APT_GET" ]; then
- update_sources_lists
- # If the repo was just added, force a cache update.
- if [ $? -eq 1 ]; then
- install_key
- "$APT_GET" -qq update
- fi
-
- # TODO(mmoss) detect if apt cache is stale (> 1 day) and force update?
-
- # Just try to install the packge. If it's already installed, apt-get won't do
- # anything.
- "$APT_GET" install -y -q @@PACKAGE@@
-fi
-
+++ /dev/null
-# System-wide package configuration.
-DEFAULTS_FILE="/etc/default/@@PACKAGE@@"
-
-# sources.list setting for @@PACKAGE@@ updates.
-REPOCONFIG="@@REPOCONFIG@@"
+++ /dev/null
-#!/bin/bash
-#
-# 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.
-
-set -e
-if [ "$VERBOSE" ]; then
- set -x
-fi
-set -u
-
-# Create the Debian changelog file needed by dpkg-gencontrol. This just adds a
-# placeholder change, indicating it is the result of an automatic build.
-gen_changelog() {
- rm -f "${DEB_CHANGELOG}"
- process_template "${SCRIPTDIR}/changelog.template" "${DEB_CHANGELOG}"
- debchange -a --nomultimaint -m --changelog "${DEB_CHANGELOG}" \
- --distribution UNRELEASED "automatic build"
-}
-
-# Create the Debian control file needed by dpkg-deb.
-gen_control() {
- dpkg-gencontrol -v"${VERSIONFULL}" -c"${DEB_CONTROL}" -l"${DEB_CHANGELOG}" \
- -f"${DEB_FILES}" -p"${PACKAGE}-${CHANNEL}" -P"${STAGEDIR}" -T"${DEB_SUBST}" \
- -O > "${STAGEDIR}/DEBIAN/control"
- rm -f "${DEB_CONTROL}"
-}
-
-# Create the Debian substvars file needed by dpkg-gencontrol.
-gen_substvars() {
- # dpkg-shlibdeps requires a control file in debian/control, so we're
- # forced to prepare a fake debian directory.
- mkdir "${SUBSTFILEDIR}/debian"
- cp "${DEB_CONTROL}" "${SUBSTFILEDIR}/debian"
- pushd "${SUBSTFILEDIR}" >/dev/null
- dpkg-shlibdeps "${STAGEDIR}${APACHE_MODULEDIR}/mod_spdy.so" \
- -O >> "${DEB_SUBST}" 2>/dev/null
- popd >/dev/null
-}
-
-# Setup the installation directory hierachy in the package staging area.
-prep_staging_debian() {
- prep_staging_common
- install -m 755 -d "${STAGEDIR}/DEBIAN" \
- "${STAGEDIR}/etc/cron.daily"
-}
-
-# Put the package contents in the staging area.
-stage_install_debian() {
- prep_staging_debian
- stage_install_common
- echo "Staging Debian install files in '${STAGEDIR}'..."
- process_template "${BUILDDIR}/install/common/repo.cron" \
- "${STAGEDIR}/etc/cron.daily/${PACKAGE}"
- chmod 755 "${STAGEDIR}/etc/cron.daily/${PACKAGE}"
- process_template "${BUILDDIR}/install/debian/preinst" \
- "${STAGEDIR}/DEBIAN/preinst"
- chmod 755 "${STAGEDIR}/DEBIAN/preinst"
- process_template "${BUILDDIR}/install/debian/postinst" \
- "${STAGEDIR}/DEBIAN/postinst"
- chmod 755 "${STAGEDIR}/DEBIAN/postinst"
- process_template "${BUILDDIR}/install/debian/prerm" \
- "${STAGEDIR}/DEBIAN/prerm"
- chmod 755 "${STAGEDIR}/DEBIAN/prerm"
- process_template "${BUILDDIR}/install/debian/postrm" \
- "${STAGEDIR}/DEBIAN/postrm"
- chmod 755 "${STAGEDIR}/DEBIAN/postrm"
- process_template "${BUILDDIR}/install/debian/conffiles.template" \
- "${STAGEDIR}/DEBIAN/conffiles"
- chmod 644 "${STAGEDIR}/DEBIAN/conffiles"
- process_template "${BUILDDIR}/install/common/spdy.load.template" \
- "${STAGEDIR}${APACHE_CONFDIR}/spdy.load"
- chmod 644 "${STAGEDIR}${APACHE_CONFDIR}/spdy.load"
- process_template "${BUILDDIR}/install/common/spdy.conf.template" \
- "${STAGEDIR}${APACHE_CONFDIR}/spdy.conf"
- chmod 644 "${STAGEDIR}${APACHE_CONFDIR}/spdy.conf"
-}
-
-# Build the deb file within a fakeroot.
-do_package_in_fakeroot() {
- FAKEROOTFILE=$(mktemp -t fakeroot.tmp.XXXXXX) || exit 1
- fakeroot -i "${FAKEROOTFILE}" -- \
- dpkg-deb -b "${STAGEDIR}" .
- rm -f "${FAKEROOTFILE}"
-}
-
-# Actually generate the package file.
-do_package() {
- export HOST_ARCH="$1"
- echo "Packaging ${HOST_ARCH}..."
- PREDEPENDS="$COMMON_PREDEPS"
- DEPENDS="${COMMON_DEPS}"
- gen_changelog
- process_template "${SCRIPTDIR}/control.template" "${DEB_CONTROL}"
- export DEB_HOST_ARCH="${HOST_ARCH}"
- gen_substvars
- if [ -f "${DEB_CONTROL}" ]; then
- gen_control
- fi
-
- do_package_in_fakeroot
-}
-
-# Remove temporary files and unwanted packaging output.
-cleanup() {
- echo "Cleaning..."
- rm -rf "${STAGEDIR}"
- rm -rf "${TMPFILEDIR}"
- rm -rf "${SUBSTFILEDIR}"
-}
-
-usage() {
- echo "usage: $(basename $0) [-c channel] [-a target_arch] [-o 'dir'] [-b 'dir']"
- echo "-c channel the package channel (unstable, beta, stable)"
- echo "-a arch package architecture (ia32 or x64)"
- echo "-o dir package output directory [${OUTPUTDIR}]"
- echo "-b dir build input directory [${BUILDDIR}]"
- echo "-h this help message"
-}
-
-# Check that the channel name is one of the allowable ones.
-verify_channel() {
- case $CHANNEL in
- stable )
- CHANNEL=stable
- ;;
- unstable|dev|alpha )
- CHANNEL=unstable
- ;;
- testing|beta )
- CHANNEL=beta
- ;;
- * )
- echo
- echo "ERROR: '$CHANNEL' is not a valid channel type."
- echo
- exit 1
- ;;
- esac
-}
-
-process_opts() {
- while getopts ":o:b:c:a:h" OPTNAME
- do
- case $OPTNAME in
- o )
- OUTPUTDIR="$OPTARG"
- mkdir -p "${OUTPUTDIR}"
- ;;
- b )
- BUILDDIR=$(readlink -f "${OPTARG}")
- ;;
- c )
- CHANNEL="$OPTARG"
- ;;
- a )
- TARGETARCH="$OPTARG"
- ;;
- h )
- usage
- exit 0
- ;;
- \: )
- echo "'-$OPTARG' needs an argument."
- usage
- exit 1
- ;;
- * )
- echo "invalid command-line option: $OPTARG"
- usage
- exit 1
- ;;
- esac
- done
-}
-
-#=========
-# MAIN
-#=========
-
-SCRIPTDIR=$(readlink -f "$(dirname "$0")")
-OUTPUTDIR="${PWD}"
-STAGEDIR=$(mktemp -d -t deb.build.XXXXXX) || exit 1
-TMPFILEDIR=$(mktemp -d -t deb.tmp.XXXXXX) || exit 1
-SUBSTFILEDIR=$(mktemp -d -t deb.subst.XXXXXX) || exit 1
-DEB_CHANGELOG="${TMPFILEDIR}/changelog"
-DEB_FILES="${TMPFILEDIR}/files"
-DEB_CONTROL="${TMPFILEDIR}/control"
-DEB_SUBST="${SUBSTFILEDIR}/debian/substvars"
-CHANNEL="beta"
-# Default target architecture to same as build host.
-if [ "$(uname -m)" = "x86_64" ]; then
- TARGETARCH="x64"
-else
- TARGETARCH="ia32"
-fi
-
-# call cleanup() on exit
-trap cleanup 0
-process_opts "$@"
-if [ ! "$BUILDDIR" ]; then
- BUILDDIR=$(readlink -f "${BUILDDIR}/install/../mod-spdy-release/src/out/Release")
-fi
-
-source ${BUILDDIR}/install/common/installer.include
-
-get_version_info
-VERSIONFULL="${VERSION}-r${REVISION}"
-
-source "${BUILDDIR}/install/common/mod-spdy.info"
-eval $(sed -e "s/^\([^=]\+\)=\(.*\)$/export \1='\2'/" \
- "${BUILDDIR}/install/common/BRANDING")
-
-REPOCONFIG="deb http://dl.google.com/linux/${PACKAGE#google-}/deb/ stable main"
-verify_channel
-
-# Some Debian packaging tools want these set.
-export DEBFULLNAME="${MAINTNAME}"
-export DEBEMAIL="${MAINTMAIL}"
-
-# Make everything happen in the OUTPUTDIR.
-cd "${OUTPUTDIR}"
-
-COMMON_DEPS="apache2.2-common"
-COMMON_PREDEPS="dpkg (>= 1.14.0)"
-REPLACES=""
-
-APACHE_MODULEDIR="/usr/lib/apache2/modules"
-APACHE_CONFDIR="/etc/apache2/mods-available"
-APACHE_USER="www-data"
-COMMENT_OUT_DEFLATE=
-
-case "$TARGETARCH" in
- ia32 )
- stage_install_debian
- do_package "i386"
- ;;
- x64 )
- stage_install_debian
- do_package "amd64"
- ;;
- * )
- echo
- echo "ERROR: Don't know how to build DEBs for '$TARGETARCH'."
- echo
- exit 1
- ;;
-esac
+++ /dev/null
-@@PACKAGE@@-@@CHANNEL@@ (@@VERSIONFULL@@) UNRELEASED; urgency=low
- * No changes
-
- -- @@MAINTNAME@@ <@@MAINTMAIL@@> Wed, 20 Oct 2010 14:54:35 -0800
+++ /dev/null
-/etc/apache2/mods-available/spdy.load
-/etc/apache2/mods-available/spdy.conf
-/etc/cron.daily/@@PACKAGE@@
+++ /dev/null
-Source: @@PACKAGE@@-@@CHANNEL@@
-Section: httpd
-Priority: optional
-Maintainer: @@MAINTNAME@@ <@@MAINTMAIL@@>
-Build-Depends: dpkg-dev, devscripts, fakeroot
-Standards-Version: 3.8.0
-
-Package: @@PACKAGE@@-@@CHANNEL@@
-Provides: @@PROVIDES@@
-Replaces: @@REPLACES@@
-Conflicts: @@CONFLICTS@@
-Pre-Depends: @@PREDEPENDS@@
-Depends: ${shlibs:Depends}, @@DEPENDS@@
-Architecture: @@ARCHITECTURE@@
-Description: @@SHORTDESC@@
- @@FULLDESC@@
+++ /dev/null
-#!/bin/sh
-
-# Based on postinst from Chromium and Google Talk.
-
-@@include@@../common/apt.include
-
-MODSPDY_ENABLE_UPDATES=@@MODSPDY_ENABLE_UPDATES@@
-
-case "$1" in
- configure)
- if [ -n "${MODSPDY_ENABLE_UPDATES}" -a ! -e "$DEFAULTS_FILE" ]; then
- echo 'repo_add_once="true"' > "$DEFAULTS_FILE"
- echo 'repo_reenable_on_distupgrade="true"' >> "$DEFAULTS_FILE"
- fi
-
- # Run the cron job immediately to perform repository
- # configuration.
- nohup sh /etc/cron.daily/@@PACKAGE@@ > /dev/null 2>&1 &
-
- test ! -e /etc/apache2/mods-enabled/spdy.load && \
- a2enmod spdy
- ;;
- abort-upgrade|abort-remove|abort-deconfigure)
- ;;
- *)
- echo "postinst called with unknown argument \`$1'" >&2
- exit 1
- ;;
-esac
-
-set -e # If any command fails from here on, the whole scripts fails.
-
-# Regardless of what argument postinst is called with, we should make sure at
-# this point that we're set up to load our version of mod_ssl. Note that if we
-# upgrade mod-spdy, the old package's prerm will first get called, which will
-# undo changes to ssl.load, and then we'll redo them here. This is good, in
-# case we ever need to change the way we modify ssl.load.
-if [ -f "@@APACHE_CONFDIR@@/ssl.load" ]; then
- # Don't do anything if the magic "MOD_SPDY" marker is already present in the
- # file; this helps ensure that this prerm script is idempotent. See
- # http://www.debian.org/doc/debian-policy/ch-maintainerscripts.html#s-idempotency
- # for why this is important.
- if ! grep -q 'MOD_SPDY' @@APACHE_CONFDIR@@/ssl.load; then
- # First, comment out all lines in the file, using a special prefix. We
- # will look for that prefix later when we uninstall.
- sed --in-place 's/^.*$/#ORIG# &/' @@APACHE_CONFDIR@@/ssl.load
- # Next, append a new LoadModule line to the file, with some explanitory
- # comments. The first line we append contains the magic marker "MOD_SPDY",
- # which we look for in the prerm script so that we can remove the below
- # text when we uninstall.
- cat >> @@APACHE_CONFDIR@@/ssl.load <<EOF
-########## MOD_SPDY CHANGES BELOW ##########
-# If mod_spdy is uninstalled, this file will be restored to its original form
-# by deleting everything below here and uncommenting everything above.
-
-# Using mod_spdy requires using a patched version of mod_ssl that provides
-# hooks into the Next Protocol Negotiation (NPN) data from the SSL handshake.
-# Thus, the mod_spdy package installs mod_ssl_with_npn.so, which is exactly
-# mod_ssl but with the following (small) patch applied:
-# https://issues.apache.org/bugzilla/attachment.cgi?id=27969
-
-LoadModule ssl_module @@APACHE_MODULEDIR@@/mod_ssl_with_npn.so
-EOF
- fi
-fi
-
-exit 0
+++ /dev/null
-#!/bin/sh
-#
-# 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.
-
-action="$1"
-
-# Only do complete clean-up on purge.
-if [ "$action" != "purge" ] ; then
- exit 0
-fi
-
-@@include@@../common/apt.include
-
-# Only remove the defaults file if it is not empty. An empty file was probably
-# put there by the sysadmin to disable automatic repository configuration, as
-# per the instructions on the package download page.
-if [ -s "$DEFAULTS_FILE" ]; then
- # Make sure the package defaults are removed before the repository config,
- # otherwise it could result in the repository config being removed, but the
- # package defaults remain and are set to not recreate the repository config.
- # In that case, future installs won't recreate it and won't get auto-updated.
- rm "$DEFAULTS_FILE" || exit 1
-fi
-# Remove any Google repository added by the package.
-clean_sources_lists
+++ /dev/null
-#!/bin/sh
-
-exit 0
+++ /dev/null
-#!/bin/sh
-
-case "$1" in
- remove)
- test -e /etc/apache2/mods-enabled/spdy.load && a2dismod spdy
- ;;
- upgrade|deconfigure|failed-upgrade)
- ;;
- *)
- echo "prerm called with unknown argument \`$1'" >&2
- exit 1
- ;;
-esac
-
-set -e # If any command fails from here on, the whole scripts fails.
-
-# Regardless of the argument prerm is called with, we should undo our changes
-# to ssl.load. If we're upgrading to a newer version of mod_spdy, the new
-# package will redo its changes to ssl.load in its postinst script. See
-# http://www.debian.org/doc/debian-policy/ch-maintainerscripts.html#s-unpackphase
-# for details.
-if [ -f "@@APACHE_CONFDIR@@/ssl.load" ]; then
- # Don't do anything if we don't see the magic "MOD_SPDY" marker; this helps
- # ensure that this prerm script is idempotent. See
- # http://www.debian.org/doc/debian-policy/ch-maintainerscripts.html#s-idempotency
- # for why this is important.
- if grep -q 'MOD_SPDY' @@APACHE_CONFDIR@@/ssl.load; then
- # First, we uncomment any line that starts with "#ORIG# " (we use that
- # particular prefix, to reduce the chances that we break the file if the
- # user has added their own comments to the file for some reason), up until
- # we see the "MOD_SPDY" marker. Second, we delete the line containing the
- # "MOD_SPDY" marker and all lines thereafter, thus removing the stuff we
- # appended to the file in the postinst script.
- sed --in-place \
- -e '1,/MOD_SPDY/ s/^#ORIG# \(.*\)$/\1/' \
- -e '/MOD_SPDY/,$ d' \
- @@APACHE_CONFDIR@@/ssl.load
- fi
-fi
-
-exit 0
+++ /dev/null
-#!/bin/bash
-#
-# 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.
-
-set -e
-if [ "$VERBOSE" ]; then
- set -x
-fi
-set -u
-
-gen_spec() {
- rm -f "${SPEC}"
- process_template "${SCRIPTDIR}/mod-spdy.spec.template" "${SPEC}"
-}
-
-# Setup the installation directory hierachy in the package staging area.
-prep_staging_rpm() {
- prep_staging_common
- install -m 755 -d "${STAGEDIR}/etc/cron.daily"
-}
-
-# Put the package contents in the staging area.
-stage_install_rpm() {
- prep_staging_rpm
- stage_install_common
- echo "Staging RPM install files in '${STAGEDIR}'..."
- process_template "${BUILDDIR}/install/common/rpmrepo.cron" \
- "${STAGEDIR}/etc/cron.daily/${PACKAGE}"
- chmod 755 "${STAGEDIR}/etc/cron.daily/${PACKAGE}"
-
- # For CentOS, the load and conf files are combined into a single
- # 'conf' file. So we install the load template as the conf file, and
- # then concatenate the actual conf file.
- process_template "${BUILDDIR}/install/common/spdy.load.template" \
- "${STAGEDIR}${APACHE_CONFDIR}/spdy.conf"
- process_template "${BUILDDIR}/install/common/spdy.conf.template" \
- "${BUILDDIR}/install/common/spdy.conf"
- cat "${BUILDDIR}/install/common/spdy.conf" >> \
- "${STAGEDIR}${APACHE_CONFDIR}/spdy.conf"
- chmod 644 "${STAGEDIR}${APACHE_CONFDIR}/spdy.conf"
-
- # Our conf file for loading mod_ssl_with_npn.so must come alphabetically
- # before the built-in ssl.conf file, so we can't call it "ssl_with_npn.conf".
- # Since all it will do is load the module (not configure it),
- # "load_ssl_with_npn.conf" seems like an appropriate name.
- process_template "${BUILDDIR}/install/common/ssl.load.template" \
- "${STAGEDIR}${APACHE_CONFDIR}/load_ssl_with_npn.conf"
- chmod 644 "${STAGEDIR}${APACHE_CONFDIR}/load_ssl_with_npn.conf"
-}
-
-# Actually generate the package file.
-do_package() {
- echo "Packaging ${HOST_ARCH}..."
- PROVIDES="${PACKAGE}"
- local REPS="$REPLACES"
- REPLACES=""
- for rep in $REPS; do
- if [ -z "$REPLACES" ]; then
- REPLACES="$PACKAGE-$rep"
- else
- REPLACES="$REPLACES $PACKAGE-$rep"
- fi
- done
-
- # If we specify a dependecy of foo.so below, we would depend on both the
- # 32 and 64-bit versions on a 64-bit machine. The current version of RPM
- # we use is too old and doesn't provide %{_isa}, so we do this manually.
- if [ "$HOST_ARCH" = "x86_64" ] ; then
- local EMPTY_VERSION="()"
- local PKG_ARCH="(64bit)"
- elif [ "$HOST_ARCH" = "i386" ] ; then
- local EMPTY_VERSION=""
- local PKG_ARCH=""
- fi
-
- DEPENDS="httpd >= 2.2.4, \
- mod_ssl >= 2.2, \
- libstdc++ >= 4.1.2, \
- at"
- gen_spec
-
- # Create temporary rpmbuild dirs.
- RPMBUILD_DIR=$(mktemp -d -t rpmbuild.XXXXXX) || exit 1
- mkdir -p "$RPMBUILD_DIR/BUILD"
- mkdir -p "$RPMBUILD_DIR/RPMS"
-
- rpmbuild --buildroot="$RPMBUILD_DIR/BUILD" -bb \
- --target="$HOST_ARCH" --rmspec \
- --define "_topdir $RPMBUILD_DIR" \
- --define "_binary_payload w9.bzdio" \
- "${SPEC}"
- PKGNAME="${PACKAGE}-${CHANNEL}-${VERSION}-${REVISION}"
- mv "$RPMBUILD_DIR/RPMS/$HOST_ARCH/${PKGNAME}.${HOST_ARCH}.rpm" "${OUTPUTDIR}"
- # Make sure the package is world-readable, otherwise it causes problems when
- # copied to share drive.
- chmod a+r "${OUTPUTDIR}/${PKGNAME}.$HOST_ARCH.rpm"
- rm -rf "$RPMBUILD_DIR"
-}
-
-# Remove temporary files and unwanted packaging output.
-cleanup() {
- rm -rf "${STAGEDIR}"
- rm -rf "${TMPFILEDIR}"
-}
-
-usage() {
- echo "usage: $(basename $0) [-c channel] [-a target_arch] [-o 'dir'] [-b 'dir']"
- echo "-c channel the package channel (unstable, beta, stable)"
- echo "-a arch package architecture (ia32 or x64)"
- echo "-o dir package output directory [${OUTPUTDIR}]"
- echo "-b dir build input directory [${BUILDDIR}]"
- echo "-h this help message"
-}
-
-# Check that the channel name is one of the allowable ones.
-verify_channel() {
- case $CHANNEL in
- stable )
- CHANNEL=stable
- REPLACES="unstable beta"
- ;;
- unstable|dev|alpha )
- CHANNEL=unstable
- REPLACES="stable beta"
- ;;
- testing|beta )
- CHANNEL=beta
- REPLACES="unstable stable"
- ;;
- * )
- echo
- echo "ERROR: '$CHANNEL' is not a valid channel type."
- echo
- exit 1
- ;;
- esac
-}
-
-process_opts() {
- while getopts ":o:b:c:a:h" OPTNAME
- do
- case $OPTNAME in
- o )
- OUTPUTDIR="$OPTARG"
- mkdir -p "${OUTPUTDIR}"
- ;;
- b )
- BUILDDIR=$(readlink -f "${OPTARG}")
- ;;
- c )
- CHANNEL="$OPTARG"
- verify_channel
- ;;
- a )
- TARGETARCH="$OPTARG"
- ;;
- h )
- usage
- exit 0
- ;;
- \: )
- echo "'-$OPTARG' needs an argument."
- usage
- exit 1
- ;;
- * )
- echo "invalid command-line option: $OPTARG"
- usage
- exit 1
- ;;
- esac
- done
-}
-
-#=========
-# MAIN
-#=========
-
-SCRIPTDIR=$(readlink -f "$(dirname "$0")")
-OUTPUTDIR="${PWD}"
-STAGEDIR=$(mktemp -d -t rpm.build.XXXXXX) || exit 1
-TMPFILEDIR=$(mktemp -d -t rpm.tmp.XXXXXX) || exit 1
-CHANNEL="beta"
-# Default target architecture to same as build host.
-if [ "$(uname -m)" = "x86_64" ]; then
- TARGETARCH="x64"
-else
- TARGETARCH="ia32"
-fi
-SPEC="${TMPFILEDIR}/mod-spdy.spec"
-
-# call cleanup() on exit
-trap cleanup 0
-process_opts "$@"
-if [ ! "$BUILDDIR" ]; then
- BUILDDIR=$(readlink -f "${SCRIPTDIR}/../../out/Release")
-fi
-
-source ${BUILDDIR}/install/common/installer.include
-
-get_version_info
-
-source "${BUILDDIR}/install/common/mod-spdy.info"
-eval $(sed -e "s/^\([^=]\+\)=\(.*\)$/export \1='\2'/" \
- "${BUILDDIR}/install/common/BRANDING")
-
-REPOCONFIG="http://dl.google.com/linux/${PACKAGE#google-}/rpm/stable"
-verify_channel
-
-APACHE_CONFDIR="/etc/httpd/conf.d"
-APACHE_USER="apache"
-COMMENT_OUT_DEFLATE=
-
-# Make everything happen in the OUTPUTDIR.
-cd "${OUTPUTDIR}"
-
-case "$TARGETARCH" in
- ia32 )
- export APACHE_MODULEDIR="/usr/lib/httpd/modules"
- export HOST_ARCH="i386"
- stage_install_rpm
- ;;
- x64 )
- export APACHE_MODULEDIR="/usr/lib64/httpd/modules"
- export HOST_ARCH="x86_64"
- stage_install_rpm
- ;;
- * )
- echo
- echo "ERROR: Don't know how to build RPMs for '$TARGETARCH'."
- echo
- exit 1
- ;;
-esac
-
-do_package "$HOST_ARCH"
+++ /dev/null
-#------------------------------------------------------------------------------
-# mod-spdy.spec
-#------------------------------------------------------------------------------
-
-#------------------------------------------------------------------------------
-# Prologue information
-#------------------------------------------------------------------------------
-Summary : @@SHORTDESC@@
-License : Apache Software License
-Name : @@PACKAGE@@-@@CHANNEL@@
-Version : @@VERSION@@
-Release : @@REVISION@@
-Group : System Environment/Daemons
-Vendor : @@COMPANY_FULLNAME@@
-Url : @@PRODUCTURL@@
-Packager : @@MAINTNAME@@ <@@MAINTMAIL@@>
-
-#------------------------------------------------------------------------------
-# Tested on:
-# TODO
-#------------------------------------------------------------------------------
-
-Provides : @@PROVIDES@@ = %{version}
-Requires : @@DEPENDS@@
-Conflicts : @@REPLACES@@
-
-#------------------------------------------------------------------------------
-# Description
-#------------------------------------------------------------------------------
-%Description
-@@FULLDESC@@
-
-#------------------------------------------------------------------------------
-# Build rule - How to make the package
-#------------------------------------------------------------------------------
-%build
-
-#------------------------------------------------------------------------------
-# Installation rule - how to install it (note that it
-# gets installed into a temp directory given by $RPM_BUILD_ROOT)
-#------------------------------------------------------------------------------
-%install
-rm -rf "$RPM_BUILD_ROOT"
-
-if [ -z "@@STAGEDIR@@" -o ! -d "@@STAGEDIR@@" ] ; then
- echo "@@STAGEDIR@@ appears to be incorrectly set - aborting"
- exit 1
-fi
-
-install -m 755 -d \
- "$RPM_BUILD_ROOT/etc" \
- "$RPM_BUILD_ROOT/usr"
-# This is hard coded for now
-cp -a "@@STAGEDIR@@/etc/" "$RPM_BUILD_ROOT/"
-cp -a "@@STAGEDIR@@/usr/" "$RPM_BUILD_ROOT/"
-
-#------------------------------------------------------------------------------
-# Rule to clean up a build
-#------------------------------------------------------------------------------
-%clean
-rm -rf "$RPM_BUILD_ROOT"
-
-#------------------------------------------------------------------------------
-# Files listing.
-#------------------------------------------------------------------------------
-%files
-%defattr(-,root,root)
-@@APACHE_MODULEDIR@@/mod_spdy.so
-@@APACHE_MODULEDIR@@/mod_ssl_with_npn.so
-%config(noreplace) @@APACHE_CONFDIR@@/spdy.conf
-%config @@APACHE_CONFDIR@@/load_ssl_with_npn.conf
-/etc/cron.daily/mod-spdy
-
-#------------------------------------------------------------------------------
-# Pre install script
-#------------------------------------------------------------------------------
-%pre
-
-exit 0
-
-#------------------------------------------------------------------------------
-# Post install script
-#------------------------------------------------------------------------------
-%post
-
-@@include@@../common/rpm.include
-
-MODSPDY_ENABLE_UPDATES=@@MODSPDY_ENABLE_UPDATES@@
-
-DEFAULTS_FILE="/etc/default/@@PACKAGE@@"
-if [ -n "${MODSPDY_ENABLE_UPDATES}" -a ! -e "$DEFAULTS_FILE" ]; then
- echo 'repo_add_once="true"' > "$DEFAULTS_FILE"
-fi
-
-if [ -e "$DEFAULTS_FILE" ]; then
-. "$DEFAULTS_FILE"
-
-if [ "$repo_add_once" = "true" ]; then
- determine_rpm_package_manager
-
- case $PACKAGEMANAGER in
- "yum")
- install_yum
- ;;
- "urpmi")
- install_urpmi
- ;;
- "yast")
- install_yast
- ;;
- esac
-fi
-
-# Some package managers have locks that prevent everything from being
-# configured at install time, so wait a bit then kick the cron job to do
-# whatever is left. Probably the db will be unlocked by then, but if not, the
-# cron job will keep retrying.
-# Do this with 'at' instead of a backgrounded shell because zypper waits on all
-# sub-shells to finish before it finishes, which is exactly the opposite of
-# what we want here. Also preemptively start atd because for some reason it's
-# not always running, which kind of defeats the purpose of having 'at' as a
-# required LSB command.
-service atd start
-echo "sh /etc/cron.daily/@@PACKAGE@@" | at now + 2 minute
-fi
-
-# Turn off loading of the normal mod_ssl.so:
-sed --in-place \
- 's/^ *LoadModule \+ssl_module .*$/#& # See load_ssl_with_npn.conf/' \
- @@APACHE_CONFDIR@@/ssl.conf
-
-exit 0
-
-
-#------------------------------------------------------------------------------
-# Pre uninstallation script
-#------------------------------------------------------------------------------
-%preun
-
-if [ "$1" -eq "0" ]; then
- mode="uninstall"
-elif [ "$1" -eq "1" ]; then
- mode="upgrade"
-fi
-
-@@include@@../common/rpm.include
-
-# On Debian we only remove when we purge. However, RPM has no equivalent to
-# dpkg --purge, so this is all disabled.
-#
-#determine_rpm_package_manager
-#
-#case $PACKAGEMANAGER in
-#"yum")
-# remove_yum
-# ;;
-#"urpmi")
-# remove_urpmi
-# ;;
-#"yast")
-# remove_yast
-# ;;
-#esac
-
-if [ "$mode" == "uninstall" ]; then
- # Re-enable loading of the normal mod_ssl.so:
- sed --in-place \
- 's/^#\( *LoadModule.*[^ ]\) *# See load_ssl_with_npn.conf$/\1/' \
- @@APACHE_CONFDIR@@/ssl.conf
-fi
-
-exit 0
-
-#------------------------------------------------------------------------------
-# Post uninstallation script
-#------------------------------------------------------------------------------
-%postun
-
-exit 0
+++ /dev/null
-# 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',
- ],
- },
- ],
-}
+++ /dev/null
-#!/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()
-
-#=============================================================================#
+++ /dev/null
-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 */
+++ /dev/null
-# 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',
- ],
- },
- },
- ],
- }],
- ],
-}
-
+++ /dev/null
-/* Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-
-#ifndef APR_H
-#define APR_H
-
-/* GENERATED FILE WARNING! DO NOT EDIT apr.h
- *
- * You must modify apr.h.in instead.
- *
- * And please, make an effort to stub apr.hw and apr.hnw in the process.
- */
-
-/**
- * @file apr.h
- * @brief APR Platform Definitions
- * @remark This is a generated header generated from include/apr.h.in by
- * ./configure, or copied from include/apr.hw or include/apr.hnw
- * for Win32 or Netware by those build environments, respectively.
- */
-
-/**
- * @defgroup APR Apache Portability Runtime library
- * @{
- */
-/**
- * @defgroup apr_platform Platform Definitions
- * @{
- * @warning
- * <strong><em>The actual values of macros and typedefs on this page<br>
- * are platform specific and should NOT be relied upon!</em></strong>
- */
-
-/* So that we can use inline on some critical functions, and use
- * GNUC attributes (such as to get -Wall warnings for printf-like
- * functions). Only do this in gcc 2.7 or later ... it may work
- * on earlier stuff, but why chance it.
- *
- * We've since discovered that the gcc shipped with NeXT systems
- * as "cc" is completely broken. It claims to be __GNUC__ and so
- * on, but it doesn't implement half of the things that __GNUC__
- * means. In particular it's missing inline and the __attribute__
- * stuff. So we hack around it. PR#1613. -djg
- */
-#if !defined(__GNUC__) || __GNUC__ < 2 || \
- (__GNUC__ == 2 && __GNUC_MINOR__ < 7) ||\
- defined(NEXT)
-#ifndef __attribute__
-#define __attribute__(__x)
-#endif
-#define APR_INLINE
-#define APR_HAS_INLINE 0
-#else
-#define APR_INLINE __inline__
-#define APR_HAS_INLINE 1
-#endif
-
-#define APR_HAVE_ARPA_INET_H 1
-#define APR_HAVE_CONIO_H 0
-#define APR_HAVE_CRYPT_H 1
-#define APR_HAVE_CTYPE_H 1
-#define APR_HAVE_DIRENT_H 1
-#define APR_HAVE_ERRNO_H 1
-#define APR_HAVE_FCNTL_H 1
-#define APR_HAVE_IO_H 0
-#define APR_HAVE_LIMITS_H 1
-#define APR_HAVE_NETDB_H 1
-#define APR_HAVE_NETINET_IN_H 1
-#define APR_HAVE_NETINET_SCTP_H 0
-#define APR_HAVE_NETINET_SCTP_UIO_H 0
-#define APR_HAVE_NETINET_TCP_H 1
-#define APR_HAVE_PTHREAD_H 1
-#define APR_HAVE_SEMAPHORE_H 1
-#define APR_HAVE_SIGNAL_H 1
-#define APR_HAVE_STDARG_H 1
-#define APR_HAVE_STDINT_H 1
-#define APR_HAVE_STDIO_H 1
-#define APR_HAVE_STDLIB_H 1
-#define APR_HAVE_STRING_H 1
-#define APR_HAVE_STRINGS_H 1
-#define APR_HAVE_SYS_IOCTL_H 1
-#define APR_HAVE_SYS_SENDFILE_H 1
-#define APR_HAVE_SYS_SIGNAL_H 1
-#define APR_HAVE_SYS_SOCKET_H 1
-#define APR_HAVE_SYS_SOCKIO_H 0
-#define APR_HAVE_SYS_SYSLIMITS_H 0
-#define APR_HAVE_SYS_TIME_H 1
-#define APR_HAVE_SYS_TYPES_H 1
-#define APR_HAVE_SYS_UIO_H 1
-#define APR_HAVE_SYS_UN_H 1
-#define APR_HAVE_SYS_WAIT_H 1
-#define APR_HAVE_TIME_H 1
-#define APR_HAVE_UNISTD_H 1
-#define APR_HAVE_WINDOWS_H 0
-#define APR_HAVE_WINSOCK2_H 0
-
-/** @} */
-/** @} */
-
-/* We don't include our conditional headers within the doxyblocks
- * or the extern "C" namespace
- */
-
-#if APR_HAVE_WINDOWS_H
-#include <windows.h>
-#endif
-
-#if APR_HAVE_WINSOCK2_H
-#include <winsock2.h>
-#endif
-
-#if APR_HAVE_SYS_TYPES_H
-#include <sys/types.h>
-#endif
-
-#if APR_HAVE_SYS_SOCKET_H
-#include <sys/socket.h>
-#endif
-
-#if defined(__cplusplus) && !defined(__STDC_CONSTANT_MACROS)
-/* C99 7.18.4 requires that stdint.h only exposes INT64_C
- * and UINT64_C for C++ implementations if this is defined: */
-#define __STDC_CONSTANT_MACROS
-#endif
-
-#if APR_HAVE_STDINT_H
-#include <stdint.h>
-#endif
-
-#if APR_HAVE_SYS_WAIT_H
-#include <sys/wait.h>
-#endif
-
-#ifdef OS2
-#define INCL_DOS
-#define INCL_DOSERRORS
-#include <os2.h>
-#endif
-
-/* header files for PATH_MAX, _POSIX_PATH_MAX */
-#if APR_HAVE_LIMITS_H
-#include <limits.h>
-#else
-#if APR_HAVE_SYS_SYSLIMITS_H
-#include <sys/syslimits.h>
-#endif
-#endif
-
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/**
- * @addtogroup apr_platform
- * @ingroup APR
- * @{
- */
-
-#define APR_HAVE_SHMEM_MMAP_TMP 1
-#define APR_HAVE_SHMEM_MMAP_SHM 1
-#define APR_HAVE_SHMEM_MMAP_ZERO 1
-#define APR_HAVE_SHMEM_SHMGET_ANON 1
-#define APR_HAVE_SHMEM_SHMGET 1
-#define APR_HAVE_SHMEM_MMAP_ANON 1
-#define APR_HAVE_SHMEM_BEOS 0
-
-#define APR_USE_SHMEM_MMAP_TMP 0
-#define APR_USE_SHMEM_MMAP_SHM 0
-#define APR_USE_SHMEM_MMAP_ZERO 0
-#define APR_USE_SHMEM_SHMGET_ANON 0
-#define APR_USE_SHMEM_SHMGET 1
-#define APR_USE_SHMEM_MMAP_ANON 1
-#define APR_USE_SHMEM_BEOS 0
-
-#define APR_USE_FLOCK_SERIALIZE 0
-#define APR_USE_SYSVSEM_SERIALIZE 1
-#define APR_USE_POSIXSEM_SERIALIZE 0
-#define APR_USE_FCNTL_SERIALIZE 0
-#define APR_USE_PROC_PTHREAD_SERIALIZE 0
-#define APR_USE_PTHREAD_SERIALIZE 1
-
-#define APR_HAS_FLOCK_SERIALIZE 1
-#define APR_HAS_SYSVSEM_SERIALIZE 1
-#define APR_HAS_POSIXSEM_SERIALIZE 1
-#define APR_HAS_FCNTL_SERIALIZE 1
-#define APR_HAS_PROC_PTHREAD_SERIALIZE 1
-
-#define APR_PROCESS_LOCK_IS_GLOBAL 0
-
-#define APR_HAVE_CORKABLE_TCP 1
-#define APR_HAVE_GETRLIMIT 1
-#define APR_HAVE_IN_ADDR 1
-#define APR_HAVE_INET_ADDR 1
-#define APR_HAVE_INET_NETWORK 1
-#define APR_HAVE_IPV6 1
-#define APR_HAVE_MEMMOVE 1
-#define APR_HAVE_SETRLIMIT 1
-#define APR_HAVE_SIGACTION 1
-#define APR_HAVE_SIGSUSPEND 1
-#define APR_HAVE_SIGWAIT 1
-#define APR_HAVE_SA_STORAGE 1
-#define APR_HAVE_STRCASECMP 1
-#define APR_HAVE_STRDUP 1
-#define APR_HAVE_STRICMP 0
-#define APR_HAVE_STRNCASECMP 1
-#define APR_HAVE_STRNICMP 0
-#define APR_HAVE_STRSTR 1
-#define APR_HAVE_MEMCHR 1
-#define APR_HAVE_STRUCT_RLIMIT 1
-#define APR_HAVE_UNION_SEMUN 0
-#define APR_HAVE_SCTP 0
-#define APR_HAVE_IOVEC 1
-
-/* APR Feature Macros */
-#define APR_HAS_SHARED_MEMORY 1
-#define APR_HAS_THREADS 1
-#define APR_HAS_SENDFILE 1
-#define APR_HAS_MMAP 1
-#define APR_HAS_FORK 1
-#define APR_HAS_RANDOM 1
-#define APR_HAS_OTHER_CHILD 1
-#define APR_HAS_DSO 1
-#define APR_HAS_SO_ACCEPTFILTER 0
-#define APR_HAS_UNICODE_FS 0
-#define APR_HAS_PROC_INVOKED 0
-#define APR_HAS_USER 1
-#define APR_HAS_LARGE_FILES 1
-#define APR_HAS_XTHREAD_FILES 0
-#define APR_HAS_OS_UUID 0
-
-#define APR_PROCATTR_USER_SET_REQUIRES_PASSWORD 0
-
-/* APR sets APR_FILES_AS_SOCKETS to 1 on systems where it is possible
- * to poll on files/pipes.
- */
-#define APR_FILES_AS_SOCKETS 1
-
-/* This macro indicates whether or not EBCDIC is the native character set.
- */
-#define APR_CHARSET_EBCDIC 0
-
-/* If we have a TCP implementation that can be "corked", what flag
- * do we use?
- */
-#define APR_TCP_NOPUSH_FLAG TCP_CORK
-
-/* Is the TCP_NODELAY socket option inherited from listening sockets?
-*/
-#define APR_TCP_NODELAY_INHERITED 1
-
-/* Is the O_NONBLOCK flag inherited from listening sockets?
-*/
-#define APR_O_NONBLOCK_INHERITED 0
-
-/* Typedefs that APR needs. */
-
-typedef unsigned char apr_byte_t;
-
-typedef short apr_int16_t;
-typedef unsigned short apr_uint16_t;
-
-typedef int apr_int32_t;
-typedef unsigned int apr_uint32_t;
-
-typedef long long apr_int64_t;
-typedef unsigned long long apr_uint64_t;
-
-typedef size_t apr_size_t;
-typedef ssize_t apr_ssize_t;
-typedef off64_t apr_off_t;
-typedef socklen_t apr_socklen_t;
-typedef unsigned long apr_ino_t;
-
-#define APR_SIZEOF_VOIDP 4
-
-#if APR_SIZEOF_VOIDP == 8
-typedef apr_uint64_t apr_uintptr_t;
-#else
-typedef apr_uint32_t apr_uintptr_t;
-#endif
-
-/* Are we big endian? */
-#define APR_IS_BIGENDIAN 0
-
-/* Mechanisms to properly type numeric literals */
-#define APR_INT64_C(val) INT64_C(val)
-#define APR_UINT64_C(val) UINT64_C(val)
-
-#ifdef INT16_MIN
-#define APR_INT16_MIN INT16_MIN
-#else
-#define APR_INT16_MIN (-0x7fff - 1)
-#endif
-
-#ifdef INT16_MAX
-#define APR_INT16_MAX INT16_MAX
-#else
-#define APR_INT16_MAX (0x7fff)
-#endif
-
-#ifdef UINT16_MAX
-#define APR_UINT16_MAX UINT16_MAX
-#else
-#define APR_UINT16_MAX (0xffff)
-#endif
-
-#ifdef INT32_MIN
-#define APR_INT32_MIN INT32_MIN
-#else
-#define APR_INT32_MIN (-0x7fffffff - 1)
-#endif
-
-#ifdef INT32_MAX
-#define APR_INT32_MAX INT32_MAX
-#else
-#define APR_INT32_MAX 0x7fffffff
-#endif
-
-#ifdef UINT32_MAX
-#define APR_UINT32_MAX UINT32_MAX
-#else
-#define APR_UINT32_MAX (0xffffffffU)
-#endif
-
-#ifdef INT64_MIN
-#define APR_INT64_MIN INT64_MIN
-#else
-#define APR_INT64_MIN (APR_INT64_C(-0x7fffffffffffffff) - 1)
-#endif
-
-#ifdef INT64_MAX
-#define APR_INT64_MAX INT64_MAX
-#else
-#define APR_INT64_MAX APR_INT64_C(0x7fffffffffffffff)
-#endif
-
-#ifdef UINT64_MAX
-#define APR_UINT64_MAX UINT64_MAX
-#else
-#define APR_UINT64_MAX APR_UINT64_C(0xffffffffffffffff)
-#endif
-
-#define APR_SIZE_MAX (~((apr_size_t)0))
-
-
-/* Definitions that APR programs need to work properly. */
-
-/**
- * APR public API wrap for C++ compilers.
- */
-#ifdef __cplusplus
-#define APR_BEGIN_DECLS extern "C" {
-#define APR_END_DECLS }
-#else
-#define APR_BEGIN_DECLS
-#define APR_END_DECLS
-#endif
-
-/**
- * Thread callbacks from APR functions must be declared with APR_THREAD_FUNC,
- * so that they follow the platform's calling convention.
- * <PRE>
- *
- * void* APR_THREAD_FUNC my_thread_entry_fn(apr_thread_t *thd, void *data);
- *
- * </PRE>
- */
-#define APR_THREAD_FUNC
-
-/**
- * The public APR functions are declared with APR_DECLARE(), so they may
- * use the most appropriate calling convention. Public APR functions with
- * variable arguments must use APR_DECLARE_NONSTD().
- *
- * @remark Both the declaration and implementations must use the same macro.
- *
- * <PRE>
- * APR_DECLARE(rettype) apr_func(args)
- * </PRE>
- * @see APR_DECLARE_NONSTD @see APR_DECLARE_DATA
- * @remark Note that when APR compiles the library itself, it passes the
- * symbol -DAPR_DECLARE_EXPORT to the compiler on some platforms (e.g. Win32)
- * to export public symbols from the dynamic library build.\n
- * The user must define the APR_DECLARE_STATIC when compiling to target
- * the static APR library on some platforms (e.g. Win32.) The public symbols
- * are neither exported nor imported when APR_DECLARE_STATIC is defined.\n
- * By default, compiling an application and including the APR public
- * headers, without defining APR_DECLARE_STATIC, will prepare the code to be
- * linked to the dynamic library.
- */
-#define APR_DECLARE(type) type
-
-/**
- * The public APR functions using variable arguments are declared with
- * APR_DECLARE_NONSTD(), as they must follow the C language calling convention.
- * @see APR_DECLARE @see APR_DECLARE_DATA
- * @remark Both the declaration and implementations must use the same macro.
- * <PRE>
- *
- * APR_DECLARE_NONSTD(rettype) apr_func(args, ...);
- *
- * </PRE>
- */
-#define APR_DECLARE_NONSTD(type) type
-
-/**
- * The public APR variables are declared with AP_MODULE_DECLARE_DATA.
- * This assures the appropriate indirection is invoked at compile time.
- * @see APR_DECLARE @see APR_DECLARE_NONSTD
- * @remark Note that the declaration and implementations use different forms,
- * but both must include the macro.
- *
- * <PRE>
- *
- * extern APR_DECLARE_DATA type apr_variable;\n
- * APR_DECLARE_DATA type apr_variable = value;
- *
- * </PRE>
- */
-#define APR_DECLARE_DATA
-
-/* Define APR_SSIZE_T_FMT.
- * If ssize_t is an integer we define it to be "d",
- * if ssize_t is a long int we define it to be "ld",
- * if ssize_t is neither we declare an error here.
- * I looked for a better way to define this here, but couldn't find one, so
- * to find the logic for this definition search for "ssize_t_fmt" in
- * configure.in.
- */
-#define APR_SSIZE_T_FMT "d"
-
-/* And APR_SIZE_T_FMT */
-#define APR_SIZE_T_FMT "u"
-
-/* And APR_OFF_T_FMT */
-#define APR_OFF_T_FMT APR_INT64_T_FMT
-
-/* And APR_PID_T_FMT */
-#define APR_PID_T_FMT "d"
-
-/* And APR_INT64_T_FMT */
-#define APR_INT64_T_FMT "lld"
-
-/* And APR_UINT64_T_FMT */
-#define APR_UINT64_T_FMT "llu"
-
-/* And APR_UINT64_T_HEX_FMT */
-#define APR_UINT64_T_HEX_FMT "llx"
-
-/* Does the proc mutex lock threads too */
-#define APR_PROC_MUTEX_IS_GLOBAL 0
-
-/* Local machine definition for console and log output. */
-#define APR_EOL_STR "\n"
-
-#if APR_HAVE_SYS_WAIT_H
-#ifdef WEXITSTATUS
-#define apr_wait_t int
-#else
-#define apr_wait_t union wait
-#define WEXITSTATUS(status) (int)((status).w_retcode)
-#define WTERMSIG(status) (int)((status).w_termsig)
-#endif /* !WEXITSTATUS */
-#elif defined(__MINGW32__)
-typedef int apr_wait_t;
-#endif /* HAVE_SYS_WAIT_H */
-
-#if defined(PATH_MAX)
-#define APR_PATH_MAX PATH_MAX
-#elif defined(_POSIX_PATH_MAX)
-#define APR_PATH_MAX _POSIX_PATH_MAX
-#else
-#error no decision has been made on APR_PATH_MAX for your platform
-#endif
-
-#define APR_DSOPATH "LD_LIBRARY_PATH"
-
-/** @} */
-
-/* Definitions that only Win32 programs need to compile properly. */
-
-/* XXX These simply don't belong here, perhaps in apr_portable.h
- * based on some APR_HAVE_PID/GID/UID?
- */
-#ifdef __MINGW32__
-#ifndef __GNUC__
-typedef int pid_t;
-#endif
-typedef int uid_t;
-typedef int gid_t;
-#endif
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* APR_H */
+++ /dev/null
-/* include/arch/unix/apr_private.h. Generated from apr_private.h.in by configure. */
-/* include/arch/unix/apr_private.h.in. Generated from configure.in by autoheader. */
-
-
-#ifndef APR_PRIVATE_H
-#define APR_PRIVATE_H
-
-
-/* Define as function which can be used for conversion of strings to
- apr_int64_t */
-#define APR_INT64_STRFN strtoll
-
-/* Define as function used for conversion of strings to apr_off_t */
-#define APR_OFF_T_STRFN strtoll
-
-/* Define to one of `_getb67', `GETB67', `getb67' for Cray-2 and Cray-YMP
- systems. This function is required for `alloca.c' support on those systems.
- */
-/* #undef CRAY_STACKSEG_END */
-
-/* Define to 1 if using `alloca.c'. */
-/* #undef C_ALLOCA */
-
-/* Define to path of random device */
-#define DEV_RANDOM "/dev/urandom"
-
-/* Define if struct dirent has an inode member */
-#define DIRENT_INODE d_fileno
-
-/* Define if struct dirent has a d_type member */
-#define DIRENT_TYPE d_type
-
-/* Define if DSO support uses dlfcn.h */
-#define DSO_USE_DLFCN 1
-
-/* Define if DSO support uses dyld.h */
-/* #undef DSO_USE_DYLD */
-
-/* Define if DSO support uses shl_load */
-/* #undef DSO_USE_SHL */
-
-/* Define to list of paths to EGD sockets */
-/* #undef EGD_DEFAULT_SOCKET */
-
-/* Define if fcntl locks affect threads within the process */
-/* #undef FCNTL_IS_GLOBAL */
-
-/* Define if fcntl returns EACCES when F_SETLK is already held */
-/* #undef FCNTL_TRYACQUIRE_EACCES */
-
-/* Define if flock locks affect threads within the process */
-/* #undef FLOCK_IS_GLOBAL */
-
-/* Define if gethostbyaddr is thread safe */
-/* #undef GETHOSTBYADDR_IS_THREAD_SAFE */
-
-/* Define if gethostbyname is thread safe */
-/* #undef GETHOSTBYNAME_IS_THREAD_SAFE */
-
-/* Define if gethostbyname_r has the glibc style */
-#define GETHOSTBYNAME_R_GLIBC2 1
-
-/* Define if gethostbyname_r has the hostent_data for the third argument */
-/* #undef GETHOSTBYNAME_R_HOSTENT_DATA */
-
-/* Define if getservbyname is thread safe */
-/* #undef GETSERVBYNAME_IS_THREAD_SAFE */
-
-/* Define if getservbyname_r has the glibc style */
-#define GETSERVBYNAME_R_GLIBC2 1
-
-/* Define if getservbyname_r has the OSF/1 style */
-/* #undef GETSERVBYNAME_R_OSF1 */
-
-/* Define if getservbyname_r has the Solaris style */
-/* #undef GETSERVBYNAME_R_SOLARIS */
-
-/* Define if accept4 function is supported */
-/* #undef HAVE_ACCEPT4 */
-
-/* Define to 1 if you have `alloca', as a function or macro. */
-#define HAVE_ALLOCA 1
-
-/* Define to 1 if you have <alloca.h> and it should be used (not on Ultrix).
- */
-#define HAVE_ALLOCA_H 1
-
-/* Define to 1 if you have the <arpa/inet.h> header file. */
-#define HAVE_ARPA_INET_H 1
-
-/* Define if compiler provides atomic builtins */
-#define HAVE_ATOMIC_BUILTINS 1
-
-/* Define if BONE_VERSION is defined in sys/socket.h */
-/* #undef HAVE_BONE_VERSION */
-
-/* Define to 1 if you have the <ByteOrder.h> header file. */
-/* #undef HAVE_BYTEORDER_H */
-
-/* Define to 1 if you have the `calloc' function. */
-#define HAVE_CALLOC 1
-
-/* Define to 1 if you have the <conio.h> header file. */
-/* #undef HAVE_CONIO_H */
-
-/* Define to 1 if you have the `create_area' function. */
-/* #undef HAVE_CREATE_AREA */
-
-/* Define to 1 if you have the `create_sem' function. */
-/* #undef HAVE_CREATE_SEM */
-
-/* Define to 1 if you have the <crypt.h> header file. */
-#define HAVE_CRYPT_H 1
-
-/* Define to 1 if you have the <ctype.h> header file. */
-#define HAVE_CTYPE_H 1
-
-/* Define to 1 if you have the declaration of `sys_siglist', and to 0 if you
- don't. */
-#define HAVE_DECL_SYS_SIGLIST 1
-
-/* Define to 1 if you have the <dirent.h> header file. */
-#define HAVE_DIRENT_H 1
-
-/* Define to 1 if you have the <dir.h> header file. */
-/* #undef HAVE_DIR_H */
-
-/* Define to 1 if you have the <dlfcn.h> header file. */
-#define HAVE_DLFCN_H 1
-
-/* Define to 1 if you have the <dl.h> header file. */
-/* #undef HAVE_DL_H */
-
-/* Define if dup3 function is supported */
-/* #undef HAVE_DUP3 */
-
-/* Define if EGD is supported */
-/* #undef HAVE_EGD */
-
-/* Define if the epoll interface is supported */
-#define HAVE_EPOLL 1
-
-/* Define if epoll_create1 function is supported */
-/* #undef HAVE_EPOLL_CREATE1 */
-
-/* Define to 1 if you have the <errno.h> header file. */
-#define HAVE_ERRNO_H 1
-
-/* Define to 1 if you have the <fcntl.h> header file. */
-#define HAVE_FCNTL_H 1
-
-/* Define to 1 if you have the `fdatasync' function. */
-#define HAVE_FDATASYNC 1
-
-/* Define to 1 if you have the `flock' function. */
-#define HAVE_FLOCK 1
-
-/* Define to 1 if you have the `fork' function. */
-#define HAVE_FORK 1
-
-/* Define if F_SETLK is defined in fcntl.h */
-#define HAVE_F_SETLK 1
-
-/* Define if getaddrinfo accepts the AI_ADDRCONFIG flag */
-#define HAVE_GAI_ADDRCONFIG 1
-
-/* Define to 1 if you have the `gai_strerror' function. */
-#define HAVE_GAI_STRERROR 1
-
-/* Define if getaddrinfo exists and works well enough for APR */
-#define HAVE_GETADDRINFO 1
-
-/* Define to 1 if you have the `getenv' function. */
-#define HAVE_GETENV 1
-
-/* Define to 1 if you have the `getgrgid_r' function. */
-#define HAVE_GETGRGID_R 1
-
-/* Define to 1 if you have the `getgrnam_r' function. */
-#define HAVE_GETGRNAM_R 1
-
-/* Define to 1 if you have the `gethostbyaddr_r' function. */
-#define HAVE_GETHOSTBYADDR_R 1
-
-/* Define to 1 if you have the `gethostbyname_r' function. */
-#define HAVE_GETHOSTBYNAME_R 1
-
-/* Define to 1 if you have the `getifaddrs' function. */
-#define HAVE_GETIFADDRS 1
-
-/* Define if getnameinfo exists */
-#define HAVE_GETNAMEINFO 1
-
-/* Define to 1 if you have the `getpass' function. */
-#define HAVE_GETPASS 1
-
-/* Define to 1 if you have the `getpassphrase' function. */
-/* #undef HAVE_GETPASSPHRASE */
-
-/* Define to 1 if you have the `getpwnam_r' function. */
-#define HAVE_GETPWNAM_R 1
-
-/* Define to 1 if you have the `getpwuid_r' function. */
-#define HAVE_GETPWUID_R 1
-
-/* Define to 1 if you have the `getrlimit' function. */
-#define HAVE_GETRLIMIT 1
-
-/* Define to 1 if you have the `getservbyname_r' function. */
-#define HAVE_GETSERVBYNAME_R 1
-
-/* Define to 1 if you have the `gmtime_r' function. */
-#define HAVE_GMTIME_R 1
-
-/* Define to 1 if you have the <grp.h> header file. */
-#define HAVE_GRP_H 1
-
-/* Define if hstrerror is present */
-/* #undef HAVE_HSTRERROR */
-
-/* Define to 1 if you have the <inttypes.h> header file. */
-#define HAVE_INTTYPES_H 1
-
-/* Define to 1 if you have the <io.h> header file. */
-/* #undef HAVE_IO_H */
-
-/* Define to 1 if you have the `isinf' function. */
-#define HAVE_ISINF 1
-
-/* Define to 1 if you have the `isnan' function. */
-#define HAVE_ISNAN 1
-
-/* Define to 1 if you have the <kernel/OS.h> header file. */
-/* #undef HAVE_KERNEL_OS_H */
-
-/* Define to 1 if you have the `kqueue' function. */
-/* #undef HAVE_KQUEUE */
-
-/* Define to 1 if you have the <langinfo.h> header file. */
-#define HAVE_LANGINFO_H 1
-
-/* Enable if this library is available */
-/* #undef HAVE_LIBADVAPI32 */
-
-/* Define to 1 if you have the `bsd' library (-lbsd). */
-/* #undef HAVE_LIBBSD */
-
-/* Enable if this library is available */
-/* #undef HAVE_LIBKERNEL32 */
-
-/* Define to 1 if you have the `msvcrt' library (-lmsvcrt). */
-/* #undef HAVE_LIBMSVCRT */
-
-/* Enable if this library is available */
-/* #undef HAVE_LIBRPCRT4 */
-
-/* Define to 1 if you have the `sendfile' library (-lsendfile). */
-/* #undef HAVE_LIBSENDFILE */
-
-/* Enable if this library is available */
-/* #undef HAVE_LIBSHELL32 */
-
-/* Define to 1 if you have the `truerand' library (-ltruerand). */
-/* #undef HAVE_LIBTRUERAND */
-
-/* Enable if this library is available */
-/* #undef HAVE_LIBWS2_32 */
-
-/* Define to 1 if you have the <limits.h> header file. */
-#define HAVE_LIMITS_H 1
-
-/* Define to 1 if you have the `localtime_r' function. */
-#define HAVE_LOCALTIME_R 1
-
-/* Define if LOCK_EX is defined in sys/file.h */
-#define HAVE_LOCK_EX 1
-
-/* Define to 1 if you have the <mach-o/dyld.h> header file. */
-/* #undef HAVE_MACH_O_DYLD_H */
-
-/* Define to 1 if you have the <malloc.h> header file. */
-#define HAVE_MALLOC_H 1
-
-/* Define if MAP_ANON is defined in sys/mman.h */
-#define HAVE_MAP_ANON 1
-
-/* Define to 1 if you have the `memchr' function. */
-#define HAVE_MEMCHR 1
-
-/* Define to 1 if you have the `memmove' function. */
-#define HAVE_MEMMOVE 1
-
-/* Define to 1 if you have the <memory.h> header file. */
-#define HAVE_MEMORY_H 1
-
-/* Define to 1 if you have the `mkstemp' function. */
-#define HAVE_MKSTEMP 1
-
-/* Define to 1 if you have the `mkstemp64' function. */
-#define HAVE_MKSTEMP64 1
-
-/* Define to 1 if you have the `mmap' function. */
-#define HAVE_MMAP 1
-
-/* Define to 1 if you have the `mmap64' function. */
-#define HAVE_MMAP64 1
-
-/* Define to 1 if you have the `munmap' function. */
-#define HAVE_MUNMAP 1
-
-/* Define to 1 if you have the <netdb.h> header file. */
-#define HAVE_NETDB_H 1
-
-/* Define to 1 if you have the <netinet/in.h> header file. */
-#define HAVE_NETINET_IN_H 1
-
-/* Define to 1 if you have the <netinet/sctp.h> header file. */
-/* #undef HAVE_NETINET_SCTP_H */
-
-/* Define to 1 if you have the <netinet/sctp_uio.h> header file. */
-/* #undef HAVE_NETINET_SCTP_UIO_H */
-
-/* Defined if netinet/tcp.h is present */
-#define HAVE_NETINET_TCP_H 1
-
-/* Define to 1 if you have the <net/errno.h> header file. */
-/* #undef HAVE_NET_ERRNO_H */
-
-/* Define to 1 if you have the `nl_langinfo' function. */
-#define HAVE_NL_LANGINFO 1
-
-/* Define to 1 if you have the <os2.h> header file. */
-/* #undef HAVE_OS2_H */
-
-/* Define to 1 if you have the <osreldate.h> header file. */
-/* #undef HAVE_OSRELDATE_H */
-
-/* Define to 1 if you have the <OS.h> header file. */
-/* #undef HAVE_OS_H */
-
-/* Define to 1 if you have the `poll' function. */
-#define HAVE_POLL 1
-
-/* Define if POLLIN is defined */
-#define HAVE_POLLIN 1
-
-/* Define to 1 if you have the <poll.h> header file. */
-#define HAVE_POLL_H 1
-
-/* Define to 1 if you have the `port_create' function. */
-/* #undef HAVE_PORT_CREATE */
-
-/* Define to 1 if you have the <process.h> header file. */
-/* #undef HAVE_PROCESS_H */
-
-/* Define to 1 if you have the `pthread_attr_setguardsize' function. */
-#define HAVE_PTHREAD_ATTR_SETGUARDSIZE 1
-
-/* Define to 1 if you have the <pthread.h> header file. */
-#define HAVE_PTHREAD_H 1
-
-/* Define to 1 if you have the `pthread_key_delete' function. */
-#define HAVE_PTHREAD_KEY_DELETE 1
-
-/* Define to 1 if you have the `pthread_mutexattr_setpshared' function. */
-#define HAVE_PTHREAD_MUTEXATTR_SETPSHARED 1
-
-/* Define if recursive pthread mutexes are available */
-#define HAVE_PTHREAD_MUTEX_RECURSIVE 1
-
-/* Define if cross-process robust mutexes are available */
-#define HAVE_PTHREAD_MUTEX_ROBUST 1
-
-/* Define if PTHREAD_PROCESS_SHARED is defined in pthread.h */
-#define HAVE_PTHREAD_PROCESS_SHARED 1
-
-/* Define if pthread rwlocks are available */
-#define HAVE_PTHREAD_RWLOCKS 1
-
-/* Define to 1 if you have the `pthread_rwlock_init' function. */
-#define HAVE_PTHREAD_RWLOCK_INIT 1
-
-/* Define to 1 if you have the `pthread_yield' function. */
-#define HAVE_PTHREAD_YIELD 1
-
-/* Define to 1 if you have the `putenv' function. */
-#define HAVE_PUTENV 1
-
-/* Define to 1 if you have the <pwd.h> header file. */
-#define HAVE_PWD_H 1
-
-/* Define to 1 if you have the `readdir64_r' function. */
-#define HAVE_READDIR64_R 1
-
-/* Define to 1 if you have the <sched.h> header file. */
-/* #undef HAVE_SCHED_H */
-
-/* Define to 1 if you have the `sched_yield' function. */
-/* #undef HAVE_SCHED_YIELD */
-
-/* Define to 1 if you have the <semaphore.h> header file. */
-#define HAVE_SEMAPHORE_H 1
-
-/* Define to 1 if you have the `semctl' function. */
-#define HAVE_SEMCTL 1
-
-/* Define to 1 if you have the `semget' function. */
-#define HAVE_SEMGET 1
-
-/* Define to 1 if you have the `sem_close' function. */
-#define HAVE_SEM_CLOSE 1
-
-/* Define to 1 if you have the `sem_post' function. */
-#define HAVE_SEM_POST 1
-
-/* Define if SEM_UNDO is defined in sys/sem.h */
-#define HAVE_SEM_UNDO 1
-
-/* Define to 1 if you have the `sem_unlink' function. */
-#define HAVE_SEM_UNLINK 1
-
-/* Define to 1 if you have the `sem_wait' function. */
-#define HAVE_SEM_WAIT 1
-
-/* Define to 1 if you have the `sendfile' function. */
-#define HAVE_SENDFILE 1
-
-/* Define to 1 if you have the `sendfile64' function. */
-#define HAVE_SENDFILE64 1
-
-/* Define to 1 if you have the `sendfilev' function. */
-/* #undef HAVE_SENDFILEV */
-
-/* Define to 1 if you have the `sendfilev64' function. */
-/* #undef HAVE_SENDFILEV64 */
-
-/* Define to 1 if you have the `send_file' function. */
-/* #undef HAVE_SEND_FILE */
-
-/* Define to 1 if you have the `setenv' function. */
-#define HAVE_SETENV 1
-
-/* Define to 1 if you have the `setrlimit' function. */
-#define HAVE_SETRLIMIT 1
-
-/* Define to 1 if you have the `setsid' function. */
-#define HAVE_SETSID 1
-
-/* Define to 1 if you have the `set_h_errno' function. */
-/* #undef HAVE_SET_H_ERRNO */
-
-/* Define to 1 if you have the `shmat' function. */
-#define HAVE_SHMAT 1
-
-/* Define to 1 if you have the `shmctl' function. */
-#define HAVE_SHMCTL 1
-
-/* Define to 1 if you have the `shmdt' function. */
-#define HAVE_SHMDT 1
-
-/* Define to 1 if you have the `shmget' function. */
-#define HAVE_SHMGET 1
-
-/* Define to 1 if you have the `shm_open' function. */
-#define HAVE_SHM_OPEN 1
-
-/* Define to 1 if you have the `shm_unlink' function. */
-#define HAVE_SHM_UNLINK 1
-
-/* Define to 1 if you have the `sigaction' function. */
-#define HAVE_SIGACTION 1
-
-/* Define to 1 if you have the <signal.h> header file. */
-#define HAVE_SIGNAL_H 1
-
-/* Define to 1 if you have the `sigsuspend' function. */
-#define HAVE_SIGSUSPEND 1
-
-/* Define to 1 if you have the `sigwait' function. */
-#define HAVE_SIGWAIT 1
-
-/* Whether you have socklen_t */
-#define HAVE_SOCKLEN_T 1
-
-/* Define if the SOCK_CLOEXEC flag is supported */
-/* #undef HAVE_SOCK_CLOEXEC */
-
-/* Define if SO_ACCEPTFILTER is defined in sys/socket.h */
-/* #undef HAVE_SO_ACCEPTFILTER */
-
-/* Define to 1 if you have the <stdarg.h> header file. */
-#define HAVE_STDARG_H 1
-
-/* Define to 1 if you have the <stddef.h> header file. */
-#define HAVE_STDDEF_H 1
-
-/* Define to 1 if you have the <stdint.h> header file. */
-#define HAVE_STDINT_H 1
-
-/* Define to 1 if you have the <stdio.h> header file. */
-#define HAVE_STDIO_H 1
-
-/* Define to 1 if you have the <stdlib.h> header file. */
-#define HAVE_STDLIB_H 1
-
-/* Define to 1 if you have the `strcasecmp' function. */
-#define HAVE_STRCASECMP 1
-
-/* Define to 1 if you have the `strdup' function. */
-#define HAVE_STRDUP 1
-
-/* Define to 1 if you have the `strerror_r' function. */
-#define HAVE_STRERROR_R 1
-
-/* Define to 1 if you have the `stricmp' function. */
-/* #undef HAVE_STRICMP */
-
-/* Define to 1 if you have the <strings.h> header file. */
-#define HAVE_STRINGS_H 1
-
-/* Define to 1 if you have the <string.h> header file. */
-#define HAVE_STRING_H 1
-
-/* Define to 1 if you have the `strncasecmp' function. */
-#define HAVE_STRNCASECMP 1
-
-/* Define to 1 if you have the `strnicmp' function. */
-/* #undef HAVE_STRNICMP */
-
-/* Define to 1 if you have the `strstr' function. */
-#define HAVE_STRSTR 1
-
-/* Define if struct impreq was found */
-#define HAVE_STRUCT_IPMREQ 1
-
-/* Define to 1 if `st_atimensec' is member of `struct stat'. */
-/* #undef HAVE_STRUCT_STAT_ST_ATIMENSEC */
-
-/* Define to 1 if `st_atime_n' is member of `struct stat'. */
-/* #undef HAVE_STRUCT_STAT_ST_ATIME_N */
-
-/* Define to 1 if `st_atim.tv_nsec' is member of `struct stat'. */
-#define HAVE_STRUCT_STAT_ST_ATIM_TV_NSEC 1
-
-/* Define to 1 if `st_blocks' is member of `struct stat'. */
-#define HAVE_STRUCT_STAT_ST_BLOCKS 1
-
-/* Define to 1 if `st_ctimensec' is member of `struct stat'. */
-/* #undef HAVE_STRUCT_STAT_ST_CTIMENSEC */
-
-/* Define to 1 if `st_ctime_n' is member of `struct stat'. */
-/* #undef HAVE_STRUCT_STAT_ST_CTIME_N */
-
-/* Define to 1 if `st_ctim.tv_nsec' is member of `struct stat'. */
-#define HAVE_STRUCT_STAT_ST_CTIM_TV_NSEC 1
-
-/* Define to 1 if `st_mtimensec' is member of `struct stat'. */
-/* #undef HAVE_STRUCT_STAT_ST_MTIMENSEC */
-
-/* Define to 1 if `st_mtime_n' is member of `struct stat'. */
-/* #undef HAVE_STRUCT_STAT_ST_MTIME_N */
-
-/* Define to 1 if `st_mtim.tv_nsec' is member of `struct stat'. */
-#define HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC 1
-
-/* Define to 1 if `tm_gmtoff' is member of `struct tm'. */
-#define HAVE_STRUCT_TM_TM_GMTOFF 1
-
-/* Define to 1 if `__tm_gmtoff' is member of `struct tm'. */
-/* #undef HAVE_STRUCT_TM___TM_GMTOFF */
-
-/* Define to 1 if you have the <sysapi.h> header file. */
-/* #undef HAVE_SYSAPI_H */
-
-/* Define to 1 if you have the <sysgtime.h> header file. */
-/* #undef HAVE_SYSGTIME_H */
-
-/* Define to 1 if you have the <sys/file.h> header file. */
-#define HAVE_SYS_FILE_H 1
-
-/* Define to 1 if you have the <sys/ioctl.h> header file. */
-#define HAVE_SYS_IOCTL_H 1
-
-/* Define to 1 if you have the <sys/ipc.h> header file. */
-#define HAVE_SYS_IPC_H 1
-
-/* Define to 1 if you have the <sys/mman.h> header file. */
-#define HAVE_SYS_MMAN_H 1
-
-/* Define to 1 if you have the <sys/mutex.h> header file. */
-/* #undef HAVE_SYS_MUTEX_H */
-
-/* Define to 1 if you have the <sys/param.h> header file. */
-#define HAVE_SYS_PARAM_H 1
-
-/* Define to 1 if you have the <sys/poll.h> header file. */
-#define HAVE_SYS_POLL_H 1
-
-/* Define to 1 if you have the <sys/resource.h> header file. */
-#define HAVE_SYS_RESOURCE_H 1
-
-/* Define to 1 if you have the <sys/select.h> header file. */
-#define HAVE_SYS_SELECT_H 1
-
-/* Define to 1 if you have the <sys/sem.h> header file. */
-#define HAVE_SYS_SEM_H 1
-
-/* Define to 1 if you have the <sys/sendfile.h> header file. */
-#define HAVE_SYS_SENDFILE_H 1
-
-/* Define to 1 if you have the <sys/shm.h> header file. */
-#define HAVE_SYS_SHM_H 1
-
-/* Define to 1 if you have the <sys/signal.h> header file. */
-#define HAVE_SYS_SIGNAL_H 1
-
-/* Define to 1 if you have the <sys/socket.h> header file. */
-#define HAVE_SYS_SOCKET_H 1
-
-/* Define to 1 if you have the <sys/sockio.h> header file. */
-/* #undef HAVE_SYS_SOCKIO_H */
-
-/* Define to 1 if you have the <sys/stat.h> header file. */
-#define HAVE_SYS_STAT_H 1
-
-/* Define to 1 if you have the <sys/sysctl.h> header file. */
-#define HAVE_SYS_SYSCTL_H 1
-
-/* Define to 1 if you have the <sys/syslimits.h> header file. */
-/* #undef HAVE_SYS_SYSLIMITS_H */
-
-/* Define to 1 if you have the <sys/time.h> header file. */
-#define HAVE_SYS_TIME_H 1
-
-/* Define to 1 if you have the <sys/types.h> header file. */
-#define HAVE_SYS_TYPES_H 1
-
-/* Define to 1 if you have the <sys/uio.h> header file. */
-#define HAVE_SYS_UIO_H 1
-
-/* Define to 1 if you have the <sys/un.h> header file. */
-#define HAVE_SYS_UN_H 1
-
-/* Define to 1 if you have the <sys/uuid.h> header file. */
-/* #undef HAVE_SYS_UUID_H */
-
-/* Define to 1 if you have the <sys/wait.h> header file. */
-#define HAVE_SYS_WAIT_H 1
-
-/* Define if TCP_CORK is defined in netinet/tcp.h */
-#define HAVE_TCP_CORK 1
-
-/* Define if TCP_NODELAY and TCP_CORK can be enabled at the same time */
-#define HAVE_TCP_NODELAY_WITH_CORK 1
-
-/* Define if TCP_NOPUSH is defined in netinet/tcp.h */
-/* #undef HAVE_TCP_NOPUSH */
-
-/* Define to 1 if you have the <termios.h> header file. */
-#define HAVE_TERMIOS_H 1
-
-/* Define to 1 if you have the <time.h> header file. */
-#define HAVE_TIME_H 1
-
-/* Define to 1 if you have the <tpfeq.h> header file. */
-/* #undef HAVE_TPFEQ_H */
-
-/* Define to 1 if you have the <tpfio.h> header file. */
-/* #undef HAVE_TPFIO_H */
-
-/* Define if truerand is supported */
-/* #undef HAVE_TRUERAND */
-
-/* Define to 1 if you have the <unistd.h> header file. */
-#define HAVE_UNISTD_H 1
-
-/* Define to 1 if you have the <unix.h> header file. */
-/* #undef HAVE_UNIX_H */
-
-/* Define to 1 if you have the `unsetenv' function. */
-#define HAVE_UNSETENV 1
-
-/* Define to 1 if you have the `utime' function. */
-#define HAVE_UTIME 1
-
-/* Define to 1 if you have the `utimes' function. */
-#define HAVE_UTIMES 1
-
-/* Define to 1 if you have the `uuid_create' function. */
-/* #undef HAVE_UUID_CREATE */
-
-/* Define to 1 if you have the `uuid_generate' function. */
-#define HAVE_UUID_GENERATE 1
-
-/* Define to 1 if you have the <uuid.h> header file. */
-/* #undef HAVE_UUID_H */
-
-/* Define to 1 if you have the <uuid/uuid.h> header file. */
-/* #undef HAVE_UUID_UUID_H */
-
-/* Define if C compiler supports VLA */
-#define HAVE_VLA 1
-
-/* Define to 1 if you have the `waitpid' function. */
-#define HAVE_WAITPID 1
-
-/* Define to 1 if you have the <windows.h> header file. */
-/* #undef HAVE_WINDOWS_H */
-
-/* Define to 1 if you have the <winsock2.h> header file. */
-/* #undef HAVE_WINSOCK2_H */
-
-/* Define to 1 if you have the `writev' function. */
-#define HAVE_WRITEV 1
-
-/* Define for z/OS pthread API nuances */
-/* #undef HAVE_ZOS_PTHREADS */
-
-/* Define if EAI_ error codes from getaddrinfo are negative */
-#define NEGATIVE_EAI 1
-
-/* Define to the address where bug reports for this package should be sent. */
-#define PACKAGE_BUGREPORT ""
-
-/* Define to the full name of this package. */
-#define PACKAGE_NAME ""
-
-/* Define to the full name and version of this package. */
-#define PACKAGE_STRING ""
-
-/* Define to the one symbol short name of this package. */
-#define PACKAGE_TARNAME ""
-
-/* Define to the version of this package. */
-#define PACKAGE_VERSION ""
-
-/* Define if POSIX semaphores affect threads within the process */
-/* #undef POSIXSEM_IS_GLOBAL */
-
-/* Define on PowerPC 405 where errata 77 applies */
-/* #undef PPC405_ERRATA */
-
-/* Define if pthread_attr_getdetachstate() has one arg */
-/* #undef PTHREAD_ATTR_GETDETACHSTATE_TAKES_ONE_ARG */
-
-/* Define if pthread_getspecific() has two args */
-/* #undef PTHREAD_GETSPECIFIC_TAKES_TWO_ARGS */
-
-/* Define if readdir is thread safe */
-/* #undef READDIR_IS_THREAD_SAFE */
-
-/* Define to 1 if the `setpgrp' function takes no argument. */
-#define SETPGRP_VOID 1
-
-/* */
-/* #undef SIGWAIT_TAKES_ONE_ARG */
-
-/* The size of `char', as computed by sizeof. */
-#define SIZEOF_CHAR 1
-
-/* The size of `int', as computed by sizeof. */
-#define SIZEOF_INT 4
-
-/* The size of `long', as computed by sizeof. */
-#define SIZEOF_LONG 4
-
-/* The size of `long long', as computed by sizeof. */
-#define SIZEOF_LONG_LONG 8
-
-/* The size of off_t */
-#define SIZEOF_OFF_T 4
-
-/* The size of pid_t */
-#define SIZEOF_PID_T 4
-
-/* The size of `short', as computed by sizeof. */
-#define SIZEOF_SHORT 2
-
-/* The size of size_t */
-#define SIZEOF_SIZE_T 4
-
-/* The size of ssize_t */
-#define SIZEOF_SSIZE_T 4
-
-/* The size of struct iovec */
-#define SIZEOF_STRUCT_IOVEC 8
-
-/* The size of `void*', as computed by sizeof. */
-#define SIZEOF_VOIDP 4
-
-/* If using the C implementation of alloca, define if you know the
- direction of stack growth for your system; otherwise it will be
- automatically deduced at runtime.
- STACK_DIRECTION > 0 => grows toward higher addresses
- STACK_DIRECTION < 0 => grows toward lower addresses
- STACK_DIRECTION = 0 => direction of growth unknown */
-/* #undef STACK_DIRECTION */
-
-/* Define to 1 if you have the ANSI C header files. */
-#define STDC_HEADERS 1
-
-/* Define if strerror returns int */
-/* #undef STRERROR_R_RC_INT */
-
-/* Define if SysV semaphores affect threads within the process */
-/* #undef SYSVSEM_IS_GLOBAL */
-
-/* Define if use of generic atomics is requested */
-#define USE_ATOMICS_GENERIC 1
-
-/* Define if BeOS Semaphores will be used */
-/* #undef USE_BEOSSEM */
-
-/* Define if SVR4-style fcntl() will be used */
-/* #undef USE_FCNTL_SERIALIZE */
-
-/* Define if 4.2BSD-style flock() will be used */
-/* #undef USE_FLOCK_SERIALIZE */
-
-/* Define if BeOS areas will be used */
-/* #undef USE_SHMEM_BEOS */
-
-/* Define if BeOS areas will be used */
-/* #undef USE_SHMEM_BEOS_ANON */
-
-/* Define if 4.4BSD-style mmap() via MAP_ANON will be used */
-#define USE_SHMEM_MMAP_ANON 1
-
-/* Define if mmap() via POSIX.1 shm_open() on temporary file will be used */
-/* #undef USE_SHMEM_MMAP_SHM */
-
-/* Define if Classical mmap() on temporary file will be used */
-/* #undef USE_SHMEM_MMAP_TMP */
-
-/* Define if SVR4-style mmap() on /dev/zero will be used */
-/* #undef USE_SHMEM_MMAP_ZERO */
-
-/* Define if OS/2 DosAllocSharedMem() will be used */
-/* #undef USE_SHMEM_OS2 */
-
-/* Define if OS/2 DosAllocSharedMem() will be used */
-/* #undef USE_SHMEM_OS2_ANON */
-
-/* Define if SysV IPC shmget() will be used */
-#define USE_SHMEM_SHMGET 1
-
-/* Define if SysV IPC shmget() will be used */
-/* #undef USE_SHMEM_SHMGET_ANON */
-
-/* Define if Windows shared memory will be used */
-/* #undef USE_SHMEM_WIN32 */
-
-/* Define if Windows CreateFileMapping() will be used */
-/* #undef USE_SHMEM_WIN32_ANON */
-
-/* Define if SysV IPC semget() will be used */
-#define USE_SYSVSEM_SERIALIZE 1
-
-/* Define if apr_wait_for_io_or_timeout() uses poll(2) */
-#define WAITIO_USES_POLL 1
-
-/* Define to 1 if your processor stores words with the most significant byte
- first (like Motorola and SPARC, unlike Intel and VAX). */
-/* #undef WORDS_BIGENDIAN */
-
-/* Define to 1 if on AIX 3.
- System headers sometimes define this.
- We just want to avoid a redefinition error message. */
-#ifndef _ALL_SOURCE
-/* # undef _ALL_SOURCE */
-#endif
-
-/* Enable GNU extensions on systems that have them. */
-#ifndef _GNU_SOURCE
-# define _GNU_SOURCE 1
-#endif
-
-/* Define to 1 if on MINIX. */
-/* #undef _MINIX */
-
-/* Define to 2 if the system does not provide POSIX.1 features except with
- this defined. */
-/* #undef _POSIX_1_SOURCE */
-
-/* Define to 1 if you need to in order for `stat' and other things to work. */
-/* #undef _POSIX_SOURCE */
-
-/* Enable extensions on Solaris. */
-#ifndef __EXTENSIONS__
-# define __EXTENSIONS__ 1
-#endif
-#ifndef _POSIX_PTHREAD_SEMANTICS
-# define _POSIX_PTHREAD_SEMANTICS 1
-#endif
-#ifndef _TANDEM_SOURCE
-# define _TANDEM_SOURCE 1
-#endif
-
-/* Define to empty if `const' does not conform to ANSI C. */
-/* #undef const */
-
-/* Define to `int' if <sys/types.h> doesn't define. */
-/* #undef gid_t */
-
-/* Define to `__inline__' or `__inline' if that's what the C compiler
- calls it, or to nothing if 'inline' is not supported under any name. */
-#ifndef __cplusplus
-/* #undef inline */
-#endif
-
-/* Define to `long int' if <sys/types.h> does not define. */
-/* #undef off_t */
-
-/* Define to `int' if <sys/types.h> does not define. */
-/* #undef pid_t */
-
-/* Define to `unsigned int' if <sys/types.h> does not define. */
-/* #undef size_t */
-
-/* Define to `int' if <sys/types.h> does not define. */
-/* #undef ssize_t */
-
-/* Define to `int' if <sys/types.h> doesn't define. */
-/* #undef uid_t */
-
-
-/* switch this on if we have a BeOS version below BONE */
-#if BEOS && !HAVE_BONE_VERSION
-#define BEOS_R5 1
-#else
-#define BEOS_BONE 1
-#endif
-
-/*
- * Include common private declarations.
- */
-#include "../apr_private_common.h"
-#endif /* APR_PRIVATE_H */
+++ /dev/null
-/* Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-
-#ifndef APR_H
-#define APR_H
-
-/* GENERATED FILE WARNING! DO NOT EDIT apr.h
- *
- * You must modify apr.h.in instead.
- *
- * And please, make an effort to stub apr.hw and apr.hnw in the process.
- */
-
-/**
- * @file apr.h
- * @brief APR Platform Definitions
- * @remark This is a generated header generated from include/apr.h.in by
- * ./configure, or copied from include/apr.hw or include/apr.hnw
- * for Win32 or Netware by those build environments, respectively.
- */
-
-/**
- * @defgroup APR Apache Portability Runtime library
- * @{
- */
-/**
- * @defgroup apr_platform Platform Definitions
- * @{
- * @warning
- * <strong><em>The actual values of macros and typedefs on this page<br>
- * are platform specific and should NOT be relied upon!</em></strong>
- */
-
-/* So that we can use inline on some critical functions, and use
- * GNUC attributes (such as to get -Wall warnings for printf-like
- * functions). Only do this in gcc 2.7 or later ... it may work
- * on earlier stuff, but why chance it.
- *
- * We've since discovered that the gcc shipped with NeXT systems
- * as "cc" is completely broken. It claims to be __GNUC__ and so
- * on, but it doesn't implement half of the things that __GNUC__
- * means. In particular it's missing inline and the __attribute__
- * stuff. So we hack around it. PR#1613. -djg
- */
-#if !defined(__GNUC__) || __GNUC__ < 2 || \
- (__GNUC__ == 2 && __GNUC_MINOR__ < 7) ||\
- defined(NEXT)
-#ifndef __attribute__
-#define __attribute__(__x)
-#endif
-#define APR_INLINE
-#define APR_HAS_INLINE 0
-#else
-#define APR_INLINE __inline__
-#define APR_HAS_INLINE 1
-#endif
-
-#define APR_HAVE_ARPA_INET_H 1
-#define APR_HAVE_CONIO_H 0
-#define APR_HAVE_CRYPT_H 1
-#define APR_HAVE_CTYPE_H 1
-#define APR_HAVE_DIRENT_H 1
-#define APR_HAVE_ERRNO_H 1
-#define APR_HAVE_FCNTL_H 1
-#define APR_HAVE_IO_H 0
-#define APR_HAVE_LIMITS_H 1
-#define APR_HAVE_NETDB_H 1
-#define APR_HAVE_NETINET_IN_H 1
-#define APR_HAVE_NETINET_SCTP_H 0
-#define APR_HAVE_NETINET_SCTP_UIO_H 0
-#define APR_HAVE_NETINET_TCP_H 1
-#define APR_HAVE_PTHREAD_H 1
-#define APR_HAVE_SEMAPHORE_H 1
-#define APR_HAVE_SIGNAL_H 1
-#define APR_HAVE_STDARG_H 1
-#define APR_HAVE_STDINT_H 1
-#define APR_HAVE_STDIO_H 1
-#define APR_HAVE_STDLIB_H 1
-#define APR_HAVE_STRING_H 1
-#define APR_HAVE_STRINGS_H 1
-#define APR_HAVE_SYS_IOCTL_H 1
-#define APR_HAVE_SYS_SENDFILE_H 1
-#define APR_HAVE_SYS_SIGNAL_H 1
-#define APR_HAVE_SYS_SOCKET_H 1
-#define APR_HAVE_SYS_SOCKIO_H 0
-#define APR_HAVE_SYS_SYSLIMITS_H 0
-#define APR_HAVE_SYS_TIME_H 1
-#define APR_HAVE_SYS_TYPES_H 1
-#define APR_HAVE_SYS_UIO_H 1
-#define APR_HAVE_SYS_UN_H 1
-#define APR_HAVE_SYS_WAIT_H 1
-#define APR_HAVE_TIME_H 1
-#define APR_HAVE_UNISTD_H 1
-#define APR_HAVE_WINDOWS_H 0
-#define APR_HAVE_WINSOCK2_H 0
-
-/** @} */
-/** @} */
-
-/* We don't include our conditional headers within the doxyblocks
- * or the extern "C" namespace
- */
-
-#if APR_HAVE_WINDOWS_H
-#include <windows.h>
-#endif
-
-#if APR_HAVE_WINSOCK2_H
-#include <winsock2.h>
-#endif
-
-#if APR_HAVE_SYS_TYPES_H
-#include <sys/types.h>
-#endif
-
-#if APR_HAVE_SYS_SOCKET_H
-#include <sys/socket.h>
-#endif
-
-#if defined(__cplusplus) && !defined(__STDC_CONSTANT_MACROS)
-/* C99 7.18.4 requires that stdint.h only exposes INT64_C
- * and UINT64_C for C++ implementations if this is defined: */
-#define __STDC_CONSTANT_MACROS
-#endif
-
-#if APR_HAVE_STDINT_H
-#include <stdint.h>
-#endif
-
-#if APR_HAVE_SYS_WAIT_H
-#include <sys/wait.h>
-#endif
-
-#ifdef OS2
-#define INCL_DOS
-#define INCL_DOSERRORS
-#include <os2.h>
-#endif
-
-/* header files for PATH_MAX, _POSIX_PATH_MAX */
-#if APR_HAVE_LIMITS_H
-#include <limits.h>
-#else
-#if APR_HAVE_SYS_SYSLIMITS_H
-#include <sys/syslimits.h>
-#endif
-#endif
-
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/**
- * @addtogroup apr_platform
- * @ingroup APR
- * @{
- */
-
-#define APR_HAVE_SHMEM_MMAP_TMP 1
-#define APR_HAVE_SHMEM_MMAP_SHM 1
-#define APR_HAVE_SHMEM_MMAP_ZERO 1
-#define APR_HAVE_SHMEM_SHMGET_ANON 1
-#define APR_HAVE_SHMEM_SHMGET 1
-#define APR_HAVE_SHMEM_MMAP_ANON 1
-#define APR_HAVE_SHMEM_BEOS 0
-
-#define APR_USE_SHMEM_MMAP_TMP 0
-#define APR_USE_SHMEM_MMAP_SHM 0
-#define APR_USE_SHMEM_MMAP_ZERO 0
-#define APR_USE_SHMEM_SHMGET_ANON 0
-#define APR_USE_SHMEM_SHMGET 1
-#define APR_USE_SHMEM_MMAP_ANON 1
-#define APR_USE_SHMEM_BEOS 0
-
-#define APR_USE_FLOCK_SERIALIZE 0
-#define APR_USE_SYSVSEM_SERIALIZE 1
-#define APR_USE_POSIXSEM_SERIALIZE 0
-#define APR_USE_FCNTL_SERIALIZE 0
-#define APR_USE_PROC_PTHREAD_SERIALIZE 0
-#define APR_USE_PTHREAD_SERIALIZE 1
-
-#define APR_HAS_FLOCK_SERIALIZE 1
-#define APR_HAS_SYSVSEM_SERIALIZE 1
-#define APR_HAS_POSIXSEM_SERIALIZE 1
-#define APR_HAS_FCNTL_SERIALIZE 1
-#define APR_HAS_PROC_PTHREAD_SERIALIZE 1
-
-#define APR_PROCESS_LOCK_IS_GLOBAL 0
-
-#define APR_HAVE_CORKABLE_TCP 1
-#define APR_HAVE_GETRLIMIT 1
-#define APR_HAVE_IN_ADDR 1
-#define APR_HAVE_INET_ADDR 1
-#define APR_HAVE_INET_NETWORK 1
-#define APR_HAVE_IPV6 1
-#define APR_HAVE_MEMMOVE 1
-#define APR_HAVE_SETRLIMIT 1
-#define APR_HAVE_SIGACTION 1
-#define APR_HAVE_SIGSUSPEND 1
-#define APR_HAVE_SIGWAIT 1
-#define APR_HAVE_SA_STORAGE 1
-#define APR_HAVE_STRCASECMP 1
-#define APR_HAVE_STRDUP 1
-#define APR_HAVE_STRICMP 0
-#define APR_HAVE_STRNCASECMP 1
-#define APR_HAVE_STRNICMP 0
-#define APR_HAVE_STRSTR 1
-#define APR_HAVE_MEMCHR 1
-#define APR_HAVE_STRUCT_RLIMIT 1
-#define APR_HAVE_UNION_SEMUN 0
-#define APR_HAVE_SCTP 0
-#define APR_HAVE_IOVEC 1
-
-/* APR Feature Macros */
-#define APR_HAS_SHARED_MEMORY 1
-#define APR_HAS_THREADS 1
-#define APR_HAS_SENDFILE 1
-#define APR_HAS_MMAP 1
-#define APR_HAS_FORK 1
-#define APR_HAS_RANDOM 1
-#define APR_HAS_OTHER_CHILD 1
-#define APR_HAS_DSO 1
-#define APR_HAS_SO_ACCEPTFILTER 0
-#define APR_HAS_UNICODE_FS 0
-#define APR_HAS_PROC_INVOKED 0
-#define APR_HAS_USER 1
-#define APR_HAS_LARGE_FILES 0
-#define APR_HAS_XTHREAD_FILES 0
-#define APR_HAS_OS_UUID 0
-
-#define APR_PROCATTR_USER_SET_REQUIRES_PASSWORD 0
-
-/* APR sets APR_FILES_AS_SOCKETS to 1 on systems where it is possible
- * to poll on files/pipes.
- */
-#define APR_FILES_AS_SOCKETS 1
-
-/* This macro indicates whether or not EBCDIC is the native character set.
- */
-#define APR_CHARSET_EBCDIC 0
-
-/* If we have a TCP implementation that can be "corked", what flag
- * do we use?
- */
-#define APR_TCP_NOPUSH_FLAG TCP_CORK
-
-/* Is the TCP_NODELAY socket option inherited from listening sockets?
-*/
-#define APR_TCP_NODELAY_INHERITED 1
-
-/* Is the O_NONBLOCK flag inherited from listening sockets?
-*/
-#define APR_O_NONBLOCK_INHERITED 0
-
-/* Typedefs that APR needs. */
-
-typedef unsigned char apr_byte_t;
-
-typedef short apr_int16_t;
-typedef unsigned short apr_uint16_t;
-
-typedef int apr_int32_t;
-typedef unsigned int apr_uint32_t;
-
-typedef long apr_int64_t;
-typedef unsigned long apr_uint64_t;
-
-typedef size_t apr_size_t;
-typedef ssize_t apr_ssize_t;
-typedef off_t apr_off_t;
-typedef socklen_t apr_socklen_t;
-typedef ino_t apr_ino_t;
-
-#define APR_SIZEOF_VOIDP 8
-
-#if APR_SIZEOF_VOIDP == 8
-typedef apr_uint64_t apr_uintptr_t;
-#else
-typedef apr_uint32_t apr_uintptr_t;
-#endif
-
-/* Are we big endian? */
-#define APR_IS_BIGENDIAN 0
-
-/* Mechanisms to properly type numeric literals */
-#define APR_INT64_C(val) INT64_C(val)
-#define APR_UINT64_C(val) UINT64_C(val)
-
-#ifdef INT16_MIN
-#define APR_INT16_MIN INT16_MIN
-#else
-#define APR_INT16_MIN (-0x7fff - 1)
-#endif
-
-#ifdef INT16_MAX
-#define APR_INT16_MAX INT16_MAX
-#else
-#define APR_INT16_MAX (0x7fff)
-#endif
-
-#ifdef UINT16_MAX
-#define APR_UINT16_MAX UINT16_MAX
-#else
-#define APR_UINT16_MAX (0xffff)
-#endif
-
-#ifdef INT32_MIN
-#define APR_INT32_MIN INT32_MIN
-#else
-#define APR_INT32_MIN (-0x7fffffff - 1)
-#endif
-
-#ifdef INT32_MAX
-#define APR_INT32_MAX INT32_MAX
-#else
-#define APR_INT32_MAX 0x7fffffff
-#endif
-
-#ifdef UINT32_MAX
-#define APR_UINT32_MAX UINT32_MAX
-#else
-#define APR_UINT32_MAX (0xffffffffU)
-#endif
-
-#ifdef INT64_MIN
-#define APR_INT64_MIN INT64_MIN
-#else
-#define APR_INT64_MIN (APR_INT64_C(-0x7fffffffffffffff) - 1)
-#endif
-
-#ifdef INT64_MAX
-#define APR_INT64_MAX INT64_MAX
-#else
-#define APR_INT64_MAX APR_INT64_C(0x7fffffffffffffff)
-#endif
-
-#ifdef UINT64_MAX
-#define APR_UINT64_MAX UINT64_MAX
-#else
-#define APR_UINT64_MAX APR_UINT64_C(0xffffffffffffffff)
-#endif
-
-#define APR_SIZE_MAX (~((apr_size_t)0))
-
-
-/* Definitions that APR programs need to work properly. */
-
-/**
- * APR public API wrap for C++ compilers.
- */
-#ifdef __cplusplus
-#define APR_BEGIN_DECLS extern "C" {
-#define APR_END_DECLS }
-#else
-#define APR_BEGIN_DECLS
-#define APR_END_DECLS
-#endif
-
-/**
- * Thread callbacks from APR functions must be declared with APR_THREAD_FUNC,
- * so that they follow the platform's calling convention.
- * <PRE>
- *
- * void* APR_THREAD_FUNC my_thread_entry_fn(apr_thread_t *thd, void *data);
- *
- * </PRE>
- */
-#define APR_THREAD_FUNC
-
-/**
- * The public APR functions are declared with APR_DECLARE(), so they may
- * use the most appropriate calling convention. Public APR functions with
- * variable arguments must use APR_DECLARE_NONSTD().
- *
- * @remark Both the declaration and implementations must use the same macro.
- *
- * <PRE>
- * APR_DECLARE(rettype) apr_func(args)
- * </PRE>
- * @see APR_DECLARE_NONSTD @see APR_DECLARE_DATA
- * @remark Note that when APR compiles the library itself, it passes the
- * symbol -DAPR_DECLARE_EXPORT to the compiler on some platforms (e.g. Win32)
- * to export public symbols from the dynamic library build.\n
- * The user must define the APR_DECLARE_STATIC when compiling to target
- * the static APR library on some platforms (e.g. Win32.) The public symbols
- * are neither exported nor imported when APR_DECLARE_STATIC is defined.\n
- * By default, compiling an application and including the APR public
- * headers, without defining APR_DECLARE_STATIC, will prepare the code to be
- * linked to the dynamic library.
- */
-#define APR_DECLARE(type) type
-
-/**
- * The public APR functions using variable arguments are declared with
- * APR_DECLARE_NONSTD(), as they must follow the C language calling convention.
- * @see APR_DECLARE @see APR_DECLARE_DATA
- * @remark Both the declaration and implementations must use the same macro.
- * <PRE>
- *
- * APR_DECLARE_NONSTD(rettype) apr_func(args, ...);
- *
- * </PRE>
- */
-#define APR_DECLARE_NONSTD(type) type
-
-/**
- * The public APR variables are declared with AP_MODULE_DECLARE_DATA.
- * This assures the appropriate indirection is invoked at compile time.
- * @see APR_DECLARE @see APR_DECLARE_NONSTD
- * @remark Note that the declaration and implementations use different forms,
- * but both must include the macro.
- *
- * <PRE>
- *
- * extern APR_DECLARE_DATA type apr_variable;\n
- * APR_DECLARE_DATA type apr_variable = value;
- *
- * </PRE>
- */
-#define APR_DECLARE_DATA
-
-/* Define APR_SSIZE_T_FMT.
- * If ssize_t is an integer we define it to be "d",
- * if ssize_t is a long int we define it to be "ld",
- * if ssize_t is neither we declare an error here.
- * I looked for a better way to define this here, but couldn't find one, so
- * to find the logic for this definition search for "ssize_t_fmt" in
- * configure.in.
- */
-#define APR_SSIZE_T_FMT "ld"
-
-/* And APR_SIZE_T_FMT */
-#define APR_SIZE_T_FMT "lu"
-
-/* And APR_OFF_T_FMT */
-#define APR_OFF_T_FMT "ld"
-
-/* And APR_PID_T_FMT */
-#define APR_PID_T_FMT "d"
-
-/* And APR_INT64_T_FMT */
-#define APR_INT64_T_FMT "ld"
-
-/* And APR_UINT64_T_FMT */
-#define APR_UINT64_T_FMT "lu"
-
-/* And APR_UINT64_T_HEX_FMT */
-#define APR_UINT64_T_HEX_FMT "lx"
-
-/* Does the proc mutex lock threads too */
-#define APR_PROC_MUTEX_IS_GLOBAL 0
-
-/* Local machine definition for console and log output. */
-#define APR_EOL_STR "\n"
-
-#if APR_HAVE_SYS_WAIT_H
-#ifdef WEXITSTATUS
-#define apr_wait_t int
-#else
-#define apr_wait_t union wait
-#define WEXITSTATUS(status) (int)((status).w_retcode)
-#define WTERMSIG(status) (int)((status).w_termsig)
-#endif /* !WEXITSTATUS */
-#elif defined(__MINGW32__)
-typedef int apr_wait_t;
-#endif /* HAVE_SYS_WAIT_H */
-
-#if defined(PATH_MAX)
-#define APR_PATH_MAX PATH_MAX
-#elif defined(_POSIX_PATH_MAX)
-#define APR_PATH_MAX _POSIX_PATH_MAX
-#else
-#error no decision has been made on APR_PATH_MAX for your platform
-#endif
-
-#define APR_DSOPATH "LD_LIBRARY_PATH"
-
-/** @} */
-
-/* Definitions that only Win32 programs need to compile properly. */
-
-/* XXX These simply don't belong here, perhaps in apr_portable.h
- * based on some APR_HAVE_PID/GID/UID?
- */
-#ifdef __MINGW32__
-#ifndef __GNUC__
-typedef int pid_t;
-#endif
-typedef int uid_t;
-typedef int gid_t;
-#endif
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* APR_H */
+++ /dev/null
-/* include/arch/unix/apr_private.h. Generated from apr_private.h.in by configure. */
-/* include/arch/unix/apr_private.h.in. Generated from configure.in by autoheader. */
-
-
-#ifndef APR_PRIVATE_H
-#define APR_PRIVATE_H
-
-
-/* Define as function which can be used for conversion of strings to
- apr_int64_t */
-#define APR_INT64_STRFN strtol
-
-/* Define as function used for conversion of strings to apr_off_t */
-#define APR_OFF_T_STRFN strtol
-
-/* Define to one of `_getb67', `GETB67', `getb67' for Cray-2 and Cray-YMP
- systems. This function is required for `alloca.c' support on those systems.
- */
-/* #undef CRAY_STACKSEG_END */
-
-/* Define to 1 if using `alloca.c'. */
-/* #undef C_ALLOCA */
-
-/* Define to path of random device */
-#define DEV_RANDOM "/dev/urandom"
-
-/* Define if struct dirent has an inode member */
-#define DIRENT_INODE d_fileno
-
-/* Define if struct dirent has a d_type member */
-#define DIRENT_TYPE d_type
-
-/* Define if DSO support uses dlfcn.h */
-#define DSO_USE_DLFCN 1
-
-/* Define if DSO support uses dyld.h */
-/* #undef DSO_USE_DYLD */
-
-/* Define if DSO support uses shl_load */
-/* #undef DSO_USE_SHL */
-
-/* Define to list of paths to EGD sockets */
-/* #undef EGD_DEFAULT_SOCKET */
-
-/* Define if fcntl locks affect threads within the process */
-/* #undef FCNTL_IS_GLOBAL */
-
-/* Define if fcntl returns EACCES when F_SETLK is already held */
-/* #undef FCNTL_TRYACQUIRE_EACCES */
-
-/* Define if flock locks affect threads within the process */
-/* #undef FLOCK_IS_GLOBAL */
-
-/* Define if gethostbyaddr is thread safe */
-/* #undef GETHOSTBYADDR_IS_THREAD_SAFE */
-
-/* Define if gethostbyname is thread safe */
-/* #undef GETHOSTBYNAME_IS_THREAD_SAFE */
-
-/* Define if gethostbyname_r has the glibc style */
-#define GETHOSTBYNAME_R_GLIBC2 1
-
-/* Define if gethostbyname_r has the hostent_data for the third argument */
-/* #undef GETHOSTBYNAME_R_HOSTENT_DATA */
-
-/* Define if getservbyname is thread safe */
-/* #undef GETSERVBYNAME_IS_THREAD_SAFE */
-
-/* Define if getservbyname_r has the glibc style */
-#define GETSERVBYNAME_R_GLIBC2 1
-
-/* Define if getservbyname_r has the OSF/1 style */
-/* #undef GETSERVBYNAME_R_OSF1 */
-
-/* Define if getservbyname_r has the Solaris style */
-/* #undef GETSERVBYNAME_R_SOLARIS */
-
-/* Define if accept4 function is supported */
-/* #undef HAVE_ACCEPT4 */
-
-/* Define to 1 if you have `alloca', as a function or macro. */
-#define HAVE_ALLOCA 1
-
-/* Define to 1 if you have <alloca.h> and it should be used (not on Ultrix).
- */
-#define HAVE_ALLOCA_H 1
-
-/* Define to 1 if you have the <arpa/inet.h> header file. */
-#define HAVE_ARPA_INET_H 1
-
-/* Define if compiler provides atomic builtins */
-#define HAVE_ATOMIC_BUILTINS 1
-
-/* Define if BONE_VERSION is defined in sys/socket.h */
-/* #undef HAVE_BONE_VERSION */
-
-/* Define to 1 if you have the <ByteOrder.h> header file. */
-/* #undef HAVE_BYTEORDER_H */
-
-/* Define to 1 if you have the `calloc' function. */
-#define HAVE_CALLOC 1
-
-/* Define to 1 if you have the <conio.h> header file. */
-/* #undef HAVE_CONIO_H */
-
-/* Define to 1 if you have the `create_area' function. */
-/* #undef HAVE_CREATE_AREA */
-
-/* Define to 1 if you have the `create_sem' function. */
-/* #undef HAVE_CREATE_SEM */
-
-/* Define to 1 if you have the <crypt.h> header file. */
-#define HAVE_CRYPT_H 1
-
-/* Define to 1 if you have the <ctype.h> header file. */
-#define HAVE_CTYPE_H 1
-
-/* Define to 1 if you have the declaration of `sys_siglist', and to 0 if you
- don't. */
-#define HAVE_DECL_SYS_SIGLIST 1
-
-/* Define to 1 if you have the <dirent.h> header file. */
-#define HAVE_DIRENT_H 1
-
-/* Define to 1 if you have the <dir.h> header file. */
-/* #undef HAVE_DIR_H */
-
-/* Define to 1 if you have the <dlfcn.h> header file. */
-#define HAVE_DLFCN_H 1
-
-/* Define to 1 if you have the <dl.h> header file. */
-/* #undef HAVE_DL_H */
-
-/* Define if dup3 function is supported */
-/* #undef HAVE_DUP3 */
-
-/* Define if EGD is supported */
-/* #undef HAVE_EGD */
-
-/* Define if the epoll interface is supported */
-#define HAVE_EPOLL 1
-
-/* Define if epoll_create1 function is supported */
-/* #undef HAVE_EPOLL_CREATE1 */
-
-/* Define to 1 if you have the <errno.h> header file. */
-#define HAVE_ERRNO_H 1
-
-/* Define to 1 if you have the <fcntl.h> header file. */
-#define HAVE_FCNTL_H 1
-
-/* Define to 1 if you have the `fdatasync' function. */
-#define HAVE_FDATASYNC 1
-
-/* Define to 1 if you have the `flock' function. */
-#define HAVE_FLOCK 1
-
-/* Define to 1 if you have the `fork' function. */
-#define HAVE_FORK 1
-
-/* Define if F_SETLK is defined in fcntl.h */
-#define HAVE_F_SETLK 1
-
-/* Define if getaddrinfo accepts the AI_ADDRCONFIG flag */
-#define HAVE_GAI_ADDRCONFIG 1
-
-/* Define to 1 if you have the `gai_strerror' function. */
-#define HAVE_GAI_STRERROR 1
-
-/* Define if getaddrinfo exists and works well enough for APR */
-#define HAVE_GETADDRINFO 1
-
-/* Define to 1 if you have the `getenv' function. */
-#define HAVE_GETENV 1
-
-/* Define to 1 if you have the `getgrgid_r' function. */
-#define HAVE_GETGRGID_R 1
-
-/* Define to 1 if you have the `getgrnam_r' function. */
-#define HAVE_GETGRNAM_R 1
-
-/* Define to 1 if you have the `gethostbyaddr_r' function. */
-#define HAVE_GETHOSTBYADDR_R 1
-
-/* Define to 1 if you have the `gethostbyname_r' function. */
-#define HAVE_GETHOSTBYNAME_R 1
-
-/* Define to 1 if you have the `getifaddrs' function. */
-#define HAVE_GETIFADDRS 1
-
-/* Define if getnameinfo exists */
-#define HAVE_GETNAMEINFO 1
-
-/* Define to 1 if you have the `getpass' function. */
-#define HAVE_GETPASS 1
-
-/* Define to 1 if you have the `getpassphrase' function. */
-/* #undef HAVE_GETPASSPHRASE */
-
-/* Define to 1 if you have the `getpwnam_r' function. */
-#define HAVE_GETPWNAM_R 1
-
-/* Define to 1 if you have the `getpwuid_r' function. */
-#define HAVE_GETPWUID_R 1
-
-/* Define to 1 if you have the `getrlimit' function. */
-#define HAVE_GETRLIMIT 1
-
-/* Define to 1 if you have the `getservbyname_r' function. */
-#define HAVE_GETSERVBYNAME_R 1
-
-/* Define to 1 if you have the `gmtime_r' function. */
-#define HAVE_GMTIME_R 1
-
-/* Define to 1 if you have the <grp.h> header file. */
-#define HAVE_GRP_H 1
-
-/* Define if hstrerror is present */
-/* #undef HAVE_HSTRERROR */
-
-/* Define to 1 if you have the <inttypes.h> header file. */
-#define HAVE_INTTYPES_H 1
-
-/* Define to 1 if you have the <io.h> header file. */
-/* #undef HAVE_IO_H */
-
-/* Define to 1 if you have the `isinf' function. */
-#define HAVE_ISINF 1
-
-/* Define to 1 if you have the `isnan' function. */
-#define HAVE_ISNAN 1
-
-/* Define to 1 if you have the <kernel/OS.h> header file. */
-/* #undef HAVE_KERNEL_OS_H */
-
-/* Define to 1 if you have the `kqueue' function. */
-/* #undef HAVE_KQUEUE */
-
-/* Define to 1 if you have the <langinfo.h> header file. */
-#define HAVE_LANGINFO_H 1
-
-/* Enable if this library is available */
-/* #undef HAVE_LIBADVAPI32 */
-
-/* Define to 1 if you have the `bsd' library (-lbsd). */
-/* #undef HAVE_LIBBSD */
-
-/* Enable if this library is available */
-/* #undef HAVE_LIBKERNEL32 */
-
-/* Define to 1 if you have the `msvcrt' library (-lmsvcrt). */
-/* #undef HAVE_LIBMSVCRT */
-
-/* Enable if this library is available */
-/* #undef HAVE_LIBRPCRT4 */
-
-/* Define to 1 if you have the `sendfile' library (-lsendfile). */
-/* #undef HAVE_LIBSENDFILE */
-
-/* Enable if this library is available */
-/* #undef HAVE_LIBSHELL32 */
-
-/* Define to 1 if you have the `truerand' library (-ltruerand). */
-/* #undef HAVE_LIBTRUERAND */
-
-/* Enable if this library is available */
-/* #undef HAVE_LIBWS2_32 */
-
-/* Define to 1 if you have the <limits.h> header file. */
-#define HAVE_LIMITS_H 1
-
-/* Define to 1 if you have the `localtime_r' function. */
-#define HAVE_LOCALTIME_R 1
-
-/* Define if LOCK_EX is defined in sys/file.h */
-#define HAVE_LOCK_EX 1
-
-/* Define to 1 if you have the <mach-o/dyld.h> header file. */
-/* #undef HAVE_MACH_O_DYLD_H */
-
-/* Define to 1 if you have the <malloc.h> header file. */
-#define HAVE_MALLOC_H 1
-
-/* Define if MAP_ANON is defined in sys/mman.h */
-#define HAVE_MAP_ANON 1
-
-/* Define to 1 if you have the `memchr' function. */
-#define HAVE_MEMCHR 1
-
-/* Define to 1 if you have the `memmove' function. */
-#define HAVE_MEMMOVE 1
-
-/* Define to 1 if you have the <memory.h> header file. */
-#define HAVE_MEMORY_H 1
-
-/* Define to 1 if you have the `mkstemp' function. */
-#define HAVE_MKSTEMP 1
-
-/* Define to 1 if you have the `mkstemp64' function. */
-/* #undef HAVE_MKSTEMP64 */
-
-/* Define to 1 if you have the `mmap' function. */
-#define HAVE_MMAP 1
-
-/* Define to 1 if you have the `mmap64' function. */
-/* #undef HAVE_MMAP64 */
-
-/* Define to 1 if you have the `munmap' function. */
-#define HAVE_MUNMAP 1
-
-/* Define to 1 if you have the <netdb.h> header file. */
-#define HAVE_NETDB_H 1
-
-/* Define to 1 if you have the <netinet/in.h> header file. */
-#define HAVE_NETINET_IN_H 1
-
-/* Define to 1 if you have the <netinet/sctp.h> header file. */
-/* #undef HAVE_NETINET_SCTP_H */
-
-/* Define to 1 if you have the <netinet/sctp_uio.h> header file. */
-/* #undef HAVE_NETINET_SCTP_UIO_H */
-
-/* Defined if netinet/tcp.h is present */
-#define HAVE_NETINET_TCP_H 1
-
-/* Define to 1 if you have the <net/errno.h> header file. */
-/* #undef HAVE_NET_ERRNO_H */
-
-/* Define to 1 if you have the `nl_langinfo' function. */
-#define HAVE_NL_LANGINFO 1
-
-/* Define to 1 if you have the <os2.h> header file. */
-/* #undef HAVE_OS2_H */
-
-/* Define to 1 if you have the <osreldate.h> header file. */
-/* #undef HAVE_OSRELDATE_H */
-
-/* Define to 1 if you have the <OS.h> header file. */
-/* #undef HAVE_OS_H */
-
-/* Define to 1 if you have the `poll' function. */
-#define HAVE_POLL 1
-
-/* Define if POLLIN is defined */
-#define HAVE_POLLIN 1
-
-/* Define to 1 if you have the <poll.h> header file. */
-#define HAVE_POLL_H 1
-
-/* Define to 1 if you have the `port_create' function. */
-/* #undef HAVE_PORT_CREATE */
-
-/* Define to 1 if you have the <process.h> header file. */
-/* #undef HAVE_PROCESS_H */
-
-/* Define to 1 if you have the `pthread_attr_setguardsize' function. */
-#define HAVE_PTHREAD_ATTR_SETGUARDSIZE 1
-
-/* Define to 1 if you have the <pthread.h> header file. */
-#define HAVE_PTHREAD_H 1
-
-/* Define to 1 if you have the `pthread_key_delete' function. */
-#define HAVE_PTHREAD_KEY_DELETE 1
-
-/* Define to 1 if you have the `pthread_mutexattr_setpshared' function. */
-#define HAVE_PTHREAD_MUTEXATTR_SETPSHARED 1
-
-/* Define if recursive pthread mutexes are available */
-#define HAVE_PTHREAD_MUTEX_RECURSIVE 1
-
-/* Define if cross-process robust mutexes are available */
-#define HAVE_PTHREAD_MUTEX_ROBUST 1
-
-/* Define if PTHREAD_PROCESS_SHARED is defined in pthread.h */
-#define HAVE_PTHREAD_PROCESS_SHARED 1
-
-/* Define if pthread rwlocks are available */
-#define HAVE_PTHREAD_RWLOCKS 1
-
-/* Define to 1 if you have the `pthread_rwlock_init' function. */
-#define HAVE_PTHREAD_RWLOCK_INIT 1
-
-/* Define to 1 if you have the `pthread_yield' function. */
-#define HAVE_PTHREAD_YIELD 1
-
-/* Define to 1 if you have the `putenv' function. */
-#define HAVE_PUTENV 1
-
-/* Define to 1 if you have the <pwd.h> header file. */
-#define HAVE_PWD_H 1
-
-/* Define to 1 if you have the `readdir64_r' function. */
-/* #undef HAVE_READDIR64_R */
-
-/* Define to 1 if you have the <sched.h> header file. */
-/* #undef HAVE_SCHED_H */
-
-/* Define to 1 if you have the `sched_yield' function. */
-/* #undef HAVE_SCHED_YIELD */
-
-/* Define to 1 if you have the <semaphore.h> header file. */
-#define HAVE_SEMAPHORE_H 1
-
-/* Define to 1 if you have the `semctl' function. */
-#define HAVE_SEMCTL 1
-
-/* Define to 1 if you have the `semget' function. */
-#define HAVE_SEMGET 1
-
-/* Define to 1 if you have the `sem_close' function. */
-#define HAVE_SEM_CLOSE 1
-
-/* Define to 1 if you have the `sem_post' function. */
-#define HAVE_SEM_POST 1
-
-/* Define if SEM_UNDO is defined in sys/sem.h */
-#define HAVE_SEM_UNDO 1
-
-/* Define to 1 if you have the `sem_unlink' function. */
-#define HAVE_SEM_UNLINK 1
-
-/* Define to 1 if you have the `sem_wait' function. */
-#define HAVE_SEM_WAIT 1
-
-/* Define to 1 if you have the `sendfile' function. */
-#define HAVE_SENDFILE 1
-
-/* Define to 1 if you have the `sendfile64' function. */
-/* #undef HAVE_SENDFILE64 */
-
-/* Define to 1 if you have the `sendfilev' function. */
-/* #undef HAVE_SENDFILEV */
-
-/* Define to 1 if you have the `sendfilev64' function. */
-/* #undef HAVE_SENDFILEV64 */
-
-/* Define to 1 if you have the `send_file' function. */
-/* #undef HAVE_SEND_FILE */
-
-/* Define to 1 if you have the `setenv' function. */
-#define HAVE_SETENV 1
-
-/* Define to 1 if you have the `setrlimit' function. */
-#define HAVE_SETRLIMIT 1
-
-/* Define to 1 if you have the `setsid' function. */
-#define HAVE_SETSID 1
-
-/* Define to 1 if you have the `set_h_errno' function. */
-/* #undef HAVE_SET_H_ERRNO */
-
-/* Define to 1 if you have the `shmat' function. */
-#define HAVE_SHMAT 1
-
-/* Define to 1 if you have the `shmctl' function. */
-#define HAVE_SHMCTL 1
-
-/* Define to 1 if you have the `shmdt' function. */
-#define HAVE_SHMDT 1
-
-/* Define to 1 if you have the `shmget' function. */
-#define HAVE_SHMGET 1
-
-/* Define to 1 if you have the `shm_open' function. */
-#define HAVE_SHM_OPEN 1
-
-/* Define to 1 if you have the `shm_unlink' function. */
-#define HAVE_SHM_UNLINK 1
-
-/* Define to 1 if you have the `sigaction' function. */
-#define HAVE_SIGACTION 1
-
-/* Define to 1 if you have the <signal.h> header file. */
-#define HAVE_SIGNAL_H 1
-
-/* Define to 1 if you have the `sigsuspend' function. */
-#define HAVE_SIGSUSPEND 1
-
-/* Define to 1 if you have the `sigwait' function. */
-#define HAVE_SIGWAIT 1
-
-/* Whether you have socklen_t */
-#define HAVE_SOCKLEN_T 1
-
-/* Define if the SOCK_CLOEXEC flag is supported */
-/* #undef HAVE_SOCK_CLOEXEC */
-
-/* Define if SO_ACCEPTFILTER is defined in sys/socket.h */
-/* #undef HAVE_SO_ACCEPTFILTER */
-
-/* Define to 1 if you have the <stdarg.h> header file. */
-#define HAVE_STDARG_H 1
-
-/* Define to 1 if you have the <stddef.h> header file. */
-#define HAVE_STDDEF_H 1
-
-/* Define to 1 if you have the <stdint.h> header file. */
-#define HAVE_STDINT_H 1
-
-/* Define to 1 if you have the <stdio.h> header file. */
-#define HAVE_STDIO_H 1
-
-/* Define to 1 if you have the <stdlib.h> header file. */
-#define HAVE_STDLIB_H 1
-
-/* Define to 1 if you have the `strcasecmp' function. */
-#define HAVE_STRCASECMP 1
-
-/* Define to 1 if you have the `strdup' function. */
-#define HAVE_STRDUP 1
-
-/* Define to 1 if you have the `strerror_r' function. */
-#define HAVE_STRERROR_R 1
-
-/* Define to 1 if you have the `stricmp' function. */
-/* #undef HAVE_STRICMP */
-
-/* Define to 1 if you have the <strings.h> header file. */
-#define HAVE_STRINGS_H 1
-
-/* Define to 1 if you have the <string.h> header file. */
-#define HAVE_STRING_H 1
-
-/* Define to 1 if you have the `strncasecmp' function. */
-#define HAVE_STRNCASECMP 1
-
-/* Define to 1 if you have the `strnicmp' function. */
-/* #undef HAVE_STRNICMP */
-
-/* Define to 1 if you have the `strstr' function. */
-#define HAVE_STRSTR 1
-
-/* Define if struct impreq was found */
-#define HAVE_STRUCT_IPMREQ 1
-
-/* Define to 1 if `st_atimensec' is member of `struct stat'. */
-/* #undef HAVE_STRUCT_STAT_ST_ATIMENSEC */
-
-/* Define to 1 if `st_atime_n' is member of `struct stat'. */
-/* #undef HAVE_STRUCT_STAT_ST_ATIME_N */
-
-/* Define to 1 if `st_atim.tv_nsec' is member of `struct stat'. */
-#define HAVE_STRUCT_STAT_ST_ATIM_TV_NSEC 1
-
-/* Define to 1 if `st_blocks' is member of `struct stat'. */
-#define HAVE_STRUCT_STAT_ST_BLOCKS 1
-
-/* Define to 1 if `st_ctimensec' is member of `struct stat'. */
-/* #undef HAVE_STRUCT_STAT_ST_CTIMENSEC */
-
-/* Define to 1 if `st_ctime_n' is member of `struct stat'. */
-/* #undef HAVE_STRUCT_STAT_ST_CTIME_N */
-
-/* Define to 1 if `st_ctim.tv_nsec' is member of `struct stat'. */
-#define HAVE_STRUCT_STAT_ST_CTIM_TV_NSEC 1
-
-/* Define to 1 if `st_mtimensec' is member of `struct stat'. */
-/* #undef HAVE_STRUCT_STAT_ST_MTIMENSEC */
-
-/* Define to 1 if `st_mtime_n' is member of `struct stat'. */
-/* #undef HAVE_STRUCT_STAT_ST_MTIME_N */
-
-/* Define to 1 if `st_mtim.tv_nsec' is member of `struct stat'. */
-#define HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC 1
-
-/* Define to 1 if `tm_gmtoff' is member of `struct tm'. */
-#define HAVE_STRUCT_TM_TM_GMTOFF 1
-
-/* Define to 1 if `__tm_gmtoff' is member of `struct tm'. */
-/* #undef HAVE_STRUCT_TM___TM_GMTOFF */
-
-/* Define to 1 if you have the <sysapi.h> header file. */
-/* #undef HAVE_SYSAPI_H */
-
-/* Define to 1 if you have the <sysgtime.h> header file. */
-/* #undef HAVE_SYSGTIME_H */
-
-/* Define to 1 if you have the <sys/file.h> header file. */
-#define HAVE_SYS_FILE_H 1
-
-/* Define to 1 if you have the <sys/ioctl.h> header file. */
-#define HAVE_SYS_IOCTL_H 1
-
-/* Define to 1 if you have the <sys/ipc.h> header file. */
-#define HAVE_SYS_IPC_H 1
-
-/* Define to 1 if you have the <sys/mman.h> header file. */
-#define HAVE_SYS_MMAN_H 1
-
-/* Define to 1 if you have the <sys/mutex.h> header file. */
-/* #undef HAVE_SYS_MUTEX_H */
-
-/* Define to 1 if you have the <sys/param.h> header file. */
-#define HAVE_SYS_PARAM_H 1
-
-/* Define to 1 if you have the <sys/poll.h> header file. */
-#define HAVE_SYS_POLL_H 1
-
-/* Define to 1 if you have the <sys/resource.h> header file. */
-#define HAVE_SYS_RESOURCE_H 1
-
-/* Define to 1 if you have the <sys/select.h> header file. */
-#define HAVE_SYS_SELECT_H 1
-
-/* Define to 1 if you have the <sys/sem.h> header file. */
-#define HAVE_SYS_SEM_H 1
-
-/* Define to 1 if you have the <sys/sendfile.h> header file. */
-#define HAVE_SYS_SENDFILE_H 1
-
-/* Define to 1 if you have the <sys/shm.h> header file. */
-#define HAVE_SYS_SHM_H 1
-
-/* Define to 1 if you have the <sys/signal.h> header file. */
-#define HAVE_SYS_SIGNAL_H 1
-
-/* Define to 1 if you have the <sys/socket.h> header file. */
-#define HAVE_SYS_SOCKET_H 1
-
-/* Define to 1 if you have the <sys/sockio.h> header file. */
-/* #undef HAVE_SYS_SOCKIO_H */
-
-/* Define to 1 if you have the <sys/stat.h> header file. */
-#define HAVE_SYS_STAT_H 1
-
-/* Define to 1 if you have the <sys/sysctl.h> header file. */
-#define HAVE_SYS_SYSCTL_H 1
-
-/* Define to 1 if you have the <sys/syslimits.h> header file. */
-/* #undef HAVE_SYS_SYSLIMITS_H */
-
-/* Define to 1 if you have the <sys/time.h> header file. */
-#define HAVE_SYS_TIME_H 1
-
-/* Define to 1 if you have the <sys/types.h> header file. */
-#define HAVE_SYS_TYPES_H 1
-
-/* Define to 1 if you have the <sys/uio.h> header file. */
-#define HAVE_SYS_UIO_H 1
-
-/* Define to 1 if you have the <sys/un.h> header file. */
-#define HAVE_SYS_UN_H 1
-
-/* Define to 1 if you have the <sys/uuid.h> header file. */
-/* #undef HAVE_SYS_UUID_H */
-
-/* Define to 1 if you have the <sys/wait.h> header file. */
-#define HAVE_SYS_WAIT_H 1
-
-/* Define if TCP_CORK is defined in netinet/tcp.h */
-#define HAVE_TCP_CORK 1
-
-/* Define if TCP_NODELAY and TCP_CORK can be enabled at the same time */
-#define HAVE_TCP_NODELAY_WITH_CORK 1
-
-/* Define if TCP_NOPUSH is defined in netinet/tcp.h */
-/* #undef HAVE_TCP_NOPUSH */
-
-/* Define to 1 if you have the <termios.h> header file. */
-#define HAVE_TERMIOS_H 1
-
-/* Define to 1 if you have the <time.h> header file. */
-#define HAVE_TIME_H 1
-
-/* Define to 1 if you have the <tpfeq.h> header file. */
-/* #undef HAVE_TPFEQ_H */
-
-/* Define to 1 if you have the <tpfio.h> header file. */
-/* #undef HAVE_TPFIO_H */
-
-/* Define if truerand is supported */
-/* #undef HAVE_TRUERAND */
-
-/* Define to 1 if you have the <unistd.h> header file. */
-#define HAVE_UNISTD_H 1
-
-/* Define to 1 if you have the <unix.h> header file. */
-/* #undef HAVE_UNIX_H */
-
-/* Define to 1 if you have the `unsetenv' function. */
-#define HAVE_UNSETENV 1
-
-/* Define to 1 if you have the `utime' function. */
-#define HAVE_UTIME 1
-
-/* Define to 1 if you have the `utimes' function. */
-#define HAVE_UTIMES 1
-
-/* Define to 1 if you have the `uuid_create' function. */
-/* #undef HAVE_UUID_CREATE */
-
-/* Define to 1 if you have the `uuid_generate' function. */
-#define HAVE_UUID_GENERATE 1
-
-/* Define to 1 if you have the <uuid.h> header file. */
-/* #undef HAVE_UUID_H */
-
-/* Define to 1 if you have the <uuid/uuid.h> header file. */
-/* #undef HAVE_UUID_UUID_H */
-
-/* Define if C compiler supports VLA */
-#define HAVE_VLA 1
-
-/* Define to 1 if you have the `waitpid' function. */
-#define HAVE_WAITPID 1
-
-/* Define to 1 if you have the <windows.h> header file. */
-/* #undef HAVE_WINDOWS_H */
-
-/* Define to 1 if you have the <winsock2.h> header file. */
-/* #undef HAVE_WINSOCK2_H */
-
-/* Define to 1 if you have the `writev' function. */
-#define HAVE_WRITEV 1
-
-/* Define for z/OS pthread API nuances */
-/* #undef HAVE_ZOS_PTHREADS */
-
-/* Define if EAI_ error codes from getaddrinfo are negative */
-#define NEGATIVE_EAI 1
-
-/* Define to the address where bug reports for this package should be sent. */
-#define PACKAGE_BUGREPORT ""
-
-/* Define to the full name of this package. */
-#define PACKAGE_NAME ""
-
-/* Define to the full name and version of this package. */
-#define PACKAGE_STRING ""
-
-/* Define to the one symbol short name of this package. */
-#define PACKAGE_TARNAME ""
-
-/* Define to the version of this package. */
-#define PACKAGE_VERSION ""
-
-/* Define if POSIX semaphores affect threads within the process */
-/* #undef POSIXSEM_IS_GLOBAL */
-
-/* Define on PowerPC 405 where errata 77 applies */
-/* #undef PPC405_ERRATA */
-
-/* Define if pthread_attr_getdetachstate() has one arg */
-/* #undef PTHREAD_ATTR_GETDETACHSTATE_TAKES_ONE_ARG */
-
-/* Define if pthread_getspecific() has two args */
-/* #undef PTHREAD_GETSPECIFIC_TAKES_TWO_ARGS */
-
-/* Define if readdir is thread safe */
-/* #undef READDIR_IS_THREAD_SAFE */
-
-/* Define to 1 if the `setpgrp' function takes no argument. */
-#define SETPGRP_VOID 1
-
-/* */
-/* #undef SIGWAIT_TAKES_ONE_ARG */
-
-/* The size of `char', as computed by sizeof. */
-#define SIZEOF_CHAR 1
-
-/* The size of `int', as computed by sizeof. */
-#define SIZEOF_INT 4
-
-/* The size of `long', as computed by sizeof. */
-#define SIZEOF_LONG 8
-
-/* The size of `long long', as computed by sizeof. */
-#define SIZEOF_LONG_LONG 8
-
-/* The size of off_t */
-#define SIZEOF_OFF_T 8
-
-/* The size of pid_t */
-#define SIZEOF_PID_T 4
-
-/* The size of `short', as computed by sizeof. */
-#define SIZEOF_SHORT 2
-
-/* The size of size_t */
-#define SIZEOF_SIZE_T 8
-
-/* The size of ssize_t */
-#define SIZEOF_SSIZE_T 8
-
-/* The size of struct iovec */
-#define SIZEOF_STRUCT_IOVEC 16
-
-/* The size of `void*', as computed by sizeof. */
-#define SIZEOF_VOIDP 8
-
-/* If using the C implementation of alloca, define if you know the
- direction of stack growth for your system; otherwise it will be
- automatically deduced at runtime.
- STACK_DIRECTION > 0 => grows toward higher addresses
- STACK_DIRECTION < 0 => grows toward lower addresses
- STACK_DIRECTION = 0 => direction of growth unknown */
-/* #undef STACK_DIRECTION */
-
-/* Define to 1 if you have the ANSI C header files. */
-#define STDC_HEADERS 1
-
-/* Define if strerror returns int */
-/* #undef STRERROR_R_RC_INT */
-
-/* Define if SysV semaphores affect threads within the process */
-/* #undef SYSVSEM_IS_GLOBAL */
-
-/* Define if use of generic atomics is requested */
-/* #undef USE_ATOMICS_GENERIC */
-
-/* Define if BeOS Semaphores will be used */
-/* #undef USE_BEOSSEM */
-
-/* Define if SVR4-style fcntl() will be used */
-/* #undef USE_FCNTL_SERIALIZE */
-
-/* Define if 4.2BSD-style flock() will be used */
-/* #undef USE_FLOCK_SERIALIZE */
-
-/* Define if BeOS areas will be used */
-/* #undef USE_SHMEM_BEOS */
-
-/* Define if BeOS areas will be used */
-/* #undef USE_SHMEM_BEOS_ANON */
-
-/* Define if 4.4BSD-style mmap() via MAP_ANON will be used */
-#define USE_SHMEM_MMAP_ANON 1
-
-/* Define if mmap() via POSIX.1 shm_open() on temporary file will be used */
-/* #undef USE_SHMEM_MMAP_SHM */
-
-/* Define if Classical mmap() on temporary file will be used */
-/* #undef USE_SHMEM_MMAP_TMP */
-
-/* Define if SVR4-style mmap() on /dev/zero will be used */
-/* #undef USE_SHMEM_MMAP_ZERO */
-
-/* Define if OS/2 DosAllocSharedMem() will be used */
-/* #undef USE_SHMEM_OS2 */
-
-/* Define if OS/2 DosAllocSharedMem() will be used */
-/* #undef USE_SHMEM_OS2_ANON */
-
-/* Define if SysV IPC shmget() will be used */
-#define USE_SHMEM_SHMGET 1
-
-/* Define if SysV IPC shmget() will be used */
-/* #undef USE_SHMEM_SHMGET_ANON */
-
-/* Define if Windows shared memory will be used */
-/* #undef USE_SHMEM_WIN32 */
-
-/* Define if Windows CreateFileMapping() will be used */
-/* #undef USE_SHMEM_WIN32_ANON */
-
-/* Define if SysV IPC semget() will be used */
-#define USE_SYSVSEM_SERIALIZE 1
-
-/* Define if apr_wait_for_io_or_timeout() uses poll(2) */
-#define WAITIO_USES_POLL 1
-
-/* Define to 1 if your processor stores words with the most significant byte
- first (like Motorola and SPARC, unlike Intel and VAX). */
-/* #undef WORDS_BIGENDIAN */
-
-/* Define to 1 if on AIX 3.
- System headers sometimes define this.
- We just want to avoid a redefinition error message. */
-#ifndef _ALL_SOURCE
-/* # undef _ALL_SOURCE */
-#endif
-
-/* Enable GNU extensions on systems that have them. */
-#ifndef _GNU_SOURCE
-# define _GNU_SOURCE 1
-#endif
-
-/* Define to 1 if on MINIX. */
-/* #undef _MINIX */
-
-/* Define to 2 if the system does not provide POSIX.1 features except with
- this defined. */
-/* #undef _POSIX_1_SOURCE */
-
-/* Define to 1 if you need to in order for `stat' and other things to work. */
-/* #undef _POSIX_SOURCE */
-
-/* Enable extensions on Solaris. */
-#ifndef __EXTENSIONS__
-# define __EXTENSIONS__ 1
-#endif
-#ifndef _POSIX_PTHREAD_SEMANTICS
-# define _POSIX_PTHREAD_SEMANTICS 1
-#endif
-#ifndef _TANDEM_SOURCE
-# define _TANDEM_SOURCE 1
-#endif
-
-/* Define to empty if `const' does not conform to ANSI C. */
-/* #undef const */
-
-/* Define to `int' if <sys/types.h> doesn't define. */
-/* #undef gid_t */
-
-/* Define to `__inline__' or `__inline' if that's what the C compiler
- calls it, or to nothing if 'inline' is not supported under any name. */
-#ifndef __cplusplus
-/* #undef inline */
-#endif
-
-/* Define to `long int' if <sys/types.h> does not define. */
-/* #undef off_t */
-
-/* Define to `int' if <sys/types.h> does not define. */
-/* #undef pid_t */
-
-/* Define to `unsigned int' if <sys/types.h> does not define. */
-/* #undef size_t */
-
-/* Define to `int' if <sys/types.h> does not define. */
-/* #undef ssize_t */
-
-/* Define to `int' if <sys/types.h> doesn't define. */
-/* #undef uid_t */
-
-
-/* switch this on if we have a BeOS version below BONE */
-#if BEOS && !HAVE_BONE_VERSION
-#define BEOS_R5 1
-#else
-#define BEOS_BONE 1
-#endif
-
-/*
- * Include common private declarations.
- */
-#include "../apr_private_common.h"
-#endif /* APR_PRIVATE_H */
+++ /dev/null
-/* Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-
-#ifndef APR_H
-#define APR_H
-
-/* GENERATED FILE WARNING! DO NOT EDIT apr.h
- *
- * You must modify apr.h.in instead.
- *
- * And please, make an effort to stub apr.hw and apr.hnw in the process.
- */
-
-/**
- * @file apr.h
- * @brief APR Platform Definitions
- * @remark This is a generated header generated from include/apr.h.in by
- * ./configure, or copied from include/apr.hw or include/apr.hnw
- * for Win32 or Netware by those build environments, respectively.
- */
-
-/**
- * @defgroup APR Apache Portability Runtime library
- * @{
- */
-/**
- * @defgroup apr_platform Platform Definitions
- * @{
- * @warning
- * <strong><em>The actual values of macros and typedefs on this page<br>
- * are platform specific and should NOT be relied upon!</em></strong>
- */
-
-/* So that we can use inline on some critical functions, and use
- * GNUC attributes (such as to get -Wall warnings for printf-like
- * functions). Only do this in gcc 2.7 or later ... it may work
- * on earlier stuff, but why chance it.
- *
- * We've since discovered that the gcc shipped with NeXT systems
- * as "cc" is completely broken. It claims to be __GNUC__ and so
- * on, but it doesn't implement half of the things that __GNUC__
- * means. In particular it's missing inline and the __attribute__
- * stuff. So we hack around it. PR#1613. -djg
- */
-#if !defined(__GNUC__) || __GNUC__ < 2 || \
- (__GNUC__ == 2 && __GNUC_MINOR__ < 7) ||\
- defined(NEXT)
-#ifndef __attribute__
-#define __attribute__(__x)
-#endif
-#define APR_INLINE
-#define APR_HAS_INLINE 0
-#else
-#define APR_INLINE __inline__
-#define APR_HAS_INLINE 1
-#endif
-
-#define APR_HAVE_ARPA_INET_H 1
-#define APR_HAVE_CONIO_H 0
-#define APR_HAVE_CRYPT_H 0
-#define APR_HAVE_CTYPE_H 1
-#define APR_HAVE_DIRENT_H 1
-#define APR_HAVE_ERRNO_H 1
-#define APR_HAVE_FCNTL_H 1
-#define APR_HAVE_IO_H 0
-#define APR_HAVE_LIMITS_H 1
-#define APR_HAVE_NETDB_H 1
-#define APR_HAVE_NETINET_IN_H 1
-#define APR_HAVE_NETINET_SCTP_H 0
-#define APR_HAVE_NETINET_SCTP_UIO_H 0
-#define APR_HAVE_NETINET_TCP_H 1
-#define APR_HAVE_PTHREAD_H 1
-#define APR_HAVE_SEMAPHORE_H 1
-#define APR_HAVE_SIGNAL_H 1
-#define APR_HAVE_STDARG_H 1
-#define APR_HAVE_STDINT_H 1
-#define APR_HAVE_STDIO_H 1
-#define APR_HAVE_STDLIB_H 1
-#define APR_HAVE_STRING_H 1
-#define APR_HAVE_STRINGS_H 1
-#define APR_HAVE_SYS_IOCTL_H 1
-#define APR_HAVE_SYS_SENDFILE_H 0
-#define APR_HAVE_SYS_SIGNAL_H 1
-#define APR_HAVE_SYS_SOCKET_H 1
-#define APR_HAVE_SYS_SOCKIO_H 1
-#define APR_HAVE_SYS_SYSLIMITS_H 1
-#define APR_HAVE_SYS_TIME_H 1
-#define APR_HAVE_SYS_TYPES_H 1
-#define APR_HAVE_SYS_UIO_H 1
-#define APR_HAVE_SYS_UN_H 1
-#define APR_HAVE_SYS_WAIT_H 1
-#define APR_HAVE_TIME_H 1
-#define APR_HAVE_UNISTD_H 1
-#define APR_HAVE_WINDOWS_H 0
-#define APR_HAVE_WINSOCK2_H 0
-
-/** @} */
-/** @} */
-
-/* We don't include our conditional headers within the doxyblocks
- * or the extern "C" namespace
- */
-
-#if APR_HAVE_WINDOWS_H
-#include <windows.h>
-#endif
-
-#if APR_HAVE_WINSOCK2_H
-#include <winsock2.h>
-#endif
-
-#if APR_HAVE_SYS_TYPES_H
-#include <sys/types.h>
-#endif
-
-#if APR_HAVE_SYS_SOCKET_H
-#include <sys/socket.h>
-#endif
-
-#if defined(__cplusplus) && !defined(__STDC_CONSTANT_MACROS)
-/* C99 7.18.4 requires that stdint.h only exposes INT64_C
- * and UINT64_C for C++ implementations if this is defined: */
-#define __STDC_CONSTANT_MACROS
-#endif
-
-#if APR_HAVE_STDINT_H
-#include <stdint.h>
-#endif
-
-#if APR_HAVE_SYS_WAIT_H
-#include <sys/wait.h>
-#endif
-
-#ifdef OS2
-#define INCL_DOS
-#define INCL_DOSERRORS
-#include <os2.h>
-#endif
-
-/* header files for PATH_MAX, _POSIX_PATH_MAX */
-#if APR_HAVE_LIMITS_H
-#include <limits.h>
-#else
-#if APR_HAVE_SYS_SYSLIMITS_H
-#include <sys/syslimits.h>
-#endif
-#endif
-
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/**
- * @addtogroup apr_platform
- * @ingroup APR
- * @{
- */
-
-#define APR_HAVE_SHMEM_MMAP_TMP 1
-#define APR_HAVE_SHMEM_MMAP_SHM 1
-#define APR_HAVE_SHMEM_MMAP_ZERO 0
-#define APR_HAVE_SHMEM_SHMGET_ANON 1
-#define APR_HAVE_SHMEM_SHMGET 1
-#define APR_HAVE_SHMEM_MMAP_ANON 1
-#define APR_HAVE_SHMEM_BEOS 0
-
-#define APR_USE_SHMEM_MMAP_TMP 0
-#define APR_USE_SHMEM_MMAP_SHM 0
-#define APR_USE_SHMEM_MMAP_ZERO 0
-#define APR_USE_SHMEM_SHMGET_ANON 0
-#define APR_USE_SHMEM_SHMGET 1
-#define APR_USE_SHMEM_MMAP_ANON 1
-#define APR_USE_SHMEM_BEOS 0
-
-#define APR_USE_FLOCK_SERIALIZE 0
-#define APR_USE_SYSVSEM_SERIALIZE 1
-#define APR_USE_POSIXSEM_SERIALIZE 0
-#define APR_USE_FCNTL_SERIALIZE 0
-#define APR_USE_PROC_PTHREAD_SERIALIZE 0
-#define APR_USE_PTHREAD_SERIALIZE 1
-
-#define APR_HAS_FLOCK_SERIALIZE 1
-#define APR_HAS_SYSVSEM_SERIALIZE 1
-#define APR_HAS_POSIXSEM_SERIALIZE 1
-#define APR_HAS_FCNTL_SERIALIZE 1
-#define APR_HAS_PROC_PTHREAD_SERIALIZE 0
-
-#define APR_PROCESS_LOCK_IS_GLOBAL 0
-
-#define APR_HAVE_CORKABLE_TCP 1
-#define APR_HAVE_GETRLIMIT 1
-#define APR_HAVE_IN_ADDR 1
-#define APR_HAVE_INET_ADDR 1
-#define APR_HAVE_INET_NETWORK 1
-#define APR_HAVE_IPV6 1
-#define APR_HAVE_MEMMOVE 1
-#define APR_HAVE_SETRLIMIT 1
-#define APR_HAVE_SIGACTION 1
-#define APR_HAVE_SIGSUSPEND 1
-#define APR_HAVE_SIGWAIT 1
-#define APR_HAVE_SA_STORAGE 1
-#define APR_HAVE_STRCASECMP 1
-#define APR_HAVE_STRDUP 1
-#define APR_HAVE_STRICMP 0
-#define APR_HAVE_STRNCASECMP 1
-#define APR_HAVE_STRNICMP 0
-#define APR_HAVE_STRSTR 1
-#define APR_HAVE_MEMCHR 1
-#define APR_HAVE_STRUCT_RLIMIT 1
-#define APR_HAVE_UNION_SEMUN 1
-#define APR_HAVE_SCTP 0
-#define APR_HAVE_IOVEC 1
-
-/* APR Feature Macros */
-#define APR_HAS_SHARED_MEMORY 1
-#define APR_HAS_THREADS 1
-#define APR_HAS_SENDFILE 1
-#define APR_HAS_MMAP 1
-#define APR_HAS_FORK 1
-#define APR_HAS_RANDOM 1
-#define APR_HAS_OTHER_CHILD 1
-#define APR_HAS_DSO 1
-#define APR_HAS_SO_ACCEPTFILTER 0
-#define APR_HAS_UNICODE_FS 0
-#define APR_HAS_PROC_INVOKED 0
-#define APR_HAS_USER 1
-#define APR_HAS_LARGE_FILES 1
-#define APR_HAS_XTHREAD_FILES 0
-#define APR_HAS_OS_UUID 1
-
-#define APR_PROCATTR_USER_SET_REQUIRES_PASSWORD 0
-
-/* APR sets APR_FILES_AS_SOCKETS to 1 on systems where it is possible
- * to poll on files/pipes.
- */
-#define APR_FILES_AS_SOCKETS 1
-
-/* This macro indicates whether or not EBCDIC is the native character set.
- */
-#define APR_CHARSET_EBCDIC 0
-
-/* If we have a TCP implementation that can be "corked", what flag
- * do we use?
- */
-#define APR_TCP_NOPUSH_FLAG TCP_NOPUSH
-
-/* Is the TCP_NODELAY socket option inherited from listening sockets?
-*/
-#define APR_TCP_NODELAY_INHERITED 1
-
-/* Is the O_NONBLOCK flag inherited from listening sockets?
-*/
-#define APR_O_NONBLOCK_INHERITED 1
-
-/* Typedefs that APR needs. */
-
-typedef unsigned char apr_byte_t;
-
-typedef short apr_int16_t;
-typedef unsigned short apr_uint16_t;
-
-typedef int apr_int32_t;
-typedef unsigned int apr_uint32_t;
-
-typedef long long apr_int64_t;
-typedef unsigned long long apr_uint64_t;
-
-typedef size_t apr_size_t;
-typedef ssize_t apr_ssize_t;
-typedef off_t apr_off_t;
-typedef socklen_t apr_socklen_t;
-typedef ino_t apr_ino_t;
-
-#define APR_SIZEOF_VOIDP 4
-
-#if APR_SIZEOF_VOIDP == 8
-typedef apr_uint64_t apr_uintptr_t;
-#else
-typedef apr_uint32_t apr_uintptr_t;
-#endif
-
-/* Are we big endian? */
-#define APR_IS_BIGENDIAN 0
-
-/* Mechanisms to properly type numeric literals */
-#define APR_INT64_C(val) INT64_C(val)
-#define APR_UINT64_C(val) UINT64_C(val)
-
-#ifdef INT16_MIN
-#define APR_INT16_MIN INT16_MIN
-#else
-#define APR_INT16_MIN (-0x7fff - 1)
-#endif
-
-#ifdef INT16_MAX
-#define APR_INT16_MAX INT16_MAX
-#else
-#define APR_INT16_MAX (0x7fff)
-#endif
-
-#ifdef UINT16_MAX
-#define APR_UINT16_MAX UINT16_MAX
-#else
-#define APR_UINT16_MAX (0xffff)
-#endif
-
-#ifdef INT32_MIN
-#define APR_INT32_MIN INT32_MIN
-#else
-#define APR_INT32_MIN (-0x7fffffff - 1)
-#endif
-
-#ifdef INT32_MAX
-#define APR_INT32_MAX INT32_MAX
-#else
-#define APR_INT32_MAX 0x7fffffff
-#endif
-
-#ifdef UINT32_MAX
-#define APR_UINT32_MAX UINT32_MAX
-#else
-#define APR_UINT32_MAX (0xffffffffU)
-#endif
-
-#ifdef INT64_MIN
-#define APR_INT64_MIN INT64_MIN
-#else
-#define APR_INT64_MIN (APR_INT64_C(-0x7fffffffffffffff) - 1)
-#endif
-
-#ifdef INT64_MAX
-#define APR_INT64_MAX INT64_MAX
-#else
-#define APR_INT64_MAX APR_INT64_C(0x7fffffffffffffff)
-#endif
-
-#ifdef UINT64_MAX
-#define APR_UINT64_MAX UINT64_MAX
-#else
-#define APR_UINT64_MAX APR_UINT64_C(0xffffffffffffffff)
-#endif
-
-#define APR_SIZE_MAX (~((apr_size_t)0))
-
-
-/* Definitions that APR programs need to work properly. */
-
-/**
- * APR public API wrap for C++ compilers.
- */
-#ifdef __cplusplus
-#define APR_BEGIN_DECLS extern "C" {
-#define APR_END_DECLS }
-#else
-#define APR_BEGIN_DECLS
-#define APR_END_DECLS
-#endif
-
-/**
- * Thread callbacks from APR functions must be declared with APR_THREAD_FUNC,
- * so that they follow the platform's calling convention.
- * <PRE>
- *
- * void* APR_THREAD_FUNC my_thread_entry_fn(apr_thread_t *thd, void *data);
- *
- * </PRE>
- */
-#define APR_THREAD_FUNC
-
-/**
- * The public APR functions are declared with APR_DECLARE(), so they may
- * use the most appropriate calling convention. Public APR functions with
- * variable arguments must use APR_DECLARE_NONSTD().
- *
- * @remark Both the declaration and implementations must use the same macro.
- *
- * <PRE>
- * APR_DECLARE(rettype) apr_func(args)
- * </PRE>
- * @see APR_DECLARE_NONSTD @see APR_DECLARE_DATA
- * @remark Note that when APR compiles the library itself, it passes the
- * symbol -DAPR_DECLARE_EXPORT to the compiler on some platforms (e.g. Win32)
- * to export public symbols from the dynamic library build.\n
- * The user must define the APR_DECLARE_STATIC when compiling to target
- * the static APR library on some platforms (e.g. Win32.) The public symbols
- * are neither exported nor imported when APR_DECLARE_STATIC is defined.\n
- * By default, compiling an application and including the APR public
- * headers, without defining APR_DECLARE_STATIC, will prepare the code to be
- * linked to the dynamic library.
- */
-#define APR_DECLARE(type) type
-
-/**
- * The public APR functions using variable arguments are declared with
- * APR_DECLARE_NONSTD(), as they must follow the C language calling convention.
- * @see APR_DECLARE @see APR_DECLARE_DATA
- * @remark Both the declaration and implementations must use the same macro.
- * <PRE>
- *
- * APR_DECLARE_NONSTD(rettype) apr_func(args, ...);
- *
- * </PRE>
- */
-#define APR_DECLARE_NONSTD(type) type
-
-/**
- * The public APR variables are declared with AP_MODULE_DECLARE_DATA.
- * This assures the appropriate indirection is invoked at compile time.
- * @see APR_DECLARE @see APR_DECLARE_NONSTD
- * @remark Note that the declaration and implementations use different forms,
- * but both must include the macro.
- *
- * <PRE>
- *
- * extern APR_DECLARE_DATA type apr_variable;\n
- * APR_DECLARE_DATA type apr_variable = value;
- *
- * </PRE>
- */
-#define APR_DECLARE_DATA
-
-/* Define APR_SSIZE_T_FMT.
- * If ssize_t is an integer we define it to be "d",
- * if ssize_t is a long int we define it to be "ld",
- * if ssize_t is neither we declare an error here.
- * I looked for a better way to define this here, but couldn't find one, so
- * to find the logic for this definition search for "ssize_t_fmt" in
- * configure.in.
- */
-#define APR_SSIZE_T_FMT "ld"
-
-/* And APR_SIZE_T_FMT */
-#define APR_SIZE_T_FMT "lu"
-
-/* And APR_OFF_T_FMT */
-#define APR_OFF_T_FMT APR_INT64_T_FMT
-
-/* And APR_PID_T_FMT */
-#define APR_PID_T_FMT "d"
-
-/* And APR_INT64_T_FMT */
-#define APR_INT64_T_FMT "lld"
-
-/* And APR_UINT64_T_FMT */
-#define APR_UINT64_T_FMT "llu"
-
-/* And APR_UINT64_T_HEX_FMT */
-#define APR_UINT64_T_HEX_FMT "llx"
-
-/* Does the proc mutex lock threads too */
-#define APR_PROC_MUTEX_IS_GLOBAL 0
-
-/* Local machine definition for console and log output. */
-#define APR_EOL_STR "\n"
-
-#if APR_HAVE_SYS_WAIT_H
-#ifdef WEXITSTATUS
-#define apr_wait_t int
-#else
-#define apr_wait_t union wait
-#define WEXITSTATUS(status) (int)((status).w_retcode)
-#define WTERMSIG(status) (int)((status).w_termsig)
-#endif /* !WEXITSTATUS */
-#elif defined(__MINGW32__)
-typedef int apr_wait_t;
-#endif /* HAVE_SYS_WAIT_H */
-
-#if defined(PATH_MAX)
-#define APR_PATH_MAX PATH_MAX
-#elif defined(_POSIX_PATH_MAX)
-#define APR_PATH_MAX _POSIX_PATH_MAX
-#else
-#error no decision has been made on APR_PATH_MAX for your platform
-#endif
-
-#define APR_DSOPATH "DYLD_LIBRARY_PATH"
-
-/** @} */
-
-/* Definitions that only Win32 programs need to compile properly. */
-
-/* XXX These simply don't belong here, perhaps in apr_portable.h
- * based on some APR_HAVE_PID/GID/UID?
- */
-#ifdef __MINGW32__
-#ifndef __GNUC__
-typedef int pid_t;
-#endif
-typedef int uid_t;
-typedef int gid_t;
-#endif
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* APR_H */
+++ /dev/null
-/* include/arch/unix/apr_private.h. Generated from apr_private.h.in by configure. */
-/* include/arch/unix/apr_private.h.in. Generated from configure.in by autoheader. */
-
-
-#ifndef APR_PRIVATE_H
-#define APR_PRIVATE_H
-
-
-/* Define if building universal (internal helper macro) */
-/* #undef AC_APPLE_UNIVERSAL_BUILD */
-
-/* Define as function which can be used for conversion of strings to
- apr_int64_t */
-#define APR_INT64_STRFN strtoll
-
-/* Define as function used for conversion of strings to apr_off_t */
-#define APR_OFF_T_STRFN strtoll
-
-/* Define to one of `_getb67', `GETB67', `getb67' for Cray-2 and Cray-YMP
- systems. This function is required for `alloca.c' support on those systems.
- */
-/* #undef CRAY_STACKSEG_END */
-
-/* Define to 1 if using `alloca.c'. */
-/* #undef C_ALLOCA */
-
-/* Define to path of random device */
-#define DEV_RANDOM "/dev/urandom"
-
-/* Define if struct dirent has an inode member */
-#define DIRENT_INODE d_fileno
-
-/* Define if struct dirent has a d_type member */
-#define DIRENT_TYPE d_type
-
-/* Define if DSO support uses dlfcn.h */
-#define DSO_USE_DLFCN 1
-
-/* Define if DSO support uses dyld.h */
-/* #undef DSO_USE_DYLD */
-
-/* Define if DSO support uses shl_load */
-/* #undef DSO_USE_SHL */
-
-/* Define to list of paths to EGD sockets */
-/* #undef EGD_DEFAULT_SOCKET */
-
-/* Define if fcntl locks affect threads within the process */
-/* #undef FCNTL_IS_GLOBAL */
-
-/* Define if fcntl returns EACCES when F_SETLK is already held */
-/* #undef FCNTL_TRYACQUIRE_EACCES */
-
-/* Define if flock locks affect threads within the process */
-/* #undef FLOCK_IS_GLOBAL */
-
-/* Define if gethostbyaddr is thread safe */
-/* #undef GETHOSTBYADDR_IS_THREAD_SAFE */
-
-/* Define if gethostbyname is thread safe */
-/* #undef GETHOSTBYNAME_IS_THREAD_SAFE */
-
-/* Define if gethostbyname_r has the glibc style */
-/* #undef GETHOSTBYNAME_R_GLIBC2 */
-
-/* Define if gethostbyname_r has the hostent_data for the third argument */
-/* #undef GETHOSTBYNAME_R_HOSTENT_DATA */
-
-/* Define if getservbyname is thread safe */
-/* #undef GETSERVBYNAME_IS_THREAD_SAFE */
-
-/* Define if getservbyname_r has the glibc style */
-/* #undef GETSERVBYNAME_R_GLIBC2 */
-
-/* Define if getservbyname_r has the OSF/1 style */
-/* #undef GETSERVBYNAME_R_OSF1 */
-
-/* Define if getservbyname_r has the Solaris style */
-/* #undef GETSERVBYNAME_R_SOLARIS */
-
-/* Define if accept4 function is supported */
-/* #undef HAVE_ACCEPT4 */
-
-/* Define to 1 if you have `alloca', as a function or macro. */
-#define HAVE_ALLOCA 1
-
-/* Define to 1 if you have <alloca.h> and it should be used (not on Ultrix).
- */
-#define HAVE_ALLOCA_H 1
-
-/* Define to 1 if you have the <arpa/inet.h> header file. */
-#define HAVE_ARPA_INET_H 1
-
-/* Define if compiler provides atomic builtins */
-/* #undef HAVE_ATOMIC_BUILTINS */
-
-/* Define if BONE_VERSION is defined in sys/socket.h */
-/* #undef HAVE_BONE_VERSION */
-
-/* Define to 1 if you have the <ByteOrder.h> header file. */
-/* #undef HAVE_BYTEORDER_H */
-
-/* Define to 1 if you have the `calloc' function. */
-#define HAVE_CALLOC 1
-
-/* Define to 1 if you have the <conio.h> header file. */
-/* #undef HAVE_CONIO_H */
-
-/* Define to 1 if you have the `create_area' function. */
-/* #undef HAVE_CREATE_AREA */
-
-/* Define to 1 if you have the `create_sem' function. */
-/* #undef HAVE_CREATE_SEM */
-
-/* Define to 1 if you have the <crypt.h> header file. */
-/* #undef HAVE_CRYPT_H */
-
-/* Define to 1 if you have the <ctype.h> header file. */
-#define HAVE_CTYPE_H 1
-
-/* Define to 1 if you have the declaration of `sys_siglist', and to 0 if you
- don't. */
-#define HAVE_DECL_SYS_SIGLIST 1
-
-/* Define to 1 if you have the <dirent.h> header file. */
-#define HAVE_DIRENT_H 1
-
-/* Define to 1 if you have the <dir.h> header file. */
-/* #undef HAVE_DIR_H */
-
-/* Define to 1 if you have the <dlfcn.h> header file. */
-#define HAVE_DLFCN_H 1
-
-/* Define to 1 if you have the <dl.h> header file. */
-/* #undef HAVE_DL_H */
-
-/* Define if dup3 function is supported */
-/* #undef HAVE_DUP3 */
-
-/* Define if EGD is supported */
-/* #undef HAVE_EGD */
-
-/* Define if the epoll interface is supported */
-/* #undef HAVE_EPOLL */
-
-/* Define if epoll_create1 function is supported */
-/* #undef HAVE_EPOLL_CREATE1 */
-
-/* Define to 1 if you have the <errno.h> header file. */
-#define HAVE_ERRNO_H 1
-
-/* Define to 1 if you have the <fcntl.h> header file. */
-#define HAVE_FCNTL_H 1
-
-/* Define to 1 if you have the `fdatasync' function. */
-/* #undef HAVE_FDATASYNC */
-
-/* Define to 1 if you have the `flock' function. */
-#define HAVE_FLOCK 1
-
-/* Define to 1 if you have the `fork' function. */
-#define HAVE_FORK 1
-
-/* Define if F_SETLK is defined in fcntl.h */
-#define HAVE_F_SETLK 1
-
-/* Define if getaddrinfo accepts the AI_ADDRCONFIG flag */
-#define HAVE_GAI_ADDRCONFIG 1
-
-/* Define to 1 if you have the `gai_strerror' function. */
-#define HAVE_GAI_STRERROR 1
-
-/* Define if getaddrinfo exists and works well enough for APR */
-#define HAVE_GETADDRINFO 1
-
-/* Define to 1 if you have the `getenv' function. */
-#define HAVE_GETENV 1
-
-/* Define to 1 if you have the `getgrgid_r' function. */
-#define HAVE_GETGRGID_R 1
-
-/* Define to 1 if you have the `getgrnam_r' function. */
-#define HAVE_GETGRNAM_R 1
-
-/* Define to 1 if you have the `gethostbyaddr_r' function. */
-/* #undef HAVE_GETHOSTBYADDR_R */
-
-/* Define to 1 if you have the `gethostbyname_r' function. */
-/* #undef HAVE_GETHOSTBYNAME_R */
-
-/* Define to 1 if you have the `getifaddrs' function. */
-#define HAVE_GETIFADDRS 1
-
-/* Define if getnameinfo exists */
-#define HAVE_GETNAMEINFO 1
-
-/* Define to 1 if you have the `getpass' function. */
-#define HAVE_GETPASS 1
-
-/* Define to 1 if you have the `getpassphrase' function. */
-/* #undef HAVE_GETPASSPHRASE */
-
-/* Define to 1 if you have the `getpwnam_r' function. */
-#define HAVE_GETPWNAM_R 1
-
-/* Define to 1 if you have the `getpwuid_r' function. */
-#define HAVE_GETPWUID_R 1
-
-/* Define to 1 if you have the `getrlimit' function. */
-#define HAVE_GETRLIMIT 1
-
-/* Define to 1 if you have the `getservbyname_r' function. */
-/* #undef HAVE_GETSERVBYNAME_R */
-
-/* Define to 1 if you have the `gmtime_r' function. */
-#define HAVE_GMTIME_R 1
-
-/* Define to 1 if you have the <grp.h> header file. */
-#define HAVE_GRP_H 1
-
-/* Define if hstrerror is present */
-/* #undef HAVE_HSTRERROR */
-
-/* Define to 1 if you have the <inttypes.h> header file. */
-#define HAVE_INTTYPES_H 1
-
-/* Define to 1 if you have the <io.h> header file. */
-/* #undef HAVE_IO_H */
-
-/* Define to 1 if you have the `isinf' function. */
-#define HAVE_ISINF 1
-
-/* Define to 1 if you have the `isnan' function. */
-#define HAVE_ISNAN 1
-
-/* Define to 1 if you have the <kernel/OS.h> header file. */
-/* #undef HAVE_KERNEL_OS_H */
-
-/* Define to 1 if you have the `kqueue' function. */
-/* #undef HAVE_KQUEUE */
-
-/* Define to 1 if you have the <langinfo.h> header file. */
-#define HAVE_LANGINFO_H 1
-
-/* Enable if this library is available */
-/* #undef HAVE_LIBADVAPI32 */
-
-/* Define to 1 if you have the `bsd' library (-lbsd). */
-/* #undef HAVE_LIBBSD */
-
-/* Enable if this library is available */
-/* #undef HAVE_LIBKERNEL32 */
-
-/* Define to 1 if you have the `msvcrt' library (-lmsvcrt). */
-/* #undef HAVE_LIBMSVCRT */
-
-/* Enable if this library is available */
-/* #undef HAVE_LIBRPCRT4 */
-
-/* Define to 1 if you have the `sendfile' library (-lsendfile). */
-/* #undef HAVE_LIBSENDFILE */
-
-/* Enable if this library is available */
-/* #undef HAVE_LIBSHELL32 */
-
-/* Define to 1 if you have the `truerand' library (-ltruerand). */
-/* #undef HAVE_LIBTRUERAND */
-
-/* Enable if this library is available */
-/* #undef HAVE_LIBWS2_32 */
-
-/* Define to 1 if you have the <limits.h> header file. */
-#define HAVE_LIMITS_H 1
-
-/* Define to 1 if you have the `localtime_r' function. */
-#define HAVE_LOCALTIME_R 1
-
-/* Define if LOCK_EX is defined in sys/file.h */
-#define HAVE_LOCK_EX 1
-
-/* Define to 1 if you have the <mach-o/dyld.h> header file. */
-#define HAVE_MACH_O_DYLD_H 1
-
-/* Define to 1 if you have the <malloc.h> header file. */
-/* #undef HAVE_MALLOC_H */
-
-/* Define if MAP_ANON is defined in sys/mman.h */
-#define HAVE_MAP_ANON 1
-
-/* Define to 1 if you have the `memchr' function. */
-#define HAVE_MEMCHR 1
-
-/* Define to 1 if you have the `memmove' function. */
-#define HAVE_MEMMOVE 1
-
-/* Define to 1 if you have the <memory.h> header file. */
-#define HAVE_MEMORY_H 1
-
-/* Define to 1 if you have the `mkstemp' function. */
-#define HAVE_MKSTEMP 1
-
-/* Define to 1 if you have the `mkstemp64' function. */
-/* #undef HAVE_MKSTEMP64 */
-
-/* Define to 1 if you have the `mmap' function. */
-#define HAVE_MMAP 1
-
-/* Define to 1 if you have the `mmap64' function. */
-/* #undef HAVE_MMAP64 */
-
-/* Define to 1 if you have the `munmap' function. */
-#define HAVE_MUNMAP 1
-
-/* Define to 1 if you have the <netdb.h> header file. */
-#define HAVE_NETDB_H 1
-
-/* Define to 1 if you have the <netinet/in.h> header file. */
-#define HAVE_NETINET_IN_H 1
-
-/* Define to 1 if you have the <netinet/sctp.h> header file. */
-/* #undef HAVE_NETINET_SCTP_H */
-
-/* Define to 1 if you have the <netinet/sctp_uio.h> header file. */
-/* #undef HAVE_NETINET_SCTP_UIO_H */
-
-/* Defined if netinet/tcp.h is present */
-#define HAVE_NETINET_TCP_H 1
-
-/* Define to 1 if you have the <net/errno.h> header file. */
-/* #undef HAVE_NET_ERRNO_H */
-
-/* Define to 1 if you have the `nl_langinfo' function. */
-#define HAVE_NL_LANGINFO 1
-
-/* Define to 1 if you have the <os2.h> header file. */
-/* #undef HAVE_OS2_H */
-
-/* Define to 1 if you have the <osreldate.h> header file. */
-/* #undef HAVE_OSRELDATE_H */
-
-/* Define to 1 if you have the <OS.h> header file. */
-/* #undef HAVE_OS_H */
-
-/* Define to 1 if you have the `poll' function. */
-/* #undef HAVE_POLL */
-
-/* Define if POLLIN is defined */
-#define HAVE_POLLIN 1
-
-/* Define to 1 if you have the <poll.h> header file. */
-#define HAVE_POLL_H 1
-
-/* Define to 1 if you have the `port_create' function. */
-/* #undef HAVE_PORT_CREATE */
-
-/* Define to 1 if you have the <process.h> header file. */
-/* #undef HAVE_PROCESS_H */
-
-/* Define to 1 if you have the `pthread_attr_setguardsize' function. */
-#define HAVE_PTHREAD_ATTR_SETGUARDSIZE 1
-
-/* Define to 1 if you have the <pthread.h> header file. */
-#define HAVE_PTHREAD_H 1
-
-/* Define to 1 if you have the `pthread_key_delete' function. */
-#define HAVE_PTHREAD_KEY_DELETE 1
-
-/* Define to 1 if you have the `pthread_mutexattr_setpshared' function. */
-#define HAVE_PTHREAD_MUTEXATTR_SETPSHARED 1
-
-/* Define if recursive pthread mutexes are available */
-#define HAVE_PTHREAD_MUTEX_RECURSIVE 1
-
-/* Define if cross-process robust mutexes are available */
-/* #undef HAVE_PTHREAD_MUTEX_ROBUST */
-
-/* Define if PTHREAD_PROCESS_SHARED is defined in pthread.h */
-#define HAVE_PTHREAD_PROCESS_SHARED 1
-
-/* Define if pthread rwlocks are available */
-#define HAVE_PTHREAD_RWLOCKS 1
-
-/* Define to 1 if you have the `pthread_rwlock_init' function. */
-#define HAVE_PTHREAD_RWLOCK_INIT 1
-
-/* Define to 1 if you have the `pthread_yield' function. */
-/* #undef HAVE_PTHREAD_YIELD */
-
-/* Define to 1 if you have the `putenv' function. */
-#define HAVE_PUTENV 1
-
-/* Define to 1 if you have the <pwd.h> header file. */
-#define HAVE_PWD_H 1
-
-/* Define to 1 if you have the `readdir64_r' function. */
-/* #undef HAVE_READDIR64_R */
-
-/* Define to 1 if you have the <sched.h> header file. */
-#define HAVE_SCHED_H 1
-
-/* Define to 1 if you have the `sched_yield' function. */
-#define HAVE_SCHED_YIELD 1
-
-/* Define to 1 if you have the <semaphore.h> header file. */
-#define HAVE_SEMAPHORE_H 1
-
-/* Define to 1 if you have the `semctl' function. */
-#define HAVE_SEMCTL 1
-
-/* Define to 1 if you have the `semget' function. */
-#define HAVE_SEMGET 1
-
-/* Define to 1 if you have the `sem_close' function. */
-#define HAVE_SEM_CLOSE 1
-
-/* Define to 1 if you have the `sem_post' function. */
-#define HAVE_SEM_POST 1
-
-/* Define if SEM_UNDO is defined in sys/sem.h */
-#define HAVE_SEM_UNDO 1
-
-/* Define to 1 if you have the `sem_unlink' function. */
-#define HAVE_SEM_UNLINK 1
-
-/* Define to 1 if you have the `sem_wait' function. */
-#define HAVE_SEM_WAIT 1
-
-/* Define to 1 if you have the `sendfile' function. */
-#define HAVE_SENDFILE 1
-
-/* Define to 1 if you have the `sendfile64' function. */
-/* #undef HAVE_SENDFILE64 */
-
-/* Define to 1 if you have the `sendfilev' function. */
-/* #undef HAVE_SENDFILEV */
-
-/* Define to 1 if you have the `sendfilev64' function. */
-/* #undef HAVE_SENDFILEV64 */
-
-/* Define to 1 if you have the `send_file' function. */
-/* #undef HAVE_SEND_FILE */
-
-/* Define to 1 if you have the `setenv' function. */
-#define HAVE_SETENV 1
-
-/* Define to 1 if you have the `setrlimit' function. */
-#define HAVE_SETRLIMIT 1
-
-/* Define to 1 if you have the `setsid' function. */
-#define HAVE_SETSID 1
-
-/* Define to 1 if you have the `set_h_errno' function. */
-/* #undef HAVE_SET_H_ERRNO */
-
-/* Define to 1 if you have the `shmat' function. */
-#define HAVE_SHMAT 1
-
-/* Define to 1 if you have the `shmctl' function. */
-#define HAVE_SHMCTL 1
-
-/* Define to 1 if you have the `shmdt' function. */
-#define HAVE_SHMDT 1
-
-/* Define to 1 if you have the `shmget' function. */
-#define HAVE_SHMGET 1
-
-/* Define to 1 if you have the `shm_open' function. */
-#define HAVE_SHM_OPEN 1
-
-/* Define to 1 if you have the `shm_unlink' function. */
-#define HAVE_SHM_UNLINK 1
-
-/* Define to 1 if you have the `sigaction' function. */
-#define HAVE_SIGACTION 1
-
-/* Define to 1 if you have the <signal.h> header file. */
-#define HAVE_SIGNAL_H 1
-
-/* Define to 1 if you have the `sigsuspend' function. */
-#define HAVE_SIGSUSPEND 1
-
-/* Define to 1 if you have the `sigwait' function. */
-#define HAVE_SIGWAIT 1
-
-/* Whether you have socklen_t */
-#define HAVE_SOCKLEN_T 1
-
-/* Define if the SOCK_CLOEXEC flag is supported */
-/* #undef HAVE_SOCK_CLOEXEC */
-
-/* Define if SO_ACCEPTFILTER is defined in sys/socket.h */
-/* #undef HAVE_SO_ACCEPTFILTER */
-
-/* Define to 1 if you have the <stdarg.h> header file. */
-#define HAVE_STDARG_H 1
-
-/* Define to 1 if you have the <stddef.h> header file. */
-#define HAVE_STDDEF_H 1
-
-/* Define to 1 if you have the <stdint.h> header file. */
-#define HAVE_STDINT_H 1
-
-/* Define to 1 if you have the <stdio.h> header file. */
-#define HAVE_STDIO_H 1
-
-/* Define to 1 if you have the <stdlib.h> header file. */
-#define HAVE_STDLIB_H 1
-
-/* Define to 1 if you have the `strcasecmp' function. */
-#define HAVE_STRCASECMP 1
-
-/* Define to 1 if you have the `strdup' function. */
-#define HAVE_STRDUP 1
-
-/* Define to 1 if you have the `strerror_r' function. */
-#define HAVE_STRERROR_R 1
-
-/* Define to 1 if you have the `stricmp' function. */
-/* #undef HAVE_STRICMP */
-
-/* Define to 1 if you have the <strings.h> header file. */
-#define HAVE_STRINGS_H 1
-
-/* Define to 1 if you have the <string.h> header file. */
-#define HAVE_STRING_H 1
-
-/* Define to 1 if you have the `strncasecmp' function. */
-#define HAVE_STRNCASECMP 1
-
-/* Define to 1 if you have the `strnicmp' function. */
-/* #undef HAVE_STRNICMP */
-
-/* Define to 1 if you have the `strstr' function. */
-#define HAVE_STRSTR 1
-
-/* Define if struct impreq was found */
-#define HAVE_STRUCT_IPMREQ 1
-
-/* Define to 1 if `st_atimensec' is a member of `struct stat'. */
-/* #undef HAVE_STRUCT_STAT_ST_ATIMENSEC */
-
-/* Define to 1 if `st_atime_n' is a member of `struct stat'. */
-/* #undef HAVE_STRUCT_STAT_ST_ATIME_N */
-
-/* Define to 1 if `st_atim.tv_nsec' is a member of `struct stat'. */
-/* #undef HAVE_STRUCT_STAT_ST_ATIM_TV_NSEC */
-
-/* Define to 1 if `st_blocks' is a member of `struct stat'. */
-#define HAVE_STRUCT_STAT_ST_BLOCKS 1
-
-/* Define to 1 if `st_ctimensec' is a member of `struct stat'. */
-/* #undef HAVE_STRUCT_STAT_ST_CTIMENSEC */
-
-/* Define to 1 if `st_ctime_n' is a member of `struct stat'. */
-/* #undef HAVE_STRUCT_STAT_ST_CTIME_N */
-
-/* Define to 1 if `st_ctim.tv_nsec' is a member of `struct stat'. */
-/* #undef HAVE_STRUCT_STAT_ST_CTIM_TV_NSEC */
-
-/* Define to 1 if `st_mtimensec' is a member of `struct stat'. */
-/* #undef HAVE_STRUCT_STAT_ST_MTIMENSEC */
-
-/* Define to 1 if `st_mtime_n' is a member of `struct stat'. */
-/* #undef HAVE_STRUCT_STAT_ST_MTIME_N */
-
-/* Define to 1 if `st_mtim.tv_nsec' is a member of `struct stat'. */
-/* #undef HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC */
-
-/* Define to 1 if `tm_gmtoff' is a member of `struct tm'. */
-#define HAVE_STRUCT_TM_TM_GMTOFF 1
-
-/* Define to 1 if `__tm_gmtoff' is a member of `struct tm'. */
-/* #undef HAVE_STRUCT_TM___TM_GMTOFF */
-
-/* Define to 1 if you have the <sysapi.h> header file. */
-/* #undef HAVE_SYSAPI_H */
-
-/* Define to 1 if you have the <sysgtime.h> header file. */
-/* #undef HAVE_SYSGTIME_H */
-
-/* Define to 1 if you have the <sys/file.h> header file. */
-#define HAVE_SYS_FILE_H 1
-
-/* Define to 1 if you have the <sys/ioctl.h> header file. */
-#define HAVE_SYS_IOCTL_H 1
-
-/* Define to 1 if you have the <sys/ipc.h> header file. */
-#define HAVE_SYS_IPC_H 1
-
-/* Define to 1 if you have the <sys/mman.h> header file. */
-#define HAVE_SYS_MMAN_H 1
-
-/* Define to 1 if you have the <sys/mutex.h> header file. */
-/* #undef HAVE_SYS_MUTEX_H */
-
-/* Define to 1 if you have the <sys/param.h> header file. */
-#define HAVE_SYS_PARAM_H 1
-
-/* Define to 1 if you have the <sys/poll.h> header file. */
-#define HAVE_SYS_POLL_H 1
-
-/* Define to 1 if you have the <sys/resource.h> header file. */
-#define HAVE_SYS_RESOURCE_H 1
-
-/* Define to 1 if you have the <sys/select.h> header file. */
-#define HAVE_SYS_SELECT_H 1
-
-/* Define to 1 if you have the <sys/sem.h> header file. */
-#define HAVE_SYS_SEM_H 1
-
-/* Define to 1 if you have the <sys/sendfile.h> header file. */
-/* #undef HAVE_SYS_SENDFILE_H */
-
-/* Define to 1 if you have the <sys/shm.h> header file. */
-#define HAVE_SYS_SHM_H 1
-
-/* Define to 1 if you have the <sys/signal.h> header file. */
-#define HAVE_SYS_SIGNAL_H 1
-
-/* Define to 1 if you have the <sys/socket.h> header file. */
-#define HAVE_SYS_SOCKET_H 1
-
-/* Define to 1 if you have the <sys/sockio.h> header file. */
-#define HAVE_SYS_SOCKIO_H 1
-
-/* Define to 1 if you have the <sys/stat.h> header file. */
-#define HAVE_SYS_STAT_H 1
-
-/* Define to 1 if you have the <sys/sysctl.h> header file. */
-#define HAVE_SYS_SYSCTL_H 1
-
-/* Define to 1 if you have the <sys/syslimits.h> header file. */
-#define HAVE_SYS_SYSLIMITS_H 1
-
-/* Define to 1 if you have the <sys/time.h> header file. */
-#define HAVE_SYS_TIME_H 1
-
-/* Define to 1 if you have the <sys/types.h> header file. */
-#define HAVE_SYS_TYPES_H 1
-
-/* Define to 1 if you have the <sys/uio.h> header file. */
-#define HAVE_SYS_UIO_H 1
-
-/* Define to 1 if you have the <sys/un.h> header file. */
-#define HAVE_SYS_UN_H 1
-
-/* Define to 1 if you have the <sys/uuid.h> header file. */
-/* #undef HAVE_SYS_UUID_H */
-
-/* Define to 1 if you have the <sys/wait.h> header file. */
-#define HAVE_SYS_WAIT_H 1
-
-/* Define if TCP_CORK is defined in netinet/tcp.h */
-/* #undef HAVE_TCP_CORK */
-
-/* Define if TCP_NODELAY and TCP_CORK can be enabled at the same time */
-/* #undef HAVE_TCP_NODELAY_WITH_CORK */
-
-/* Define if TCP_NOPUSH is defined in netinet/tcp.h */
-#define HAVE_TCP_NOPUSH 1
-
-/* Define to 1 if you have the <termios.h> header file. */
-#define HAVE_TERMIOS_H 1
-
-/* Define to 1 if you have the <time.h> header file. */
-#define HAVE_TIME_H 1
-
-/* Define to 1 if you have the <tpfeq.h> header file. */
-/* #undef HAVE_TPFEQ_H */
-
-/* Define to 1 if you have the <tpfio.h> header file. */
-/* #undef HAVE_TPFIO_H */
-
-/* Define if truerand is supported */
-/* #undef HAVE_TRUERAND */
-
-/* Define to 1 if you have the <unistd.h> header file. */
-#define HAVE_UNISTD_H 1
-
-/* Define to 1 if you have the <unix.h> header file. */
-/* #undef HAVE_UNIX_H */
-
-/* Define to 1 if you have the `unsetenv' function. */
-#define HAVE_UNSETENV 1
-
-/* Define to 1 if you have the `utime' function. */
-#define HAVE_UTIME 1
-
-/* Define to 1 if you have the `utimes' function. */
-#define HAVE_UTIMES 1
-
-/* Define to 1 if you have the `uuid_create' function. */
-/* #undef HAVE_UUID_CREATE */
-
-/* Define to 1 if you have the `uuid_generate' function. */
-#define HAVE_UUID_GENERATE 1
-
-/* Define to 1 if you have the <uuid.h> header file. */
-/* #undef HAVE_UUID_H */
-
-/* Define to 1 if you have the <uuid/uuid.h> header file. */
-#define HAVE_UUID_UUID_H 1
-
-/* Define if C compiler supports VLA */
-#define HAVE_VLA 1
-
-/* Define to 1 if you have the `waitpid' function. */
-#define HAVE_WAITPID 1
-
-/* Define to 1 if you have the <windows.h> header file. */
-/* #undef HAVE_WINDOWS_H */
-
-/* Define to 1 if you have the <winsock2.h> header file. */
-/* #undef HAVE_WINSOCK2_H */
-
-/* Define to 1 if you have the `writev' function. */
-#define HAVE_WRITEV 1
-
-/* Define for z/OS pthread API nuances */
-/* #undef HAVE_ZOS_PTHREADS */
-
-/* Define to the sub-directory in which libtool stores uninstalled libraries.
- */
-#define LT_OBJDIR ".libs/"
-
-/* Define if EAI_ error codes from getaddrinfo are negative */
-/* #undef NEGATIVE_EAI */
-
-/* Define to the address where bug reports for this package should be sent. */
-#define PACKAGE_BUGREPORT ""
-
-/* Define to the full name of this package. */
-#define PACKAGE_NAME ""
-
-/* Define to the full name and version of this package. */
-#define PACKAGE_STRING ""
-
-/* Define to the one symbol short name of this package. */
-#define PACKAGE_TARNAME ""
-
-/* Define to the home page for this package. */
-#define PACKAGE_URL ""
-
-/* Define to the version of this package. */
-#define PACKAGE_VERSION ""
-
-/* Define if POSIX semaphores affect threads within the process */
-#define POSIXSEM_IS_GLOBAL 1
-
-/* Define on PowerPC 405 where errata 77 applies */
-/* #undef PPC405_ERRATA */
-
-/* Define if pthread_attr_getdetachstate() has one arg */
-/* #undef PTHREAD_ATTR_GETDETACHSTATE_TAKES_ONE_ARG */
-
-/* Define if pthread_getspecific() has two args */
-/* #undef PTHREAD_GETSPECIFIC_TAKES_TWO_ARGS */
-
-/* Define if readdir is thread safe */
-/* #undef READDIR_IS_THREAD_SAFE */
-
-/* Define to 1 if the `setpgrp' function takes no argument. */
-#define SETPGRP_VOID 1
-
-/* */
-/* #undef SIGWAIT_TAKES_ONE_ARG */
-
-/* The size of `char', as computed by sizeof. */
-#define SIZEOF_CHAR 1
-
-/* The size of `int', as computed by sizeof. */
-#define SIZEOF_INT 4
-
-/* The size of `long', as computed by sizeof. */
-#define SIZEOF_LONG 4
-
-/* The size of `long long', as computed by sizeof. */
-#define SIZEOF_LONG_LONG 8
-
-/* The size of off_t */
-#define SIZEOF_OFF_T 8
-
-/* The size of pid_t */
-#define SIZEOF_PID_T 4
-
-/* The size of `short', as computed by sizeof. */
-#define SIZEOF_SHORT 2
-
-/* The size of size_t */
-#define SIZEOF_SIZE_T 4
-
-/* The size of ssize_t */
-#define SIZEOF_SSIZE_T 4
-
-/* The size of struct iovec */
-#define SIZEOF_STRUCT_IOVEC 8
-
-/* The size of `void*', as computed by sizeof. */
-#define SIZEOF_VOIDP 4
-
-/* If using the C implementation of alloca, define if you know the
- direction of stack growth for your system; otherwise it will be
- automatically deduced at runtime.
- STACK_DIRECTION > 0 => grows toward higher addresses
- STACK_DIRECTION < 0 => grows toward lower addresses
- STACK_DIRECTION = 0 => direction of growth unknown */
-/* #undef STACK_DIRECTION */
-
-/* Define to 1 if you have the ANSI C header files. */
-#define STDC_HEADERS 1
-
-/* Define if strerror returns int */
-#define STRERROR_R_RC_INT 1
-
-/* Define if SysV semaphores affect threads within the process */
-/* #undef SYSVSEM_IS_GLOBAL */
-
-/* Define if use of generic atomics is requested */
-/* #undef USE_ATOMICS_GENERIC */
-
-/* Define if BeOS Semaphores will be used */
-/* #undef USE_BEOSSEM */
-
-/* Define if SVR4-style fcntl() will be used */
-/* #undef USE_FCNTL_SERIALIZE */
-
-/* Define if 4.2BSD-style flock() will be used */
-/* #undef USE_FLOCK_SERIALIZE */
-
-/* Define if BeOS areas will be used */
-/* #undef USE_SHMEM_BEOS */
-
-/* Define if BeOS areas will be used */
-/* #undef USE_SHMEM_BEOS_ANON */
-
-/* Define if 4.4BSD-style mmap() via MAP_ANON will be used */
-#define USE_SHMEM_MMAP_ANON 1
-
-/* Define if mmap() via POSIX.1 shm_open() on temporary file will be used */
-/* #undef USE_SHMEM_MMAP_SHM */
-
-/* Define if Classical mmap() on temporary file will be used */
-/* #undef USE_SHMEM_MMAP_TMP */
-
-/* Define if SVR4-style mmap() on /dev/zero will be used */
-/* #undef USE_SHMEM_MMAP_ZERO */
-
-/* Define if OS/2 DosAllocSharedMem() will be used */
-/* #undef USE_SHMEM_OS2 */
-
-/* Define if OS/2 DosAllocSharedMem() will be used */
-/* #undef USE_SHMEM_OS2_ANON */
-
-/* Define if SysV IPC shmget() will be used */
-#define USE_SHMEM_SHMGET 1
-
-/* Define if SysV IPC shmget() will be used */
-/* #undef USE_SHMEM_SHMGET_ANON */
-
-/* Define if Windows shared memory will be used */
-/* #undef USE_SHMEM_WIN32 */
-
-/* Define if Windows CreateFileMapping() will be used */
-/* #undef USE_SHMEM_WIN32_ANON */
-
-/* Enable extensions on AIX 3, Interix. */
-#ifndef _ALL_SOURCE
-# define _ALL_SOURCE 1
-#endif
-/* Enable GNU extensions on systems that have them. */
-#ifndef _GNU_SOURCE
-# define _GNU_SOURCE 1
-#endif
-/* Enable threading extensions on Solaris. */
-#ifndef _POSIX_PTHREAD_SEMANTICS
-# define _POSIX_PTHREAD_SEMANTICS 1
-#endif
-/* Enable extensions on HP NonStop. */
-#ifndef _TANDEM_SOURCE
-# define _TANDEM_SOURCE 1
-#endif
-/* Enable general extensions on Solaris. */
-#ifndef __EXTENSIONS__
-# define __EXTENSIONS__ 1
-#endif
-
-
-/* Define if SysV IPC semget() will be used */
-#define USE_SYSVSEM_SERIALIZE 1
-
-/* Define if apr_wait_for_io_or_timeout() uses poll(2) */
-/* #undef WAITIO_USES_POLL */
-
-/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most
- significant byte first (like Motorola and SPARC, unlike Intel). */
-#if defined AC_APPLE_UNIVERSAL_BUILD
-# if defined __BIG_ENDIAN__
-# define WORDS_BIGENDIAN 1
-# endif
-#else
-# ifndef WORDS_BIGENDIAN
-/* # undef WORDS_BIGENDIAN */
-# endif
-#endif
-
-/* Define to 1 if on MINIX. */
-/* #undef _MINIX */
-
-/* Define to 2 if the system does not provide POSIX.1 features except with
- this defined. */
-/* #undef _POSIX_1_SOURCE */
-
-/* Define to 1 if you need to in order for `stat' and other things to work. */
-/* #undef _POSIX_SOURCE */
-
-/* Define to empty if `const' does not conform to ANSI C. */
-/* #undef const */
-
-/* Define to `int' if <sys/types.h> doesn't define. */
-/* #undef gid_t */
-
-/* Define to `__inline__' or `__inline' if that's what the C compiler
- calls it, or to nothing if 'inline' is not supported under any name. */
-#ifndef __cplusplus
-/* #undef inline */
-#endif
-
-/* Define to `long int' if <sys/types.h> does not define. */
-/* #undef off_t */
-
-/* Define to `int' if <sys/types.h> does not define. */
-/* #undef pid_t */
-
-/* Define to `unsigned int' if <sys/types.h> does not define. */
-/* #undef size_t */
-
-/* Define to `int' if <sys/types.h> does not define. */
-/* #undef ssize_t */
-
-/* Define to `int' if <sys/types.h> doesn't define. */
-/* #undef uid_t */
-
-
-/* switch this on if we have a BeOS version below BONE */
-#if BEOS && !HAVE_BONE_VERSION
-#define BEOS_R5 1
-#else
-#define BEOS_BONE 1
-#endif
-
-/*
- * Include common private declarations.
- */
-#include "../apr_private_common.h"
-#endif /* APR_PRIVATE_H */
-
+++ /dev/null
-# 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.
-
-#
-# Notice: We do not include the dbd file in the source list.
-#
-
-{
- 'variables': {
- 'aprutil_root': '<(DEPTH)/third_party/apache/aprutil',
- 'aprutil_src_root': '<(aprutil_root)/src',
- 'aprutil_gen_os_root': '<(aprutil_root)/gen/arch/<(OS)',
- 'aprutil_gen_arch_root': '<(aprutil_gen_os_root)/<(target_arch)',
- 'system_include_path_aprutil%': '/usr/include/apr-1.0',
- },
- 'conditions': [
- ['use_system_apache_dev==0', {
- 'targets': [
- {
- 'target_name': 'include',
- 'type': 'none',
- 'direct_dependent_settings': {
- 'include_dirs': [
- '<(aprutil_src_root)/include',
- '<(aprutil_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': 'aprutil',
- 'type': '<(library)',
- 'dependencies': [
- 'include',
- '<(DEPTH)/third_party/apache/apr/apr.gyp:apr',
- ],
- 'export_dependent_settings': [
- 'include',
- ],
- 'include_dirs': [
- '<(aprutil_src_root)/include/private',
- '<(aprutil_gen_arch_root)/include/private',
- ],
- 'sources': [
- 'src/buckets/apr_brigade.c',
- 'src/buckets/apr_buckets.c',
- 'src/buckets/apr_buckets_alloc.c',
- 'src/buckets/apr_buckets_eos.c',
- 'src/buckets/apr_buckets_file.c',
- 'src/buckets/apr_buckets_flush.c',
- 'src/buckets/apr_buckets_heap.c',
- 'src/buckets/apr_buckets_mmap.c',
- 'src/buckets/apr_buckets_pipe.c',
- 'src/buckets/apr_buckets_pool.c',
- 'src/buckets/apr_buckets_refcount.c',
- 'src/buckets/apr_buckets_simple.c',
- 'src/buckets/apr_buckets_socket.c',
- 'src/dbm/apr_dbm.c',
- 'src/dbm/apr_dbm_sdbm.c',
- 'src/dbm/sdbm/sdbm.c',
- 'src/dbm/sdbm/sdbm_hash.c',
- 'src/dbm/sdbm/sdbm_lock.c',
- 'src/dbm/sdbm/sdbm_pair.c',
- 'src/encoding/apr_base64.c',
- 'src/hooks/apr_hooks.c',
- 'src/ldap/apr_ldap_stub.c',
- 'src/ldap/apr_ldap_url.c',
- 'src/memcache/apr_memcache.c',
- 'src/misc/apr_date.c',
- 'src/misc/apr_queue.c',
- 'src/misc/apr_reslist.c',
- 'src/misc/apr_rmm.c',
- 'src/misc/apr_thread_pool.c',
- 'src/misc/apu_dso.c',
- 'src/misc/apu_version.c',
- 'src/strmatch/apr_strmatch.c',
- 'src/uri/apr_uri.c',
- 'src/xlate/xlate.c',
- ],
- 'conditions': [
- ['OS!="win"', {
- 'conditions': [
- ['OS=="linux"', {
- 'cflags': [
- '-pthread',
- '-Wall',
- ],
- }],
- ],
- }],
- ],
- }
- ],
- }, { # use_system_apache_dev
- 'targets': [
- {
- 'target_name': 'include',
- 'type': 'none',
- 'direct_dependent_settings': {
- 'include_dirs': [
- '<(system_include_path_aprutil)',
- ],
- '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': 'aprutil',
- 'type': 'settings',
- 'dependencies': [
- 'include',
- ],
- 'export_dependent_settings': [
- 'include',
- ],
- 'link_settings': {
- 'libraries': [
- '-laprutil-1',
- ],
- },
- },
- ],
- }],
- ],
-}
-
+++ /dev/null
-/* Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/*
- * apr_ldap.h is generated from apr_ldap.h.in by configure -- do not edit apr_ldap.h
- */
-/**
- * @file apr_ldap.h
- * @brief APR-UTIL LDAP
- */
-#ifndef APU_LDAP_H
-#define APU_LDAP_H
-
-/**
- * @defgroup APR_Util_LDAP LDAP
- * @ingroup APR_Util
- * @{
- */
-
-/* this will be defined if LDAP support was compiled into apr-util */
-#define APR_HAS_LDAP 0
-
-/* identify the LDAP toolkit used */
-#define APR_HAS_NETSCAPE_LDAPSDK 0
-#define APR_HAS_SOLARIS_LDAPSDK 0
-#define APR_HAS_NOVELL_LDAPSDK 0
-#define APR_HAS_MOZILLA_LDAPSDK 0
-#define APR_HAS_OPENLDAP_LDAPSDK 0
-#define APR_HAS_MICROSOFT_LDAPSDK 0
-#define APR_HAS_TIVOLI_LDAPSDK 0
-#define APR_HAS_ZOS_LDAPSDK 0
-#define APR_HAS_OTHER_LDAPSDK 0
-
-
-/*
- * Handle the case when LDAP is enabled
- */
-#if APR_HAS_LDAP
-
-/*
- * The following #defines are DEPRECATED and should not be used for
- * anything. They remain to maintain binary compatibility.
- * The original code defined the OPENLDAP SDK as present regardless
- * of what really was there, which was way bogus. In addition, the
- * apr_ldap_url_parse*() functions have been rewritten specifically for
- * APR, so the APR_HAS_LDAP_URL_PARSE macro is forced to zero.
- */
-#if APR_HAS_TIVOLI_LDAPSDK
-#define APR_HAS_LDAP_SSL 0
-#else
-#define APR_HAS_LDAP_SSL 1
-#endif
-#define APR_HAS_LDAP_URL_PARSE 0
-
-#if APR_HAS_OPENLDAP_LDAPSDK && !defined(LDAP_DEPRECATED)
-/* Ensure that the "deprecated" interfaces are still exposed
- * with OpenLDAP >= 2.3; these were exposed by default in earlier
- * releases. */
-#define LDAP_DEPRECATED 1
-#endif
-
-/*
- * Include the standard LDAP header files.
- */
-
-
-
-
-
-
-/*
- * Detected standard functions
- */
-#define APR_HAS_LDAPSSL_CLIENT_INIT 0
-#define APR_HAS_LDAPSSL_CLIENT_DEINIT 0
-#define APR_HAS_LDAPSSL_ADD_TRUSTED_CERT 0
-#define APR_HAS_LDAP_START_TLS_S 0
-#define APR_HAS_LDAP_SSLINIT 0
-#define APR_HAS_LDAPSSL_INIT 0
-#define APR_HAS_LDAPSSL_INSTALL_ROUTINES 0
-
-/*
- * Make sure the secure LDAP port is defined
- */
-#ifndef LDAPS_PORT
-#define LDAPS_PORT 636 /* ldaps:/// default LDAP over TLS port */
-#endif
-
-/*
- * For ldap function calls that input a size limit on the number of returned elements
- * Some SDKs do not have the define for LDAP_DEFAULT_LIMIT (-1) or LDAP_NO_LIMIT (0)
- * LDAP_DEFAULT_LIMIT is preferred as it allows inheritance from whatever the SDK
- * or process is configured for.
- */
-#ifdef LDAP_DEFAULT_LIMIT
-#define APR_LDAP_SIZELIMIT LDAP_DEFAULT_LIMIT
-#else
-#ifdef LDAP_NO_LIMIT
-#define APR_LDAP_SIZELIMIT LDAP_NO_LIMIT
-#endif
-#endif
-
-#ifndef APR_LDAP_SIZELIMIT
-#define APR_LDAP_SIZELIMIT 0 /* equivalent to LDAP_NO_LIMIT, and what goes on the wire */
-#endif
-
-/*
- * z/OS is missing some defines
- */
-#ifndef LDAP_VERSION_MAX
-#define LDAP_VERSION_MAX LDAP_VERSION
-#endif
-#if APR_HAS_ZOS_LDAPSDK
-#define LDAP_VENDOR_NAME "IBM z/OS"
-#endif
-
-/* Note: Macros defining const casting has been removed in APR v1.0,
- * pending real support for LDAP v2.0 toolkits.
- *
- * In the mean time, please use an LDAP v3.0 toolkit.
- */
-#if LDAP_VERSION_MAX <= 2
-#error Support for LDAP v2.0 toolkits has been removed from apr-util. Please use an LDAP v3.0 toolkit.
-#endif
-
-#ifdef __cplusplus
-extern "C" {
-#endif /* __cplusplus */
-
-/**
- * This structure allows the C LDAP API error codes to be returned
- * along with plain text error messages that explain to us mere mortals
- * what really happened.
- */
-typedef struct apr_ldap_err_t {
- const char *reason;
- const char *msg;
- int rc;
-} apr_ldap_err_t;
-
-#ifdef __cplusplus
-}
-#endif
-
-/* The MS SDK returns LDAP_UNAVAILABLE when the backend has closed the connection
- * between LDAP calls. Protect with APR_HAS_MICROSOFT_LDAPSDK in case someone
- * manually chooses another SDK on Windows
- */
-#if APR_HAS_MICROSOFT_LDAPSDK
-#define APR_LDAP_IS_SERVER_DOWN(s) ((s) == LDAP_SERVER_DOWN \
- || (s) == LDAP_UNAVAILABLE)
-#else
-#define APR_LDAP_IS_SERVER_DOWN(s) ((s) == LDAP_SERVER_DOWN)
-#endif
-
-/* These symbols are not actually exported in a DSO build, but mapped into
- * a private exported function array for apr_ldap_stub to bind dynamically.
- * Rename them appropriately to protect the global namespace.
- */
-#ifdef APU_DSO_LDAP_BUILD
-
-#define apr_ldap_info apr__ldap_info
-#define apr_ldap_init apr__ldap_init
-#define apr_ldap_ssl_init apr__ldap_ssl_init
-#define apr_ldap_ssl_deinit apr__ldap_ssl_deinit
-#define apr_ldap_get_option apr__ldap_get_option
-#define apr_ldap_set_option apr__ldap_set_option
-#define apr_ldap_rebind_init apr__ldap_rebind_init
-#define apr_ldap_rebind_add apr__ldap_rebind_add
-#define apr_ldap_rebind_remove apr__ldap_rebind_remove
-
-#define APU_DECLARE_LDAP(type) type
-#else
-#define APU_DECLARE_LDAP(type) APU_DECLARE(type)
-#endif
-
-#include "apr_ldap_url.h"
-#include "apr_ldap_init.h"
-#include "apr_ldap_option.h"
-#include "apr_ldap_rebind.h"
-
-/** @} */
-#endif /* APR_HAS_LDAP */
-#endif /* APU_LDAP_H */
+++ /dev/null
-/* Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/*
- * apu.h is generated from apu.h.in by configure -- do not edit apu.h
- */
-/* @file apu.h
- * @brief APR-Utility main file
- */
-/**
- * @defgroup APR_Util APR Utility Functions
- * @{
- */
-
-
-#ifndef APU_H
-#define APU_H
-
-/**
- * APU_DECLARE_EXPORT is defined when building the APR-UTIL dynamic library,
- * so that all public symbols are exported.
- *
- * APU_DECLARE_STATIC is defined when including the APR-UTIL public headers,
- * to provide static linkage when the dynamic library may be unavailable.
- *
- * APU_DECLARE_STATIC and APU_DECLARE_EXPORT are left undefined when
- * including the APR-UTIL public headers, to import and link the symbols from
- * the dynamic APR-UTIL library and assure appropriate indirection and calling
- * conventions at compile time.
- */
-
-/**
- * The public APR-UTIL functions are declared with APU_DECLARE(), so they may
- * use the most appropriate calling convention. Public APR functions with
- * variable arguments must use APU_DECLARE_NONSTD().
- *
- * @fn APU_DECLARE(rettype) apr_func(args);
- */
-#define APU_DECLARE(type) type
-/**
- * The public APR-UTIL functions using variable arguments are declared with
- * APU_DECLARE_NONSTD(), as they must use the C language calling convention.
- *
- * @fn APU_DECLARE_NONSTD(rettype) apr_func(args, ...);
- */
-#define APU_DECLARE_NONSTD(type) type
-/**
- * The public APR-UTIL variables are declared with APU_DECLARE_DATA.
- * This assures the appropriate indirection is invoked at compile time.
- *
- * @fn APU_DECLARE_DATA type apr_variable;
- * @note APU_DECLARE_DATA extern type apr_variable; syntax is required for
- * declarations within headers to properly import the variable.
- */
-#define APU_DECLARE_DATA
-
-#if !defined(WIN32) || defined(APU_MODULE_DECLARE_STATIC)
-/**
- * Declare a dso module's exported module structure as APU_MODULE_DECLARE_DATA.
- *
- * Unless APU_MODULE_DECLARE_STATIC is defined at compile time, symbols
- * declared with APU_MODULE_DECLARE_DATA are always exported.
- * @code
- * module APU_MODULE_DECLARE_DATA mod_tag
- * @endcode
- */
-#define APU_MODULE_DECLARE_DATA
-#else
-#define APU_MODULE_DECLARE_DATA __declspec(dllexport)
-#endif
-
-/*
- * we always have SDBM (it's in our codebase)
- */
-#define APU_HAVE_SDBM 1
-#define APU_HAVE_GDBM 0
-#define APU_HAVE_NDBM 0
-#define APU_HAVE_DB 0
-
-#if APU_HAVE_DB
-#define APU_HAVE_DB_VERSION 0
-#endif
-
-#define APU_HAVE_PGSQL 1
-#define APU_HAVE_MYSQL 0
-#define APU_HAVE_SQLITE3 1
-#define APU_HAVE_SQLITE2 0
-#define APU_HAVE_ORACLE 0
-#define APU_HAVE_FREETDS 0
-#define APU_HAVE_ODBC 0
-
-#define APU_HAVE_APR_ICONV 0
-#define APU_HAVE_ICONV 1
-#define APR_HAS_XLATE (APU_HAVE_APR_ICONV || APU_HAVE_ICONV)
-
-#endif /* APU_H */
-/** @} */
+++ /dev/null
-/* Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "apu.h" /* configuration data */
-
-/**
- * @file apu_want.h
- * @brief APR Standard Headers Support
- *
- * <PRE>
- * Features:
- *
- * APU_WANT_DB: <db.h>
- *
- * Typical usage:
- *
- * #define APU_WANT_DB
- * #include "apu_want.h"
- *
- * The appropriate headers will be included.
- *
- * Note: it is safe to use this in a header (it won't interfere with other
- * headers' or source files' use of apu_want.h)
- * </PRE>
- */
-
-/* --------------------------------------------------------------------- */
-
-#ifdef APU_WANT_DB
-
-#if APU_HAVE_DB
-#include <db.h>
-#endif
-
-#undef APU_WANT_DB
-#endif
-
-/* --------------------------------------------------------------------- */
+++ /dev/null
-/* include/private/apu_config.h. Generated from apu_config.h.in by configure. */
-/* include/private/apu_config.h.in. Generated from configure.in by autoheader. */
-
-/* Define if the system crypt() function is threadsafe */
-/* #undef APU_CRYPT_THREADSAFE */
-
-/* Define to 1 if modular components are built as DSOs */
-#define APU_DSO_BUILD 1
-
-/* Define to be absolute path to DSO directory */
-#define APU_DSO_LIBDIR "/usr/local/apr/lib/apr-util-1"
-
-/* Define if the inbuf parm to iconv() is const char ** */
-/* #undef APU_ICONV_INBUF_CONST */
-
-/* Define if crypt_r has uses CRYPTD */
-/* #undef CRYPT_R_CRYPTD */
-
-/* Define if crypt_r uses struct crypt_data */
-#define CRYPT_R_STRUCT_CRYPT_DATA 1
-
-/* Define if CODESET is defined in langinfo.h */
-#define HAVE_CODESET 1
-
-/* Define to 1 if you have the `crypt_r' function. */
-#define HAVE_CRYPT_R 1
-
-/* Define if expat.h is available */
-#define HAVE_EXPAT_H 1
-
-/* Define to 1 if you have the <freetds/sybdb.h> header file. */
-/* #undef HAVE_FREETDS_SYBDB_H */
-
-/* Define to 1 if you have the <iconv.h> header file. */
-#define HAVE_ICONV_H 1
-
-/* Define to 1 if you have the <inttypes.h> header file. */
-#define HAVE_INTTYPES_H 1
-
-/* Define to 1 if you have the <langinfo.h> header file. */
-#define HAVE_LANGINFO_H 1
-
-/* Define to 1 if you have the <lber.h> header file. */
-/* #undef HAVE_LBER_H */
-
-/* Defined if ldap.h is present */
-/* #undef HAVE_LDAP_H */
-
-/* Define to 1 if you have the <ldap_ssl.h> header file. */
-/* #undef HAVE_LDAP_SSL_H */
-
-/* Define to 1 if you have the <libpq-fe.h> header file. */
-#define HAVE_LIBPQ_FE_H 1
-
-/* Define to 1 if you have the <memory.h> header file. */
-#define HAVE_MEMORY_H 1
-
-/* Define to 1 if you have the <mysql.h> header file. */
-/* #undef HAVE_MYSQL_H */
-
-/* Define to 1 if you have the <mysql/mysql.h> header file. */
-/* #undef HAVE_MYSQL_MYSQL_H */
-
-/* Define to 1 if you have the <mysql/my_global.h> header file. */
-/* #undef HAVE_MYSQL_MY_GLOBAL_H */
-
-/* Define to 1 if you have the <mysql/my_sys.h> header file. */
-/* #undef HAVE_MYSQL_MY_SYS_H */
-
-/* Define to 1 if you have the <my_global.h> header file. */
-/* #undef HAVE_MY_GLOBAL_H */
-
-/* Define to 1 if you have the <my_sys.h> header file. */
-/* #undef HAVE_MY_SYS_H */
-
-/* Define to 1 if you have the `nl_langinfo' function. */
-#define HAVE_NL_LANGINFO 1
-
-/* Define to 1 if you have the <oci.h> header file. */
-/* #undef HAVE_OCI_H */
-
-/* Define to 1 if you have the <odbc/sql.h> header file. */
-/* #undef HAVE_ODBC_SQL_H */
-
-/* Define to 1 if you have the <postgresql/libpq-fe.h> header file. */
-/* #undef HAVE_POSTGRESQL_LIBPQ_FE_H */
-
-/* Define to 1 if you have the <sqlite3.h> header file. */
-#define HAVE_SQLITE3_H 1
-
-/* Define to 1 if you have the <sqlite.h> header file. */
-/* #undef HAVE_SQLITE_H */
-
-/* Define to 1 if you have the <sql.h> header file. */
-/* #undef HAVE_SQL_H */
-
-/* Define to 1 if you have the <stdint.h> header file. */
-#define HAVE_STDINT_H 1
-
-/* Define to 1 if you have the <stdlib.h> header file. */
-#define HAVE_STDLIB_H 1
-
-/* Define to 1 if you have the <strings.h> header file. */
-#define HAVE_STRINGS_H 1
-
-/* Define to 1 if you have the <string.h> header file. */
-#define HAVE_STRING_H 1
-
-/* Define to 1 if you have the <sybdb.h> header file. */
-/* #undef HAVE_SYBDB_H */
-
-/* Define to 1 if you have the <sys/stat.h> header file. */
-#define HAVE_SYS_STAT_H 1
-
-/* Define to 1 if you have the <sys/types.h> header file. */
-#define HAVE_SYS_TYPES_H 1
-
-/* Define to 1 if you have the <unistd.h> header file. */
-#define HAVE_UNISTD_H 1
-
-/* Define if xmlparse/xmlparse.h is available */
-/* #undef HAVE_XMLPARSE_XMLPARSE_H */
-
-/* Define if xmltok/xmlparse.h is available */
-/* #undef HAVE_XMLTOK_XMLPARSE_H */
-
-/* Define if xml/xmlparse.h is available */
-/* #undef HAVE_XML_XMLPARSE_H */
-
-/* Define if ldap_set_rebind_proc takes three arguments */
-/* #undef LDAP_SET_REBIND_PROC_THREE */
-
-/* Define to the address where bug reports for this package should be sent. */
-#define PACKAGE_BUGREPORT ""
-
-/* Define to the full name of this package. */
-#define PACKAGE_NAME ""
-
-/* Define to the full name and version of this package. */
-#define PACKAGE_STRING ""
-
-/* Define to the one symbol short name of this package. */
-#define PACKAGE_TARNAME ""
-
-/* Define to the version of this package. */
-#define PACKAGE_VERSION ""
-
-/* Define to 1 if you have the ANSI C header files. */
-#define STDC_HEADERS 1
+++ /dev/null
-/* Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef APU_SELECT_DBM_H
-#define APU_SELECT_DBM_H
-
-/*
-** The following macros control what features APRUTIL will use
-*/
-#define APU_USE_SDBM 1
-#define APU_USE_NDBM 0
-#define APU_USE_GDBM 0
-#define APU_USE_DB 0
-
-#endif /* !APU_SELECT_DBM_H */
+++ /dev/null
-/* Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/*
- * apr_ldap.h is generated from apr_ldap.h.in by configure -- do not edit apr_ldap.h
- */
-/**
- * @file apr_ldap.h
- * @brief APR-UTIL LDAP
- */
-#ifndef APU_LDAP_H
-#define APU_LDAP_H
-
-/**
- * @defgroup APR_Util_LDAP LDAP
- * @ingroup APR_Util
- * @{
- */
-
-/* this will be defined if LDAP support was compiled into apr-util */
-#define APR_HAS_LDAP 0
-
-/* identify the LDAP toolkit used */
-#define APR_HAS_NETSCAPE_LDAPSDK 0
-#define APR_HAS_SOLARIS_LDAPSDK 0
-#define APR_HAS_NOVELL_LDAPSDK 0
-#define APR_HAS_MOZILLA_LDAPSDK 0
-#define APR_HAS_OPENLDAP_LDAPSDK 0
-#define APR_HAS_MICROSOFT_LDAPSDK 0
-#define APR_HAS_TIVOLI_LDAPSDK 0
-#define APR_HAS_ZOS_LDAPSDK 0
-#define APR_HAS_OTHER_LDAPSDK 0
-
-
-/*
- * Handle the case when LDAP is enabled
- */
-#if APR_HAS_LDAP
-
-/*
- * The following #defines are DEPRECATED and should not be used for
- * anything. They remain to maintain binary compatibility.
- * The original code defined the OPENLDAP SDK as present regardless
- * of what really was there, which was way bogus. In addition, the
- * apr_ldap_url_parse*() functions have been rewritten specifically for
- * APR, so the APR_HAS_LDAP_URL_PARSE macro is forced to zero.
- */
-#if APR_HAS_TIVOLI_LDAPSDK
-#define APR_HAS_LDAP_SSL 0
-#else
-#define APR_HAS_LDAP_SSL 1
-#endif
-#define APR_HAS_LDAP_URL_PARSE 0
-
-#if APR_HAS_OPENLDAP_LDAPSDK && !defined(LDAP_DEPRECATED)
-/* Ensure that the "deprecated" interfaces are still exposed
- * with OpenLDAP >= 2.3; these were exposed by default in earlier
- * releases. */
-#define LDAP_DEPRECATED 1
-#endif
-
-/*
- * Include the standard LDAP header files.
- */
-
-
-
-
-
-
-/*
- * Detected standard functions
- */
-#define APR_HAS_LDAPSSL_CLIENT_INIT 0
-#define APR_HAS_LDAPSSL_CLIENT_DEINIT 0
-#define APR_HAS_LDAPSSL_ADD_TRUSTED_CERT 0
-#define APR_HAS_LDAP_START_TLS_S 0
-#define APR_HAS_LDAP_SSLINIT 0
-#define APR_HAS_LDAPSSL_INIT 0
-#define APR_HAS_LDAPSSL_INSTALL_ROUTINES 0
-
-/*
- * Make sure the secure LDAP port is defined
- */
-#ifndef LDAPS_PORT
-#define LDAPS_PORT 636 /* ldaps:/// default LDAP over TLS port */
-#endif
-
-/*
- * For ldap function calls that input a size limit on the number of returned elements
- * Some SDKs do not have the define for LDAP_DEFAULT_LIMIT (-1) or LDAP_NO_LIMIT (0)
- * LDAP_DEFAULT_LIMIT is preferred as it allows inheritance from whatever the SDK
- * or process is configured for.
- */
-#ifdef LDAP_DEFAULT_LIMIT
-#define APR_LDAP_SIZELIMIT LDAP_DEFAULT_LIMIT
-#else
-#ifdef LDAP_NO_LIMIT
-#define APR_LDAP_SIZELIMIT LDAP_NO_LIMIT
-#endif
-#endif
-
-#ifndef APR_LDAP_SIZELIMIT
-#define APR_LDAP_SIZELIMIT 0 /* equivalent to LDAP_NO_LIMIT, and what goes on the wire */
-#endif
-
-/*
- * z/OS is missing some defines
- */
-#ifndef LDAP_VERSION_MAX
-#define LDAP_VERSION_MAX LDAP_VERSION
-#endif
-#if APR_HAS_ZOS_LDAPSDK
-#define LDAP_VENDOR_NAME "IBM z/OS"
-#endif
-
-/* Note: Macros defining const casting has been removed in APR v1.0,
- * pending real support for LDAP v2.0 toolkits.
- *
- * In the mean time, please use an LDAP v3.0 toolkit.
- */
-#if LDAP_VERSION_MAX <= 2
-#error Support for LDAP v2.0 toolkits has been removed from apr-util. Please use an LDAP v3.0 toolkit.
-#endif
-
-#ifdef __cplusplus
-extern "C" {
-#endif /* __cplusplus */
-
-/**
- * This structure allows the C LDAP API error codes to be returned
- * along with plain text error messages that explain to us mere mortals
- * what really happened.
- */
-typedef struct apr_ldap_err_t {
- const char *reason;
- const char *msg;
- int rc;
-} apr_ldap_err_t;
-
-#ifdef __cplusplus
-}
-#endif
-
-/* The MS SDK returns LDAP_UNAVAILABLE when the backend has closed the connection
- * between LDAP calls. Protect with APR_HAS_MICROSOFT_LDAPSDK in case someone
- * manually chooses another SDK on Windows
- */
-#if APR_HAS_MICROSOFT_LDAPSDK
-#define APR_LDAP_IS_SERVER_DOWN(s) ((s) == LDAP_SERVER_DOWN \
- || (s) == LDAP_UNAVAILABLE)
-#else
-#define APR_LDAP_IS_SERVER_DOWN(s) ((s) == LDAP_SERVER_DOWN)
-#endif
-
-/* These symbols are not actually exported in a DSO build, but mapped into
- * a private exported function array for apr_ldap_stub to bind dynamically.
- * Rename them appropriately to protect the global namespace.
- */
-#ifdef APU_DSO_LDAP_BUILD
-
-#define apr_ldap_info apr__ldap_info
-#define apr_ldap_init apr__ldap_init
-#define apr_ldap_ssl_init apr__ldap_ssl_init
-#define apr_ldap_ssl_deinit apr__ldap_ssl_deinit
-#define apr_ldap_get_option apr__ldap_get_option
-#define apr_ldap_set_option apr__ldap_set_option
-#define apr_ldap_rebind_init apr__ldap_rebind_init
-#define apr_ldap_rebind_add apr__ldap_rebind_add
-#define apr_ldap_rebind_remove apr__ldap_rebind_remove
-
-#define APU_DECLARE_LDAP(type) type
-#else
-#define APU_DECLARE_LDAP(type) APU_DECLARE(type)
-#endif
-
-#include "apr_ldap_url.h"
-#include "apr_ldap_init.h"
-#include "apr_ldap_option.h"
-#include "apr_ldap_rebind.h"
-
-/** @} */
-#endif /* APR_HAS_LDAP */
-#endif /* APU_LDAP_H */
+++ /dev/null
-/* Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/*
- * apu.h is generated from apu.h.in by configure -- do not edit apu.h
- */
-/* @file apu.h
- * @brief APR-Utility main file
- */
-/**
- * @defgroup APR_Util APR Utility Functions
- * @{
- */
-
-
-#ifndef APU_H
-#define APU_H
-
-/**
- * APU_DECLARE_EXPORT is defined when building the APR-UTIL dynamic library,
- * so that all public symbols are exported.
- *
- * APU_DECLARE_STATIC is defined when including the APR-UTIL public headers,
- * to provide static linkage when the dynamic library may be unavailable.
- *
- * APU_DECLARE_STATIC and APU_DECLARE_EXPORT are left undefined when
- * including the APR-UTIL public headers, to import and link the symbols from
- * the dynamic APR-UTIL library and assure appropriate indirection and calling
- * conventions at compile time.
- */
-
-/**
- * The public APR-UTIL functions are declared with APU_DECLARE(), so they may
- * use the most appropriate calling convention. Public APR functions with
- * variable arguments must use APU_DECLARE_NONSTD().
- *
- * @fn APU_DECLARE(rettype) apr_func(args);
- */
-#define APU_DECLARE(type) type
-/**
- * The public APR-UTIL functions using variable arguments are declared with
- * APU_DECLARE_NONSTD(), as they must use the C language calling convention.
- *
- * @fn APU_DECLARE_NONSTD(rettype) apr_func(args, ...);
- */
-#define APU_DECLARE_NONSTD(type) type
-/**
- * The public APR-UTIL variables are declared with APU_DECLARE_DATA.
- * This assures the appropriate indirection is invoked at compile time.
- *
- * @fn APU_DECLARE_DATA type apr_variable;
- * @note APU_DECLARE_DATA extern type apr_variable; syntax is required for
- * declarations within headers to properly import the variable.
- */
-#define APU_DECLARE_DATA
-
-#if !defined(WIN32) || defined(APU_MODULE_DECLARE_STATIC)
-/**
- * Declare a dso module's exported module structure as APU_MODULE_DECLARE_DATA.
- *
- * Unless APU_MODULE_DECLARE_STATIC is defined at compile time, symbols
- * declared with APU_MODULE_DECLARE_DATA are always exported.
- * @code
- * module APU_MODULE_DECLARE_DATA mod_tag
- * @endcode
- */
-#define APU_MODULE_DECLARE_DATA
-#else
-#define APU_MODULE_DECLARE_DATA __declspec(dllexport)
-#endif
-
-/*
- * we always have SDBM (it's in our codebase)
- */
-#define APU_HAVE_SDBM 1
-#define APU_HAVE_GDBM 0
-#define APU_HAVE_NDBM 0
-#define APU_HAVE_DB 0
-
-#if APU_HAVE_DB
-#define APU_HAVE_DB_VERSION 0
-#endif
-
-#define APU_HAVE_PGSQL 1
-#define APU_HAVE_MYSQL 0
-#define APU_HAVE_SQLITE3 1
-#define APU_HAVE_SQLITE2 0
-#define APU_HAVE_ORACLE 0
-#define APU_HAVE_FREETDS 0
-#define APU_HAVE_ODBC 0
-
-#define APU_HAVE_APR_ICONV 0
-#define APU_HAVE_ICONV 1
-#define APR_HAS_XLATE (APU_HAVE_APR_ICONV || APU_HAVE_ICONV)
-
-#endif /* APU_H */
-/** @} */
+++ /dev/null
-/* Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "apu.h" /* configuration data */
-
-/**
- * @file apu_want.h
- * @brief APR Standard Headers Support
- *
- * <PRE>
- * Features:
- *
- * APU_WANT_DB: <db.h>
- *
- * Typical usage:
- *
- * #define APU_WANT_DB
- * #include "apu_want.h"
- *
- * The appropriate headers will be included.
- *
- * Note: it is safe to use this in a header (it won't interfere with other
- * headers' or source files' use of apu_want.h)
- * </PRE>
- */
-
-/* --------------------------------------------------------------------- */
-
-#ifdef APU_WANT_DB
-
-#if APU_HAVE_DB
-#include <db.h>
-#endif
-
-#undef APU_WANT_DB
-#endif
-
-/* --------------------------------------------------------------------- */
+++ /dev/null
-/* include/private/apu_config.h. Generated from apu_config.h.in by configure. */
-/* include/private/apu_config.h.in. Generated from configure.in by autoheader. */
-
-/* Define if the system crypt() function is threadsafe */
-/* #undef APU_CRYPT_THREADSAFE */
-
-/* Define to 1 if modular components are built as DSOs */
-#define APU_DSO_BUILD 1
-
-/* Define to be absolute path to DSO directory */
-#define APU_DSO_LIBDIR "/usr/local/apr/lib/apr-util-1"
-
-/* Define if the inbuf parm to iconv() is const char ** */
-/* #undef APU_ICONV_INBUF_CONST */
-
-/* Define if crypt_r has uses CRYPTD */
-/* #undef CRYPT_R_CRYPTD */
-
-/* Define if crypt_r uses struct crypt_data */
-#define CRYPT_R_STRUCT_CRYPT_DATA 1
-
-/* Define if CODESET is defined in langinfo.h */
-#define HAVE_CODESET 1
-
-/* Define to 1 if you have the `crypt_r' function. */
-#define HAVE_CRYPT_R 1
-
-/* Define if expat.h is available */
-#define HAVE_EXPAT_H 1
-
-/* Define to 1 if you have the <freetds/sybdb.h> header file. */
-/* #undef HAVE_FREETDS_SYBDB_H */
-
-/* Define to 1 if you have the <iconv.h> header file. */
-#define HAVE_ICONV_H 1
-
-/* Define to 1 if you have the <inttypes.h> header file. */
-#define HAVE_INTTYPES_H 1
-
-/* Define to 1 if you have the <langinfo.h> header file. */
-#define HAVE_LANGINFO_H 1
-
-/* Define to 1 if you have the <lber.h> header file. */
-/* #undef HAVE_LBER_H */
-
-/* Defined if ldap.h is present */
-/* #undef HAVE_LDAP_H */
-
-/* Define to 1 if you have the <ldap_ssl.h> header file. */
-/* #undef HAVE_LDAP_SSL_H */
-
-/* Define to 1 if you have the <libpq-fe.h> header file. */
-#define HAVE_LIBPQ_FE_H 1
-
-/* Define to 1 if you have the <memory.h> header file. */
-#define HAVE_MEMORY_H 1
-
-/* Define to 1 if you have the <mysql.h> header file. */
-/* #undef HAVE_MYSQL_H */
-
-/* Define to 1 if you have the <mysql/mysql.h> header file. */
-/* #undef HAVE_MYSQL_MYSQL_H */
-
-/* Define to 1 if you have the <mysql/my_global.h> header file. */
-/* #undef HAVE_MYSQL_MY_GLOBAL_H */
-
-/* Define to 1 if you have the <mysql/my_sys.h> header file. */
-/* #undef HAVE_MYSQL_MY_SYS_H */
-
-/* Define to 1 if you have the <my_global.h> header file. */
-/* #undef HAVE_MY_GLOBAL_H */
-
-/* Define to 1 if you have the <my_sys.h> header file. */
-/* #undef HAVE_MY_SYS_H */
-
-/* Define to 1 if you have the `nl_langinfo' function. */
-#define HAVE_NL_LANGINFO 1
-
-/* Define to 1 if you have the <oci.h> header file. */
-/* #undef HAVE_OCI_H */
-
-/* Define to 1 if you have the <odbc/sql.h> header file. */
-/* #undef HAVE_ODBC_SQL_H */
-
-/* Define to 1 if you have the <postgresql/libpq-fe.h> header file. */
-/* #undef HAVE_POSTGRESQL_LIBPQ_FE_H */
-
-/* Define to 1 if you have the <sqlite3.h> header file. */
-#define HAVE_SQLITE3_H 1
-
-/* Define to 1 if you have the <sqlite.h> header file. */
-/* #undef HAVE_SQLITE_H */
-
-/* Define to 1 if you have the <sql.h> header file. */
-/* #undef HAVE_SQL_H */
-
-/* Define to 1 if you have the <stdint.h> header file. */
-#define HAVE_STDINT_H 1
-
-/* Define to 1 if you have the <stdlib.h> header file. */
-#define HAVE_STDLIB_H 1
-
-/* Define to 1 if you have the <strings.h> header file. */
-#define HAVE_STRINGS_H 1
-
-/* Define to 1 if you have the <string.h> header file. */
-#define HAVE_STRING_H 1
-
-/* Define to 1 if you have the <sybdb.h> header file. */
-/* #undef HAVE_SYBDB_H */
-
-/* Define to 1 if you have the <sys/stat.h> header file. */
-#define HAVE_SYS_STAT_H 1
-
-/* Define to 1 if you have the <sys/types.h> header file. */
-#define HAVE_SYS_TYPES_H 1
-
-/* Define to 1 if you have the <unistd.h> header file. */
-#define HAVE_UNISTD_H 1
-
-/* Define if xmlparse/xmlparse.h is available */
-/* #undef HAVE_XMLPARSE_XMLPARSE_H */
-
-/* Define if xmltok/xmlparse.h is available */
-/* #undef HAVE_XMLTOK_XMLPARSE_H */
-
-/* Define if xml/xmlparse.h is available */
-/* #undef HAVE_XML_XMLPARSE_H */
-
-/* Define if ldap_set_rebind_proc takes three arguments */
-/* #undef LDAP_SET_REBIND_PROC_THREE */
-
-/* Define to the address where bug reports for this package should be sent. */
-#define PACKAGE_BUGREPORT ""
-
-/* Define to the full name of this package. */
-#define PACKAGE_NAME ""
-
-/* Define to the full name and version of this package. */
-#define PACKAGE_STRING ""
-
-/* Define to the one symbol short name of this package. */
-#define PACKAGE_TARNAME ""
-
-/* Define to the version of this package. */
-#define PACKAGE_VERSION ""
-
-/* Define to 1 if you have the ANSI C header files. */
-#define STDC_HEADERS 1
+++ /dev/null
-/* Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef APU_SELECT_DBM_H
-#define APU_SELECT_DBM_H
-
-/*
-** The following macros control what features APRUTIL will use
-*/
-#define APU_USE_SDBM 1
-#define APU_USE_NDBM 0
-#define APU_USE_GDBM 0
-#define APU_USE_DB 0
-
-#endif /* !APU_SELECT_DBM_H */
+++ /dev/null
-/* Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/*
- * apr_ldap.h is generated from apr_ldap.h.in by configure -- do not edit apr_ldap.h
- */
-/**
- * @file apr_ldap.h
- * @brief APR-UTIL LDAP
- */
-#ifndef APU_LDAP_H
-#define APU_LDAP_H
-
-/**
- * @defgroup APR_Util_LDAP LDAP
- * @ingroup APR_Util
- * @{
- */
-
-/* this will be defined if LDAP support was compiled into apr-util */
-#define APR_HAS_LDAP 0
-
-/* identify the LDAP toolkit used */
-#define APR_HAS_NETSCAPE_LDAPSDK 0
-#define APR_HAS_SOLARIS_LDAPSDK 0
-#define APR_HAS_NOVELL_LDAPSDK 0
-#define APR_HAS_MOZILLA_LDAPSDK 0
-#define APR_HAS_OPENLDAP_LDAPSDK 0
-#define APR_HAS_MICROSOFT_LDAPSDK 0
-#define APR_HAS_TIVOLI_LDAPSDK 0
-#define APR_HAS_ZOS_LDAPSDK 0
-#define APR_HAS_OTHER_LDAPSDK 0
-
-
-/*
- * Handle the case when LDAP is enabled
- */
-#if APR_HAS_LDAP
-
-/*
- * The following #defines are DEPRECATED and should not be used for
- * anything. They remain to maintain binary compatibility.
- * The original code defined the OPENLDAP SDK as present regardless
- * of what really was there, which was way bogus. In addition, the
- * apr_ldap_url_parse*() functions have been rewritten specifically for
- * APR, so the APR_HAS_LDAP_URL_PARSE macro is forced to zero.
- */
-#if APR_HAS_TIVOLI_LDAPSDK
-#define APR_HAS_LDAP_SSL 0
-#else
-#define APR_HAS_LDAP_SSL 1
-#endif
-#define APR_HAS_LDAP_URL_PARSE 0
-
-#if APR_HAS_OPENLDAP_LDAPSDK && !defined(LDAP_DEPRECATED)
-/* Ensure that the "deprecated" interfaces are still exposed
- * with OpenLDAP >= 2.3; these were exposed by default in earlier
- * releases. */
-#define LDAP_DEPRECATED 1
-#endif
-
-/*
- * Include the standard LDAP header files.
- */
-
-
-
-
-
-
-/*
- * Detected standard functions
- */
-#define APR_HAS_LDAPSSL_CLIENT_INIT 0
-#define APR_HAS_LDAPSSL_CLIENT_DEINIT 0
-#define APR_HAS_LDAPSSL_ADD_TRUSTED_CERT 0
-#define APR_HAS_LDAP_START_TLS_S 0
-#define APR_HAS_LDAP_SSLINIT 0
-#define APR_HAS_LDAPSSL_INIT 0
-#define APR_HAS_LDAPSSL_INSTALL_ROUTINES 0
-
-/*
- * Make sure the secure LDAP port is defined
- */
-#ifndef LDAPS_PORT
-#define LDAPS_PORT 636 /* ldaps:/// default LDAP over TLS port */
-#endif
-
-/*
- * For ldap function calls that input a size limit on the number of returned elements
- * Some SDKs do not have the define for LDAP_DEFAULT_LIMIT (-1) or LDAP_NO_LIMIT (0)
- * LDAP_DEFAULT_LIMIT is preferred as it allows inheritance from whatever the SDK
- * or process is configured for.
- */
-#ifdef LDAP_DEFAULT_LIMIT
-#define APR_LDAP_SIZELIMIT LDAP_DEFAULT_LIMIT
-#else
-#ifdef LDAP_NO_LIMIT
-#define APR_LDAP_SIZELIMIT LDAP_NO_LIMIT
-#endif
-#endif
-
-#ifndef APR_LDAP_SIZELIMIT
-#define APR_LDAP_SIZELIMIT 0 /* equivalent to LDAP_NO_LIMIT, and what goes on the wire */
-#endif
-
-/*
- * z/OS is missing some defines
- */
-#ifndef LDAP_VERSION_MAX
-#define LDAP_VERSION_MAX LDAP_VERSION
-#endif
-#if APR_HAS_ZOS_LDAPSDK
-#define LDAP_VENDOR_NAME "IBM z/OS"
-#endif
-
-/* Note: Macros defining const casting has been removed in APR v1.0,
- * pending real support for LDAP v2.0 toolkits.
- *
- * In the mean time, please use an LDAP v3.0 toolkit.
- */
-#if LDAP_VERSION_MAX <= 2
-#error Support for LDAP v2.0 toolkits has been removed from apr-util. Please use an LDAP v3.0 toolkit.
-#endif
-
-#ifdef __cplusplus
-extern "C" {
-#endif /* __cplusplus */
-
-/**
- * This structure allows the C LDAP API error codes to be returned
- * along with plain text error messages that explain to us mere mortals
- * what really happened.
- */
-typedef struct apr_ldap_err_t {
- const char *reason;
- const char *msg;
- int rc;
-} apr_ldap_err_t;
-
-#ifdef __cplusplus
-}
-#endif
-
-/* The MS SDK returns LDAP_UNAVAILABLE when the backend has closed the connection
- * between LDAP calls. Protect with APR_HAS_MICROSOFT_LDAPSDK in case someone
- * manually chooses another SDK on Windows
- */
-#if APR_HAS_MICROSOFT_LDAPSDK
-#define APR_LDAP_IS_SERVER_DOWN(s) ((s) == LDAP_SERVER_DOWN \
- || (s) == LDAP_UNAVAILABLE)
-#else
-#define APR_LDAP_IS_SERVER_DOWN(s) ((s) == LDAP_SERVER_DOWN)
-#endif
-
-/* These symbols are not actually exported in a DSO build, but mapped into
- * a private exported function array for apr_ldap_stub to bind dynamically.
- * Rename them appropriately to protect the global namespace.
- */
-#ifdef APU_DSO_LDAP_BUILD
-
-#define apr_ldap_info apr__ldap_info
-#define apr_ldap_init apr__ldap_init
-#define apr_ldap_ssl_init apr__ldap_ssl_init
-#define apr_ldap_ssl_deinit apr__ldap_ssl_deinit
-#define apr_ldap_get_option apr__ldap_get_option
-#define apr_ldap_set_option apr__ldap_set_option
-#define apr_ldap_rebind_init apr__ldap_rebind_init
-#define apr_ldap_rebind_add apr__ldap_rebind_add
-#define apr_ldap_rebind_remove apr__ldap_rebind_remove
-
-#define APU_DECLARE_LDAP(type) type
-#else
-#define APU_DECLARE_LDAP(type) APU_DECLARE(type)
-#endif
-
-#include "apr_ldap_url.h"
-#include "apr_ldap_init.h"
-#include "apr_ldap_option.h"
-#include "apr_ldap_rebind.h"
-
-/** @} */
-#endif /* APR_HAS_LDAP */
-#endif /* APU_LDAP_H */
+++ /dev/null
-/* Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/*
- * apu.h is generated from apu.h.in by configure -- do not edit apu.h
- */
-/* @file apu.h
- * @brief APR-Utility main file
- */
-/**
- * @defgroup APR_Util APR Utility Functions
- * @{
- */
-
-
-#ifndef APU_H
-#define APU_H
-
-/**
- * APU_DECLARE_EXPORT is defined when building the APR-UTIL dynamic library,
- * so that all public symbols are exported.
- *
- * APU_DECLARE_STATIC is defined when including the APR-UTIL public headers,
- * to provide static linkage when the dynamic library may be unavailable.
- *
- * APU_DECLARE_STATIC and APU_DECLARE_EXPORT are left undefined when
- * including the APR-UTIL public headers, to import and link the symbols from
- * the dynamic APR-UTIL library and assure appropriate indirection and calling
- * conventions at compile time.
- */
-
-/**
- * The public APR-UTIL functions are declared with APU_DECLARE(), so they may
- * use the most appropriate calling convention. Public APR functions with
- * variable arguments must use APU_DECLARE_NONSTD().
- *
- * @fn APU_DECLARE(rettype) apr_func(args);
- */
-#define APU_DECLARE(type) type
-/**
- * The public APR-UTIL functions using variable arguments are declared with
- * APU_DECLARE_NONSTD(), as they must use the C language calling convention.
- *
- * @fn APU_DECLARE_NONSTD(rettype) apr_func(args, ...);
- */
-#define APU_DECLARE_NONSTD(type) type
-/**
- * The public APR-UTIL variables are declared with APU_DECLARE_DATA.
- * This assures the appropriate indirection is invoked at compile time.
- *
- * @fn APU_DECLARE_DATA type apr_variable;
- * @note APU_DECLARE_DATA extern type apr_variable; syntax is required for
- * declarations within headers to properly import the variable.
- */
-#define APU_DECLARE_DATA
-
-#if !defined(WIN32) || defined(APU_MODULE_DECLARE_STATIC)
-/**
- * Declare a dso module's exported module structure as APU_MODULE_DECLARE_DATA.
- *
- * Unless APU_MODULE_DECLARE_STATIC is defined at compile time, symbols
- * declared with APU_MODULE_DECLARE_DATA are always exported.
- * @code
- * module APU_MODULE_DECLARE_DATA mod_tag
- * @endcode
- */
-#define APU_MODULE_DECLARE_DATA
-#else
-#define APU_MODULE_DECLARE_DATA __declspec(dllexport)
-#endif
-
-/*
- * we always have SDBM (it's in our codebase)
- */
-#define APU_HAVE_SDBM 1
-#define APU_HAVE_GDBM 0
-#define APU_HAVE_NDBM 0
-#define APU_HAVE_DB 0
-
-#if APU_HAVE_DB
-#define APU_HAVE_DB_VERSION 0
-#endif
-
-#define APU_HAVE_PGSQL 0
-#define APU_HAVE_MYSQL 0
-#define APU_HAVE_SQLITE3 1
-#define APU_HAVE_SQLITE2 0
-#define APU_HAVE_ORACLE 0
-#define APU_HAVE_FREETDS 0
-#define APU_HAVE_ODBC 0
-
-#define APU_HAVE_APR_ICONV 0
-#define APU_HAVE_ICONV 1
-#define APR_HAS_XLATE (APU_HAVE_APR_ICONV || APU_HAVE_ICONV)
-
-#endif /* APU_H */
-/** @} */
+++ /dev/null
-/* Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "apu.h" /* configuration data */
-
-/**
- * @file apu_want.h
- * @brief APR Standard Headers Support
- *
- * <PRE>
- * Features:
- *
- * APU_WANT_DB: <db.h>
- *
- * Typical usage:
- *
- * #define APU_WANT_DB
- * #include "apu_want.h"
- *
- * The appropriate headers will be included.
- *
- * Note: it is safe to use this in a header (it won't interfere with other
- * headers' or source files' use of apu_want.h)
- * </PRE>
- */
-
-/* --------------------------------------------------------------------- */
-
-#ifdef APU_WANT_DB
-
-#if APU_HAVE_DB
-#include <db.h>
-#endif
-
-#undef APU_WANT_DB
-#endif
-
-/* --------------------------------------------------------------------- */
+++ /dev/null
-/* include/private/apu_config.h. Generated from apu_config.h.in by configure. */
-/* include/private/apu_config.h.in. Generated from configure.in by autoheader. */
-
-/* Define if the system crypt() function is threadsafe */
-/* #undef APU_CRYPT_THREADSAFE */
-
-/* Define to 1 if modular components are built as DSOs */
-#define APU_DSO_BUILD 1
-
-/* Define to be absolute path to DSO directory */
-#define APU_DSO_LIBDIR "/usr/local/apr/lib/apr-util-1"
-
-/* Define if the inbuf parm to iconv() is const char ** */
-/* #undef APU_ICONV_INBUF_CONST */
-
-/* Define if crypt_r has uses CRYPTD */
-/* #undef CRYPT_R_CRYPTD */
-
-/* Define if crypt_r uses struct crypt_data */
-/* #undef CRYPT_R_STRUCT_CRYPT_DATA */
-
-/* Define if CODESET is defined in langinfo.h */
-#define HAVE_CODESET 1
-
-/* Define to 1 if you have the `crypt_r' function. */
-/* #undef HAVE_CRYPT_R */
-
-/* Define if expat.h is available */
-#define HAVE_EXPAT_H 1
-
-/* Define to 1 if you have the <freetds/sybdb.h> header file. */
-/* #undef HAVE_FREETDS_SYBDB_H */
-
-/* Define to 1 if you have the <iconv.h> header file. */
-#define HAVE_ICONV_H 1
-
-/* Define to 1 if you have the <inttypes.h> header file. */
-#define HAVE_INTTYPES_H 1
-
-/* Define to 1 if you have the <langinfo.h> header file. */
-#define HAVE_LANGINFO_H 1
-
-/* Define to 1 if you have the <lber.h> header file. */
-/* #undef HAVE_LBER_H */
-
-/* Defined if ldap.h is present */
-/* #undef HAVE_LDAP_H */
-
-/* Define to 1 if you have the <ldap_ssl.h> header file. */
-/* #undef HAVE_LDAP_SSL_H */
-
-/* Define to 1 if you have the <libpq-fe.h> header file. */
-/* #undef HAVE_LIBPQ_FE_H */
-
-/* Define to 1 if you have the <memory.h> header file. */
-#define HAVE_MEMORY_H 1
-
-/* Define to 1 if you have the <mysql.h> header file. */
-/* #undef HAVE_MYSQL_H */
-
-/* Define to 1 if you have the <mysql/mysql.h> header file. */
-/* #undef HAVE_MYSQL_MYSQL_H */
-
-/* Define to 1 if you have the <mysql/my_global.h> header file. */
-/* #undef HAVE_MYSQL_MY_GLOBAL_H */
-
-/* Define to 1 if you have the <mysql/my_sys.h> header file. */
-/* #undef HAVE_MYSQL_MY_SYS_H */
-
-/* Define to 1 if you have the <my_global.h> header file. */
-/* #undef HAVE_MY_GLOBAL_H */
-
-/* Define to 1 if you have the <my_sys.h> header file. */
-/* #undef HAVE_MY_SYS_H */
-
-/* Define to 1 if you have the `nl_langinfo' function. */
-#define HAVE_NL_LANGINFO 1
-
-/* Define to 1 if you have the <oci.h> header file. */
-/* #undef HAVE_OCI_H */
-
-/* Define to 1 if you have the <odbc/sql.h> header file. */
-/* #undef HAVE_ODBC_SQL_H */
-
-/* Define to 1 if you have the <postgresql/libpq-fe.h> header file. */
-/* #undef HAVE_POSTGRESQL_LIBPQ_FE_H */
-
-/* Define to 1 if you have the <sqlite3.h> header file. */
-#define HAVE_SQLITE3_H 1
-
-/* Define to 1 if you have the <sqlite.h> header file. */
-/* #undef HAVE_SQLITE_H */
-
-/* Define to 1 if you have the <sql.h> header file. */
-#define HAVE_SQL_H 1
-
-/* Define to 1 if you have the <stdint.h> header file. */
-#define HAVE_STDINT_H 1
-
-/* Define to 1 if you have the <stdlib.h> header file. */
-#define HAVE_STDLIB_H 1
-
-/* Define to 1 if you have the <strings.h> header file. */
-#define HAVE_STRINGS_H 1
-
-/* Define to 1 if you have the <string.h> header file. */
-#define HAVE_STRING_H 1
-
-/* Define to 1 if you have the <sybdb.h> header file. */
-/* #undef HAVE_SYBDB_H */
-
-/* Define to 1 if you have the <sys/stat.h> header file. */
-#define HAVE_SYS_STAT_H 1
-
-/* Define to 1 if you have the <sys/types.h> header file. */
-#define HAVE_SYS_TYPES_H 1
-
-/* Define to 1 if you have the <unistd.h> header file. */
-#define HAVE_UNISTD_H 1
-
-/* Define if xmlparse/xmlparse.h is available */
-/* #undef HAVE_XMLPARSE_XMLPARSE_H */
-
-/* Define if xmltok/xmlparse.h is available */
-/* #undef HAVE_XMLTOK_XMLPARSE_H */
-
-/* Define if xml/xmlparse.h is available */
-/* #undef HAVE_XML_XMLPARSE_H */
-
-/* Define if ldap_set_rebind_proc takes three arguments */
-/* #undef LDAP_SET_REBIND_PROC_THREE */
-
-/* Define to the address where bug reports for this package should be sent. */
-#define PACKAGE_BUGREPORT ""
-
-/* Define to the full name of this package. */
-#define PACKAGE_NAME ""
-
-/* Define to the full name and version of this package. */
-#define PACKAGE_STRING ""
-
-/* Define to the one symbol short name of this package. */
-#define PACKAGE_TARNAME ""
-
-/* Define to the home page for this package. */
-#define PACKAGE_URL ""
-
-/* Define to the version of this package. */
-#define PACKAGE_VERSION ""
-
-/* Define to 1 if you have the ANSI C header files. */
-#define STDC_HEADERS 1
+++ /dev/null
-/* Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef APU_SELECT_DBM_H
-#define APU_SELECT_DBM_H
-
-/*
-** The following macros control what features APRUTIL will use
-*/
-#define APU_USE_SDBM 1
-#define APU_USE_NDBM 0
-#define APU_USE_GDBM 0
-#define APU_USE_DB 0
-
-#endif /* !APU_SELECT_DBM_H */
+++ /dev/null
-/* include/ap_config_auto.h. Generated from ap_config_auto.h.in by configure. */
-/* include/ap_config_auto.h.in. Generated from configure.in by autoheader. */
-
-/* Location of the source for the current MPM */
-#define APACHE_MPM_DIR "server/mpm/prefork"
-
-/* SuExec root directory */
-/* #undef AP_DOC_ROOT */
-
-/* Allow modules to run hook after a fatal exception */
-/* #undef AP_ENABLE_EXCEPTION_HOOK */
-
-/* Allow IPv4 connections on IPv6 listening sockets */
-#define AP_ENABLE_V4_MAPPED 1
-
-/* Minimum allowed GID */
-/* #undef AP_GID_MIN */
-
-/* User allowed to call SuExec */
-/* #undef AP_HTTPD_USER */
-
-/* SuExec log file */
-/* #undef AP_LOG_EXEC */
-
-/* Listening sockets are non-blocking when there are more than 1 */
-#define AP_NONBLOCK_WHEN_MULTI_LISTEN 1
-
-/* safe shell path for SuExec */
-/* #undef AP_SAFE_PATH */
-
-/* umask for suexec'd process */
-/* #undef AP_SUEXEC_UMASK */
-
-/* Location of the MIME types config file, relative to the Apache root
- directory */
-#define AP_TYPES_CONFIG_FILE "conf/mime.types"
-
-/* Minimum allowed UID */
-/* #undef AP_UID_MIN */
-
-/* User subdirectory */
-/* #undef AP_USERDIR_SUFFIX */
-
-/* Using autoconf to configure Apache */
-#define AP_USING_AUTOCONF 1
-
-/* Define to 1 if you have the `bindprocessor' function. */
-/* #undef HAVE_BINDPROCESSOR */
-
-/* Define to 1 if you have the <bstring.h> header file. */
-/* #undef HAVE_BSTRING_H */
-
-/* Define if distcache support is enabled */
-/* #undef HAVE_DISTCACHE */
-
-/* Define to 1 if you have the `ENGINE_init' function. */
-/* #undef HAVE_ENGINE_INIT */
-
-/* Define to 1 if you have the `ENGINE_load_builtin_engines' function. */
-/* #undef HAVE_ENGINE_LOAD_BUILTIN_ENGINES */
-
-/* Define to 1 if you have the `getgrnam' function. */
-#define HAVE_GETGRNAM 1
-
-/* Define to 1 if you have the `getpgid' function. */
-#define HAVE_GETPGID 1
-
-/* Define to 1 if you have the `getpwnam' function. */
-#define HAVE_GETPWNAM 1
-
-/* Define if struct tm has a tm_gmtoff field */
-#define HAVE_GMTOFF 1
-
-/* Define to 1 if you have the <grp.h> header file. */
-#define HAVE_GRP_H 1
-
-/* Define to 1 if you have the `initgroups' function. */
-#define HAVE_INITGROUPS 1
-
-/* Define to 1 if you have the <inttypes.h> header file. */
-#define HAVE_INTTYPES_H 1
-
-/* Define to 1 if you have the `killpg' function. */
-#define HAVE_KILLPG 1
-
-/* Define to 1 if you have the <limits.h> header file. */
-#define HAVE_LIMITS_H 1
-
-/* Define to 1 if you have the <memory.h> header file. */
-#define HAVE_MEMORY_H 1
-
-/* Define if SSL is supported using OpenSSL */
-/* #undef HAVE_OPENSSL */
-
-/* Define to 1 if you have the <openssl/engine.h> header file. */
-/* #undef HAVE_OPENSSL_ENGINE_H */
-
-/* Define to 1 if you have the <openssl/opensslv.h> header file. */
-/* #undef HAVE_OPENSSL_OPENSSLV_H */
-
-/* Define to 1 if you have the <openssl/ssl.h> header file. */
-/* #undef HAVE_OPENSSL_SSL_H */
-
-/* Define to 1 if you have the `prctl' function. */
-#define HAVE_PRCTL 1
-
-/* Define to 1 if you have the `pthread_kill' function. */
-/* #undef HAVE_PTHREAD_KILL */
-
-/* Define to 1 if you have the <pwd.h> header file. */
-#define HAVE_PWD_H 1
-
-/* Define to 1 if you have the `setsid' function. */
-#define HAVE_SETSID 1
-
-/* Define if SSL is supported using SSL-C */
-/* #undef HAVE_SSLC */
-
-/* Define to 1 if you have the <sslc.h> header file. */
-/* #undef HAVE_SSLC_H */
-
-/* Define to 1 if you have the `SSLC_library_version' function. */
-/* #undef HAVE_SSLC_LIBRARY_VERSION */
-
-/* Define to 1 if you have the `SSLeay_version' function. */
-/* #undef HAVE_SSLEAY_VERSION */
-
-/* Define to 1 if you have the `SSL_CTX_new' function. */
-/* #undef HAVE_SSL_CTX_NEW */
-
-/* Define to 1 if you have the `SSL_set_cert_store' function. */
-/* #undef HAVE_SSL_SET_CERT_STORE */
-
-/* Define to 1 if you have the `SSL_set_state' function. */
-/* #undef HAVE_SSL_SET_STATE */
-
-/* Define to 1 if you have the <stdint.h> header file. */
-#define HAVE_STDINT_H 1
-
-/* Define to 1 if you have the <stdlib.h> header file. */
-#define HAVE_STDLIB_H 1
-
-/* Define to 1 if you have the <strings.h> header file. */
-#define HAVE_STRINGS_H 1
-
-/* Define to 1 if you have the <string.h> header file. */
-#define HAVE_STRING_H 1
-
-/* Define to 1 if you have the `syslog' function. */
-/* #undef HAVE_SYSLOG */
-
-/* Define to 1 if you have the <sys/ipc.h> header file. */
-#define HAVE_SYS_IPC_H 1
-
-/* Define to 1 if you have the <sys/prctl.h> header file. */
-#define HAVE_SYS_PRCTL_H 1
-
-/* Define to 1 if you have the <sys/processor.h> header file. */
-/* #undef HAVE_SYS_PROCESSOR_H */
-
-/* Define to 1 if you have the <sys/resource.h> header file. */
-#define HAVE_SYS_RESOURCE_H 1
-
-/* Define to 1 if you have the <sys/sem.h> header file. */
-#define HAVE_SYS_SEM_H 1
-
-/* Define to 1 if you have the <sys/socket.h> header file. */
-#define HAVE_SYS_SOCKET_H 1
-
-/* Define to 1 if you have the <sys/stat.h> header file. */
-#define HAVE_SYS_STAT_H 1
-
-/* Define to 1 if you have the <sys/times.h> header file. */
-#define HAVE_SYS_TIMES_H 1
-
-/* Define to 1 if you have the <sys/time.h> header file. */
-#define HAVE_SYS_TIME_H 1
-
-/* Define to 1 if you have the <sys/types.h> header file. */
-#define HAVE_SYS_TYPES_H 1
-
-/* Define to 1 if you have <sys/wait.h> that is POSIX.1 compatible. */
-#define HAVE_SYS_WAIT_H 1
-
-/* Define to 1 if you have the `timegm' function. */
-#define HAVE_TIMEGM 1
-
-/* Define to 1 if you have the `times' function. */
-#define HAVE_TIMES 1
-
-/* Define to 1 if you have the <unistd.h> header file. */
-#define HAVE_UNISTD_H 1
-
-/* Root directory of the Apache install area */
-/* #define HTTPD_ROOT "/usr/local/apache2" */
-
-/* Define to the address where bug reports for this package should be sent. */
-#define PACKAGE_BUGREPORT ""
-
-/* Define to the full name of this package. */
-#define PACKAGE_NAME ""
-
-/* Define to the full name and version of this package. */
-#define PACKAGE_STRING ""
-
-/* Define to the one symbol short name of this package. */
-#define PACKAGE_TARNAME ""
-
-/* Define to the version of this package. */
-#define PACKAGE_VERSION ""
-
-/* Location of the config file, relative to the Apache root directory */
-#define SERVER_CONFIG_FILE "conf/httpd.conf"
-
-/* This platform doesn't suffer from the thundering herd problem */
-#define SINGLE_LISTEN_UNSERIALIZED_ACCEPT 1
-
-/* Define to 1 if you have the ANSI C header files. */
-#define STDC_HEADERS 1
-
-/* Path to suexec binary */
-/* #undef SUEXEC_BIN */
-
-/* Define to 1 if on AIX 3.
- System headers sometimes define this.
- We just want to avoid a redefinition error message. */
-#ifndef _ALL_SOURCE
-/* # undef _ALL_SOURCE */
-#endif
-
-/* Enable GNU extensions on systems that have them. */
-#ifndef _GNU_SOURCE
-# define _GNU_SOURCE 1
-#endif
-
-/* Define to 1 if on MINIX. */
-/* #undef _MINIX */
-
-/* Define to 2 if the system does not provide POSIX.1 features except with
- this defined. */
-/* #undef _POSIX_1_SOURCE */
-
-/* Define to 1 if you need to in order for `stat' and other things to work. */
-/* #undef _POSIX_SOURCE */
-
-/* Enable extensions on Solaris. */
-#ifndef __EXTENSIONS__
-# define __EXTENSIONS__ 1
-#endif
-#ifndef _POSIX_PTHREAD_SEMANTICS
-# define _POSIX_PTHREAD_SEMANTICS 1
-#endif
-#ifndef _TANDEM_SOURCE
-# define _TANDEM_SOURCE 1
-#endif
-
-/* Define to empty if `const' does not conform to ANSI C. */
-/* #undef const */
-
-/* Define to 'int' if <sys/resource.h> doesn't define it for us */
-/* #undef rlim_t */
+++ /dev/null
-/* Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**
- * @file ap_config_layout.h
- * @brief Apache Config Layout
- */
-
-#ifndef AP_CONFIG_LAYOUT_H
-#define AP_CONFIG_LAYOUT_H
-
-/* Configured Apache directory layout */
-/*
-#define DEFAULT_PREFIX "/usr/local/apache2"
-#define DEFAULT_EXP_EXEC_PREFIX "/usr/local/apache2"
-#define DEFAULT_REL_EXEC_PREFIX ""
-#define DEFAULT_EXP_BINDIR "/usr/local/apache2/bin"
-#define DEFAULT_REL_BINDIR "bin"
-#define DEFAULT_EXP_SBINDIR "/usr/local/apache2/bin"
-#define DEFAULT_REL_SBINDIR "bin"
-#define DEFAULT_EXP_LIBEXECDIR "/usr/local/apache2/modules"
-#define DEFAULT_REL_LIBEXECDIR "modules"
-#define DEFAULT_EXP_MANDIR "/usr/local/apache2/man"
-#define DEFAULT_REL_MANDIR "man"
-#define DEFAULT_EXP_SYSCONFDIR "/usr/local/apache2/conf"
-#define DEFAULT_REL_SYSCONFDIR "conf"
-#define DEFAULT_EXP_DATADIR "/usr/local/apache2"
-#define DEFAULT_REL_DATADIR ""
-#define DEFAULT_EXP_INSTALLBUILDDIR "/usr/local/apache2/build"
-#define DEFAULT_REL_INSTALLBUILDDIR "build"
-#define DEFAULT_EXP_ERRORDIR "/usr/local/apache2/error"
-#define DEFAULT_REL_ERRORDIR "error"
-#define DEFAULT_EXP_ICONSDIR "/usr/local/apache2/icons"
-#define DEFAULT_REL_ICONSDIR "icons"
-#define DEFAULT_EXP_HTDOCSDIR "/usr/local/apache2/htdocs"
-#define DEFAULT_REL_HTDOCSDIR "htdocs"
-#define DEFAULT_EXP_MANUALDIR "/usr/local/apache2/manual"
-#define DEFAULT_REL_MANUALDIR "manual"
-#define DEFAULT_EXP_CGIDIR "/usr/local/apache2/cgi-bin"
-#define DEFAULT_REL_CGIDIR "cgi-bin"
-#define DEFAULT_EXP_INCLUDEDIR "/usr/local/apache2/include"
-#define DEFAULT_REL_INCLUDEDIR "include"
-#define DEFAULT_EXP_LOCALSTATEDIR "/usr/local/apache2"
-#define DEFAULT_REL_LOCALSTATEDIR ""
-#define DEFAULT_EXP_RUNTIMEDIR "/usr/local/apache2/logs"
-#define DEFAULT_REL_RUNTIMEDIR "logs"
-#define DEFAULT_EXP_LOGFILEDIR "/usr/local/apache2/logs"
-#define DEFAULT_REL_LOGFILEDIR "logs"
-#define DEFAULT_EXP_PROXYCACHEDIR "/usr/local/apache2/proxy"
-#define DEFAULT_REL_PROXYCACHEDIR "proxy"
-*/
-
-#endif /* AP_CONFIG_LAYOUT_H */
+++ /dev/null
-/* include/ap_config_auto.h. Generated automatically by configure. */
-/* include/ap_config_auto.h.in. Generated automatically from configure.in by autoheader 2.13. */
-
-/* Define if on AIX 3.
- System headers sometimes define this.
- We just want to avoid a redefinition error message. */
-#ifndef _ALL_SOURCE
-/* #undef _ALL_SOURCE */
-#endif
-
-/* Define to empty if the keyword does not work. */
-/* #undef const */
-
-/* Define if you have <sys/wait.h> that is POSIX.1 compatible. */
-#define HAVE_SYS_WAIT_H 1
-
-/* Define if on MINIX. */
-/* #undef _MINIX */
-
-/* Define if the system does not provide POSIX.1 features except
- with this defined. */
-/* #undef _POSIX_1_SOURCE */
-
-/* Define if you need to in order for stat and other things to work. */
-/* #undef _POSIX_SOURCE */
-
-/* Define if you have the ANSI C header files. */
-#define STDC_HEADERS 1
-
-/* Define if you have the ENGINE_init function. */
-/* #undef HAVE_ENGINE_INIT */
-
-/* Define if you have the ENGINE_load_builtin_engines function. */
-/* #undef HAVE_ENGINE_LOAD_BUILTIN_ENGINES */
-
-/* Define if you have the SSLC_library_version function. */
-/* #undef HAVE_SSLC_LIBRARY_VERSION */
-
-/* Define if you have the SSL_CTX_new function. */
-/* #undef HAVE_SSL_CTX_NEW */
-
-/* Define if you have the SSL_set_cert_store function. */
-/* #undef HAVE_SSL_SET_CERT_STORE */
-
-/* Define if you have the SSL_set_state function. */
-/* #undef HAVE_SSL_SET_STATE */
-
-/* Define if you have the SSLeay_version function. */
-/* #undef HAVE_SSLEAY_VERSION */
-
-/* Define if you have the bindprocessor function. */
-/* #undef HAVE_BINDPROCESSOR */
-
-/* Define if you have the getgrnam function. */
-#define HAVE_GETGRNAM 1
-
-/* Define if you have the getpgid function. */
-#define HAVE_GETPGID 1
-
-/* Define if you have the getpwnam function. */
-#define HAVE_GETPWNAM 1
-
-/* Define if you have the initgroups function. */
-#define HAVE_INITGROUPS 1
-
-/* Define if you have the killpg function. */
-#define HAVE_KILLPG 1
-
-/* Define if you have the prctl function. */
-#define HAVE_PRCTL 1
-
-/* Define if you have the pthread_kill function. */
-/* #undef HAVE_PTHREAD_KILL */
-
-/* Define if you have the setsid function. */
-#define HAVE_SETSID 1
-
-/* Define if you have the syslog function. */
-/* #undef HAVE_SYSLOG */
-
-/* Define if you have the timegm function. */
-#define HAVE_TIMEGM 1
-
-/* Define if you have the times function. */
-#define HAVE_TIMES 1
-
-/* Define if you have the <bstring.h> header file. */
-/* #undef HAVE_BSTRING_H */
-
-/* Define if you have the <grp.h> header file. */
-#define HAVE_GRP_H 1
-
-/* Define if you have the <limits.h> header file. */
-#define HAVE_LIMITS_H 1
-
-/* Define if you have the <openssl/engine.h> header file. */
-/* #undef HAVE_OPENSSL_ENGINE_H */
-
-/* Define if you have the <openssl/opensslv.h> header file. */
-/* #undef HAVE_OPENSSL_OPENSSLV_H */
-
-/* Define if you have the <openssl/ssl.h> header file. */
-/* #undef HAVE_OPENSSL_SSL_H */
-
-/* Define if you have the <pwd.h> header file. */
-#define HAVE_PWD_H 1
-
-/* Define if you have the <sslc.h> header file. */
-/* #undef HAVE_SSLC_H */
-
-/* Define if you have the <string.h> header file. */
-#define HAVE_STRING_H 1
-
-/* Define if you have the <strings.h> header file. */
-#define HAVE_STRINGS_H 1
-
-/* Define if you have the <sys/ipc.h> header file. */
-#define HAVE_SYS_IPC_H 1
-
-/* Define if you have the <sys/prctl.h> header file. */
-#define HAVE_SYS_PRCTL_H 1
-
-/* Define if you have the <sys/processor.h> header file. */
-/* #undef HAVE_SYS_PROCESSOR_H */
-
-/* Define if you have the <sys/resource.h> header file. */
-#define HAVE_SYS_RESOURCE_H 1
-
-/* Define if you have the <sys/sem.h> header file. */
-#define HAVE_SYS_SEM_H 1
-
-/* Define if you have the <sys/socket.h> header file. */
-#define HAVE_SYS_SOCKET_H 1
-
-/* Define if you have the <sys/time.h> header file. */
-#define HAVE_SYS_TIME_H 1
-
-/* Define if you have the <sys/times.h> header file. */
-#define HAVE_SYS_TIMES_H 1
-
-/* Define if you have the <unistd.h> header file. */
-#define HAVE_UNISTD_H 1
-
-/* Define if struct tm has a tm_gmtoff field */
-#define HAVE_GMTOFF 1
-
-/* Allow IPv4 connections on IPv6 listening sockets */
-#define AP_ENABLE_V4_MAPPED 1
-
-/* Allow modules to run hook after a fatal exception */
-/* #undef AP_ENABLE_EXCEPTION_HOOK */
-
-/* Define if SSL is supported using OpenSSL */
-/* #undef HAVE_OPENSSL */
-
-/* Define if SSL is supported using SSL-C */
-/* #undef HAVE_SSLC */
-
-/* Define if distcache support is enabled */
-/* #undef HAVE_DISTCACHE */
-
-/* Define to 'int' if <sys/resource.h> doesn't define it for us */
-/* #undef rlim_t */
-
-/* Path to suexec binary */
-/* #undef SUEXEC_BIN */
-
-/* User allowed to call SuExec */
-/* #undef AP_HTTPD_USER */
-
-/* User subdirectory */
-/* #undef AP_USERDIR_SUFFIX */
-
-/* SuExec root directory */
-/* #undef AP_DOC_ROOT */
-
-/* Minimum allowed UID */
-/* #undef AP_UID_MIN */
-
-/* Minimum allowed GID */
-/* #undef AP_GID_MIN */
-
-/* SuExec log file */
-/* #undef AP_LOG_EXEC */
-
-/* safe shell path for SuExec */
-/* #undef AP_SAFE_PATH */
-
-/* umask for suexec'd process */
-/* #undef AP_SUEXEC_UMASK */
-
-/* Using autoconf to configure Apache */
-#define AP_USING_AUTOCONF 1
-
-/* This platform doesn't suffer from the thundering herd problem */
-#define SINGLE_LISTEN_UNSERIALIZED_ACCEPT 1
-
-/* Listening sockets are non-blocking when there are more than 1 */
-#define AP_NONBLOCK_WHEN_MULTI_LISTEN 1
-
-/* Root directory of the Apache install area */
-/* #define HTTPD_ROOT "/usr/local/apache2" */
-
-/* Location of the config file, relative to the Apache root directory */
-#define SERVER_CONFIG_FILE "conf/httpd.conf"
-
-/* Location of the MIME types config file, relative to the Apache root directory */
-#define AP_TYPES_CONFIG_FILE "conf/mime.types"
-
-/* Location of the source for the current MPM */
-#define APACHE_MPM_DIR "server/mpm/prefork"
-
+++ /dev/null
-/* Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**
- * @file ap_config_layout.h
- * @brief Apache Config Layout
- */
-
-#ifndef AP_CONFIG_LAYOUT_H
-#define AP_CONFIG_LAYOUT_H
-
-/* Configured Apache directory layout */
-/*
-#define DEFAULT_PREFIX "/usr/local/apache2"
-#define DEFAULT_EXP_EXEC_PREFIX "/usr/local/apache2"
-#define DEFAULT_REL_EXEC_PREFIX ""
-#define DEFAULT_EXP_BINDIR "/usr/local/apache2/bin"
-#define DEFAULT_REL_BINDIR "bin"
-#define DEFAULT_EXP_SBINDIR "/usr/local/apache2/bin"
-#define DEFAULT_REL_SBINDIR "bin"
-#define DEFAULT_EXP_LIBEXECDIR "/usr/local/apache2/modules"
-#define DEFAULT_REL_LIBEXECDIR "modules"
-#define DEFAULT_EXP_MANDIR "/usr/local/apache2/man"
-#define DEFAULT_REL_MANDIR "man"
-#define DEFAULT_EXP_SYSCONFDIR "/usr/local/apache2/conf"
-#define DEFAULT_REL_SYSCONFDIR "conf"
-#define DEFAULT_EXP_DATADIR "/usr/local/apache2"
-#define DEFAULT_REL_DATADIR ""
-#define DEFAULT_EXP_INSTALLBUILDDIR "/usr/local/apache2/build"
-#define DEFAULT_REL_INSTALLBUILDDIR "build"
-#define DEFAULT_EXP_ERRORDIR "/usr/local/apache2/error"
-#define DEFAULT_REL_ERRORDIR "error"
-#define DEFAULT_EXP_ICONSDIR "/usr/local/apache2/icons"
-#define DEFAULT_REL_ICONSDIR "icons"
-#define DEFAULT_EXP_HTDOCSDIR "/usr/local/apache2/htdocs"
-#define DEFAULT_REL_HTDOCSDIR "htdocs"
-#define DEFAULT_EXP_MANUALDIR "/usr/local/apache2/manual"
-#define DEFAULT_REL_MANUALDIR "manual"
-#define DEFAULT_EXP_CGIDIR "/usr/local/apache2/cgi-bin"
-#define DEFAULT_REL_CGIDIR "cgi-bin"
-#define DEFAULT_EXP_INCLUDEDIR "/usr/local/apache2/include"
-#define DEFAULT_REL_INCLUDEDIR "include"
-#define DEFAULT_EXP_LOCALSTATEDIR "/usr/local/apache2"
-#define DEFAULT_REL_LOCALSTATEDIR ""
-#define DEFAULT_EXP_RUNTIMEDIR "/usr/local/apache2/logs"
-#define DEFAULT_REL_RUNTIMEDIR "logs"
-#define DEFAULT_EXP_LOGFILEDIR "/usr/local/apache2/logs"
-#define DEFAULT_REL_LOGFILEDIR "logs"
-#define DEFAULT_EXP_PROXYCACHEDIR "/usr/local/apache2/proxy"
-#define DEFAULT_REL_PROXYCACHEDIR "proxy"
-*/
-
-#endif /* AP_CONFIG_LAYOUT_H */
+++ /dev/null
-/* include/ap_config_auto.h. Generated from ap_config_auto.h.in by configure. */
-/* include/ap_config_auto.h.in. Generated from configure.in by autoheader. */
-
-/* Location of the source for the current MPM */
-#define APACHE_MPM_DIR "server/mpm/prefork"
-
-/* SuExec root directory */
-/* #undef AP_DOC_ROOT */
-
-/* Allow modules to run hook after a fatal exception */
-/* #undef AP_ENABLE_EXCEPTION_HOOK */
-
-/* Allow IPv4 connections on IPv6 listening sockets */
-#define AP_ENABLE_V4_MAPPED 1
-
-/* Minimum allowed GID */
-/* #undef AP_GID_MIN */
-
-/* User allowed to call SuExec */
-/* #undef AP_HTTPD_USER */
-
-/* SuExec log file */
-/* #undef AP_LOG_EXEC */
-
-/* Listening sockets are non-blocking when there are more than 1 */
-#define AP_NONBLOCK_WHEN_MULTI_LISTEN 1
-
-/* safe shell path for SuExec */
-/* #undef AP_SAFE_PATH */
-
-/* umask for suexec'd process */
-/* #undef AP_SUEXEC_UMASK */
-
-/* Location of the MIME types config file, relative to the Apache root
- directory */
-#define AP_TYPES_CONFIG_FILE "conf/mime.types"
-
-/* Minimum allowed UID */
-/* #undef AP_UID_MIN */
-
-/* User subdirectory */
-/* #undef AP_USERDIR_SUFFIX */
-
-/* Using autoconf to configure Apache */
-#define AP_USING_AUTOCONF 1
-
-/* Define to 1 if you have the `bindprocessor' function. */
-/* #undef HAVE_BINDPROCESSOR */
-
-/* Define to 1 if you have the <bstring.h> header file. */
-/* #undef HAVE_BSTRING_H */
-
-/* Define if distcache support is enabled */
-/* #undef HAVE_DISTCACHE */
-
-/* Define to 1 if you have the `ENGINE_init' function. */
-/* #undef HAVE_ENGINE_INIT */
-
-/* Define to 1 if you have the `ENGINE_load_builtin_engines' function. */
-/* #undef HAVE_ENGINE_LOAD_BUILTIN_ENGINES */
-
-/* Define to 1 if you have the `getgrnam' function. */
-#define HAVE_GETGRNAM 1
-
-/* Define to 1 if you have the `getpgid' function. */
-#define HAVE_GETPGID 1
-
-/* Define to 1 if you have the `getpwnam' function. */
-#define HAVE_GETPWNAM 1
-
-/* Define if struct tm has a tm_gmtoff field */
-#define HAVE_GMTOFF 1
-
-/* Define to 1 if you have the <grp.h> header file. */
-#define HAVE_GRP_H 1
-
-/* Define to 1 if you have the `initgroups' function. */
-#define HAVE_INITGROUPS 1
-
-/* Define to 1 if you have the <inttypes.h> header file. */
-#define HAVE_INTTYPES_H 1
-
-/* Define to 1 if you have the `killpg' function. */
-#define HAVE_KILLPG 1
-
-/* Define to 1 if you have the <limits.h> header file. */
-#define HAVE_LIMITS_H 1
-
-/* Define to 1 if you have the <memory.h> header file. */
-#define HAVE_MEMORY_H 1
-
-/* Define if SSL is supported using OpenSSL */
-/* #undef HAVE_OPENSSL */
-
-/* Define to 1 if you have the <openssl/engine.h> header file. */
-/* #undef HAVE_OPENSSL_ENGINE_H */
-
-/* Define to 1 if you have the <openssl/opensslv.h> header file. */
-/* #undef HAVE_OPENSSL_OPENSSLV_H */
-
-/* Define to 1 if you have the <openssl/ssl.h> header file. */
-/* #undef HAVE_OPENSSL_SSL_H */
-
-/* Define to 1 if you have the `prctl' function. */
-/* #undef HAVE_PRCTL */
-
-/* Define to 1 if you have the `pthread_kill' function. */
-/* #undef HAVE_PTHREAD_KILL */
-
-/* Define to 1 if you have the <pwd.h> header file. */
-#define HAVE_PWD_H 1
-
-/* Define to 1 if you have the `setsid' function. */
-#define HAVE_SETSID 1
-
-/* Define if SSL is supported using SSL-C */
-/* #undef HAVE_SSLC */
-
-/* Define to 1 if you have the <sslc.h> header file. */
-/* #undef HAVE_SSLC_H */
-
-/* Define to 1 if you have the `SSLC_library_version' function. */
-/* #undef HAVE_SSLC_LIBRARY_VERSION */
-
-/* Define to 1 if you have the `SSLeay_version' function. */
-/* #undef HAVE_SSLEAY_VERSION */
-
-/* Define to 1 if you have the `SSL_CTX_new' function. */
-/* #undef HAVE_SSL_CTX_NEW */
-
-/* Define to 1 if you have the `SSL_set_cert_store' function. */
-/* #undef HAVE_SSL_SET_CERT_STORE */
-
-/* Define to 1 if you have the `SSL_set_state' function. */
-/* #undef HAVE_SSL_SET_STATE */
-
-/* Define to 1 if you have the <stdint.h> header file. */
-#define HAVE_STDINT_H 1
-
-/* Define to 1 if you have the <stdlib.h> header file. */
-#define HAVE_STDLIB_H 1
-
-/* Define to 1 if you have the <strings.h> header file. */
-#define HAVE_STRINGS_H 1
-
-/* Define to 1 if you have the <string.h> header file. */
-#define HAVE_STRING_H 1
-
-/* Define to 1 if you have the `syslog' function. */
-/* #undef HAVE_SYSLOG */
-
-/* Define to 1 if you have the <sys/ipc.h> header file. */
-#define HAVE_SYS_IPC_H 1
-
-/* Define to 1 if you have the <sys/prctl.h> header file. */
-/* #undef HAVE_SYS_PRCTL_H */
-
-/* Define to 1 if you have the <sys/processor.h> header file. */
-/* #undef HAVE_SYS_PROCESSOR_H */
-
-/* Define to 1 if you have the <sys/resource.h> header file. */
-#define HAVE_SYS_RESOURCE_H 1
-
-/* Define to 1 if you have the <sys/sem.h> header file. */
-#define HAVE_SYS_SEM_H 1
-
-/* Define to 1 if you have the <sys/socket.h> header file. */
-#define HAVE_SYS_SOCKET_H 1
-
-/* Define to 1 if you have the <sys/stat.h> header file. */
-#define HAVE_SYS_STAT_H 1
-
-/* Define to 1 if you have the <sys/times.h> header file. */
-#define HAVE_SYS_TIMES_H 1
-
-/* Define to 1 if you have the <sys/time.h> header file. */
-#define HAVE_SYS_TIME_H 1
-
-/* Define to 1 if you have the <sys/types.h> header file. */
-#define HAVE_SYS_TYPES_H 1
-
-/* Define to 1 if you have <sys/wait.h> that is POSIX.1 compatible. */
-#define HAVE_SYS_WAIT_H 1
-
-/* Define to 1 if you have the `timegm' function. */
-#define HAVE_TIMEGM 1
-
-/* Define to 1 if you have the `times' function. */
-#define HAVE_TIMES 1
-
-/* Define to 1 if you have the <unistd.h> header file. */
-#define HAVE_UNISTD_H 1
-
-/* Root directory of the Apache install area */
-/* #define HTTPD_ROOT "/Users/username/apache2" */
-
-/* Define to the address where bug reports for this package should be sent. */
-#define PACKAGE_BUGREPORT ""
-
-/* Define to the full name of this package. */
-#define PACKAGE_NAME ""
-
-/* Define to the full name and version of this package. */
-#define PACKAGE_STRING ""
-
-/* Define to the one symbol short name of this package. */
-#define PACKAGE_TARNAME ""
-
-/* Define to the home page for this package. */
-#define PACKAGE_URL ""
-
-/* Define to the version of this package. */
-#define PACKAGE_VERSION ""
-
-/* Location of the config file, relative to the Apache root directory */
-#define SERVER_CONFIG_FILE "conf/httpd.conf"
-
-/* This platform doesn't suffer from the thundering herd problem */
-#define SINGLE_LISTEN_UNSERIALIZED_ACCEPT 1
-
-/* Define to 1 if you have the ANSI C header files. */
-#define STDC_HEADERS 1
-
-/* Path to suexec binary */
-/* #undef SUEXEC_BIN */
-
-/* Enable extensions on AIX 3, Interix. */
-#ifndef _ALL_SOURCE
-# define _ALL_SOURCE 1
-#endif
-/* Enable GNU extensions on systems that have them. */
-#ifndef _GNU_SOURCE
-# define _GNU_SOURCE 1
-#endif
-/* Enable threading extensions on Solaris. */
-#ifndef _POSIX_PTHREAD_SEMANTICS
-# define _POSIX_PTHREAD_SEMANTICS 1
-#endif
-/* Enable extensions on HP NonStop. */
-#ifndef _TANDEM_SOURCE
-# define _TANDEM_SOURCE 1
-#endif
-/* Enable general extensions on Solaris. */
-#ifndef __EXTENSIONS__
-# define __EXTENSIONS__ 1
-#endif
-
-
-/* Define to 1 if on MINIX. */
-/* #undef _MINIX */
-
-/* Define to 2 if the system does not provide POSIX.1 features except with
- this defined. */
-/* #undef _POSIX_1_SOURCE */
-
-/* Define to 1 if you need to in order for `stat' and other things to work. */
-/* #undef _POSIX_SOURCE */
-
-/* Define to empty if `const' does not conform to ANSI C. */
-/* #undef const */
-
-/* Define to 'int' if <sys/resource.h> doesn't define it for us */
-/* #undef rlim_t */
+++ /dev/null
-/* Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**
- * @file ap_config_layout.h
- * @brief Apache Config Layout
- */
-
-#ifndef AP_CONFIG_LAYOUT_H
-#define AP_CONFIG_LAYOUT_H
-
-/* Configured Apache directory layout */
-/*
-#define DEFAULT_PREFIX "/Users/username/apache2"
-#define DEFAULT_EXP_EXEC_PREFIX "/Users/username/apache2"
-#define DEFAULT_REL_EXEC_PREFIX ""
-#define DEFAULT_EXP_BINDIR "/Users/username/apache2/bin"
-#define DEFAULT_REL_BINDIR "bin"
-#define DEFAULT_EXP_SBINDIR "/Users/username/apache2/bin"
-#define DEFAULT_REL_SBINDIR "bin"
-#define DEFAULT_EXP_LIBEXECDIR "/Users/username/apache2/modules"
-#define DEFAULT_REL_LIBEXECDIR "modules"
-#define DEFAULT_EXP_MANDIR "/Users/username/apache2/man"
-#define DEFAULT_REL_MANDIR "man"
-#define DEFAULT_EXP_SYSCONFDIR "/Users/username/apache2/conf"
-#define DEFAULT_REL_SYSCONFDIR "conf"
-#define DEFAULT_EXP_DATADIR "/Users/username/apache2"
-#define DEFAULT_REL_DATADIR ""
-#define DEFAULT_EXP_INSTALLBUILDDIR "/Users/username/apache2/build"
-#define DEFAULT_REL_INSTALLBUILDDIR "build"
-#define DEFAULT_EXP_ERRORDIR "/Users/username/apache2/error"
-#define DEFAULT_REL_ERRORDIR "error"
-#define DEFAULT_EXP_ICONSDIR "/Users/username/apache2/icons"
-#define DEFAULT_REL_ICONSDIR "icons"
-#define DEFAULT_EXP_HTDOCSDIR "/Users/username/apache2/htdocs"
-#define DEFAULT_REL_HTDOCSDIR "htdocs"
-#define DEFAULT_EXP_MANUALDIR "/Users/username/apache2/manual"
-#define DEFAULT_REL_MANUALDIR "manual"
-#define DEFAULT_EXP_CGIDIR "/Users/username/apache2/cgi-bin"
-#define DEFAULT_REL_CGIDIR "cgi-bin"
-#define DEFAULT_EXP_INCLUDEDIR "/Users/username/apache2/include"
-#define DEFAULT_REL_INCLUDEDIR "include"
-#define DEFAULT_EXP_LOCALSTATEDIR "/Users/username/apache2"
-#define DEFAULT_REL_LOCALSTATEDIR ""
-#define DEFAULT_EXP_RUNTIMEDIR "/Users/username/apache2/logs"
-#define DEFAULT_REL_RUNTIMEDIR "logs"
-#define DEFAULT_EXP_LOGFILEDIR "/Users/username/apache2/logs"
-#define DEFAULT_REL_LOGFILEDIR "logs"
-#define DEFAULT_EXP_PROXYCACHEDIR "/Users/username/apache2/proxy"
-#define DEFAULT_REL_PROXYCACHEDIR "proxy"
-*/
-
-#endif /* AP_CONFIG_LAYOUT_H */
+++ /dev/null
-# 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': {
- 'apache_root': '<(DEPTH)/third_party/apache/httpd',
- 'apache_src_root': '<(apache_root)/src',
- 'apache_gen_os_root': '<(apache_root)/gen/arch/<(OS)',
- 'apache_gen_arch_root': '<(apache_gen_os_root)/<(target_arch)',
- 'system_include_path_httpd%': '/usr/include/apache2',
- 'conditions': [
- ['OS!="win"', {
- 'apache_os_include': '<(apache_src_root)/os/unix',
- }, { # else, OS=="win"
- 'apache_os_include': '<(apache_src_root)/os/win32',
- }]
- ],
- },
- 'conditions': [
- ['use_system_apache_dev==0', {
- 'targets': [
- {
- 'target_name': 'include',
- 'type': 'none',
- 'direct_dependent_settings': {
- 'include_dirs': [
- '<(apache_src_root)/include',
- '<(apache_os_include)',
- '<(apache_gen_arch_root)/include',
- ],
- },
- 'dependencies': [
- '<(DEPTH)/third_party/apache/apr/apr.gyp:include',
- '<(DEPTH)/third_party/apache/aprutil/aprutil.gyp:include',
- ],
- 'export_dependent_settings': [
- '<(DEPTH)/third_party/apache/apr/apr.gyp:include',
- '<(DEPTH)/third_party/apache/aprutil/aprutil.gyp:include',
- ],
- },
- ],
- }, {
- 'targets': [
- {
- 'target_name': 'include',
- 'type': 'none',
- 'direct_dependent_settings': {
- 'include_dirs': [
- '<(system_include_path_httpd)',
- ],
- },
- 'dependencies': [
- '<(DEPTH)/third_party/apache/apr/apr.gyp:include',
- '<(DEPTH)/third_party/apache/aprutil/aprutil.gyp:include',
- ],
- 'export_dependent_settings': [
- '<(DEPTH)/third_party/apache/apr/apr.gyp:include',
- '<(DEPTH)/third_party/apache/aprutil/aprutil.gyp:include',
- ],
- }
- ],
- }],
- ],
-}
+++ /dev/null
-/*
- mod_diagnostics
-
- Copyright (C) 2003, Nick Kew <nick@webthing.com>
-
- This is free software. You may use and redistribute it under
- the terms of the Apache License at
- http://www.apache.org/LICENSE.txt
-*/
-
-/*
- mod_diagnostics: print diagnostic and debug information on data
- (and metadata) passing through an Apache Filter chain.
-
- Insert a mod_diagnostics filter anywhere you want to watch traffic.
- See below for registered input and output filter names.
-
- Two filters are defined for each level, so that you can insert
- mod_diagnostics before and after any module you are investigating
- or debugging.
-*/
-
-#include <httpd.h>
-#include <http_config.h>
-#include <http_connection.h>
-#include <http_core.h>
-#include <http_log.h>
-
-module AP_MODULE_DECLARE_DATA diagnostic_filter_module ;
-
-static void diagnostic_log(ap_filter_t* f, apr_bucket* b) {
- const char* t ;
-
- if ( APR_BUCKET_IS_METADATA(b) )
- t = "(metadata)" ;
- else
- t = "(data)" ;
-
- if ( b->type == &apr_bucket_type_flush )
- t = "FLUSH" ;
- else if ( b->type == &apr_bucket_type_eos )
- t = "EOS" ;
- else if ( b->type == &apr_bucket_type_file )
- t = "FILE" ;
- else if ( b->type == &apr_bucket_type_pipe )
- t = "PIPE" ;
- else if ( b->type == &apr_bucket_type_socket )
- t = "SOCKET" ;
- else if ( b->type == &apr_bucket_type_heap )
- t = "HEAP" ;
- else if ( b->type == &apr_bucket_type_transient )
- t = "TRANSIENT" ;
- else if ( b->type == &apr_bucket_type_immortal )
- t = "IMMORTAL" ;
- else if ( b->type == &apr_bucket_type_mmap )
- t = "MMAP" ;
- else if ( b->type == &apr_bucket_type_pool )
- t = "POOL" ;
-
-/* use the connection pool, so it works with all filter types
- (Request may not be valid in a connection or network filter)
-
- This doesn't work with APLOG_DEBUG (looks like a bug in log.c
- around line 409 in 2.0.44), so we use APLOG_NOTICE. This is
- worth updating if httpd gets fixed.
-*/
- ap_log_perror(APLOG_MARK, APLOG_NOTICE, APR_SUCCESS, f->c->pool,
- " %s %s: %d bytes", f->frec->name, t, b->length) ;
-}
-static int diagnostic_ofilter (ap_filter_t* f, apr_bucket_brigade* bb) {
- apr_bucket* b ;
-
- ap_log_perror(APLOG_MARK, APLOG_NOTICE, APR_SUCCESS, f->c->pool, f->frec->name) ;
-
- for ( b = APR_BRIGADE_FIRST(bb) ;
- b != APR_BRIGADE_SENTINEL(bb) ;
- b = APR_BUCKET_NEXT(b) )
- diagnostic_log(f, b) ;
-
- return ap_pass_brigade(f->next, bb) ;
-}
-static const char* getmode(ap_input_mode_t mode) {
- switch ( mode ) {
- case AP_MODE_READBYTES: return "READBYTES" ;
- case AP_MODE_GETLINE: return "GETLINE" ;
- case AP_MODE_EATCRLF: return "EATCRLF" ;
- case AP_MODE_SPECULATIVE: return "SPECULATIVE" ;
- case AP_MODE_EXHAUSTIVE: return "EXHAUSTIVE" ;
- case AP_MODE_INIT: return "INIT" ;
- }
- return "(unknown)" ;
-}
-#define gettype(block) ((block) == APR_BLOCK_READ) ? "blocking" : "non-blocking"
-static int diagnostic_ifilter (ap_filter_t* f, apr_bucket_brigade* bb,
- ap_input_mode_t mode, apr_read_type_e block, apr_off_t readbytes) {
-
- apr_bucket* b ;
- apr_status_t ret ;
-
- ap_log_perror(APLOG_MARK, APLOG_NOTICE, APR_SUCCESS, f->c->pool,
- "%s: mode %s; %s; %d bytes", f->frec->name,
- getmode(mode), gettype(block), readbytes) ;
-
- if ( ret = ap_get_brigade(f->next, bb, mode, block, readbytes) ,
- ret == APR_SUCCESS )
- for ( b = APR_BRIGADE_FIRST(bb) ;
- b != APR_BRIGADE_SENTINEL(bb) ;
- b = APR_BUCKET_NEXT(b) )
- diagnostic_log(f, b) ;
- else
- ap_log_perror(APLOG_MARK, APLOG_NOTICE, APR_SUCCESS, f->c->pool,
- "%s: ap_get_brigade returned %d", f->frec->name, ret) ;
-
- return ret ;
-}
-
-
-#define ofilter_init NULL
-#define ifilter_init NULL
-
-/**
- * Invoked once per connection. See http_connection.h for details.
- */
-int diagnostic_pre_connection_hook(conn_rec *c, void *csd) {
- ap_log_cerror(APLOG_MARK,
- APLOG_NOTICE,
- APR_SUCCESS,
- c,
- "%ld Registering diagnostic filters", c->id);
-
- ap_add_input_filter("i-connection-1", NULL, NULL, c);
- ap_add_input_filter("i-connection-2", NULL, NULL, c);
- ap_add_output_filter("o-connection-1", NULL, NULL, c);
- //ap_add_input_filter("i-transcode-1", NULL, NULL, c);
- //ap_add_input_filter("i-protocol-1", NULL, NULL, c);
- // ap_add_output_filter(g_spdy_output_filter, builder, NULL, c);
-
- return APR_SUCCESS;
-}
-
-static void diagnostic_hooks(apr_pool_t* p) {
- ap_hook_pre_connection(
- diagnostic_pre_connection_hook,
- NULL,
- NULL,
- APR_HOOK_MIDDLE);
-/* by registering twice under each phase, we can insert filters
- BEFORE and AFTER one we are debugging, and distinguish between them
-
- I don't think this makes much sense at the network level, but
- we'll do it anyway: nothing to lose!
-*/
- ap_register_output_filter("o-resource-1", diagnostic_ofilter,
- ofilter_init, AP_FTYPE_RESOURCE) ;
- ap_register_output_filter("o-resource-2", diagnostic_ofilter,
- ofilter_init, AP_FTYPE_RESOURCE) ;
- ap_register_output_filter("o-content-1", diagnostic_ofilter,
- ofilter_init, AP_FTYPE_CONTENT_SET) ;
- ap_register_output_filter("o-content-2", diagnostic_ofilter,
- ofilter_init, AP_FTYPE_CONTENT_SET) ;
- ap_register_output_filter("o-protocol-1", diagnostic_ofilter,
- ofilter_init, AP_FTYPE_PROTOCOL) ;
- ap_register_output_filter("o-protocol-2", diagnostic_ofilter,
- ofilter_init, AP_FTYPE_PROTOCOL) ;
- ap_register_output_filter("o-transcode-1", diagnostic_ofilter,
- ofilter_init, AP_FTYPE_TRANSCODE) ;
- ap_register_output_filter("o-transcode-2", diagnostic_ofilter,
- ofilter_init, AP_FTYPE_TRANSCODE) ;
- ap_register_output_filter("o-connection-1", diagnostic_ofilter,
- ofilter_init, AP_FTYPE_CONNECTION) ;
- ap_register_output_filter("o-connection-2", diagnostic_ofilter,
- ofilter_init, AP_FTYPE_CONNECTION) ;
- ap_register_output_filter("o-network-1", diagnostic_ofilter,
- ofilter_init, AP_FTYPE_NETWORK) ;
- ap_register_output_filter("o-network-2", diagnostic_ofilter,
- ofilter_init, AP_FTYPE_NETWORK) ;
-
- ap_register_input_filter("i-resource-1", diagnostic_ifilter,
- ifilter_init, AP_FTYPE_RESOURCE) ;
- ap_register_input_filter("i-resource-2", diagnostic_ifilter,
- ifilter_init, AP_FTYPE_RESOURCE) ;
- ap_register_input_filter("i-content-1", diagnostic_ifilter,
- ifilter_init, AP_FTYPE_CONTENT_SET) ;
- ap_register_input_filter("i-content-2", diagnostic_ifilter,
- ifilter_init, AP_FTYPE_CONTENT_SET) ;
- ap_register_input_filter("i-protocol-1", diagnostic_ifilter,
- ifilter_init, AP_FTYPE_PROTOCOL) ;
- ap_register_input_filter("i-protocol-2", diagnostic_ifilter,
- ifilter_init, AP_FTYPE_PROTOCOL) ;
- ap_register_input_filter("i-transcode-1", diagnostic_ifilter,
- ifilter_init, AP_FTYPE_TRANSCODE) ;
- ap_register_input_filter("i-transcode-2", diagnostic_ifilter,
- ifilter_init, AP_FTYPE_TRANSCODE) ;
- ap_register_input_filter("i-connection-1", diagnostic_ifilter,
- ifilter_init, AP_FTYPE_CONNECTION) ;
- ap_register_input_filter("i-connection-2", diagnostic_ifilter,
- ifilter_init, AP_FTYPE_CONNECTION + 8) ;
- ap_register_input_filter("i-network-1", diagnostic_ifilter,
- ifilter_init, AP_FTYPE_NETWORK) ;
- ap_register_input_filter("i-network-2", diagnostic_ifilter,
- ifilter_init, AP_FTYPE_NETWORK) ;
-}
-
-// 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
-
-module AP_MODULE_DECLARE_DATA diagnostic_filter_module = {
- STANDARD20_MODULE_STUFF,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- diagnostic_hooks
-} ;
-
-#if defined(__linux)
-#pragma GCC visibility pop
-#endif
+++ /dev/null
-# 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.
-
-{
- 'targets': [
- {
- 'target_name': 'mod_diagnostics',
- 'type': 'loadable_module',
- 'dependencies': [
- '<(DEPTH)/third_party/apache/httpd/httpd.gyp:include',
- ],
- 'include_dirs': [
- '<(DEPTH)',
- ],
- 'sources': [
- 'mod_diagnostics.c',
- ],
- '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':'',
- }
- }]],
- },
- ],
-}