1/* Licensed to the Apache Software Foundation (ASF) under one or more 2 * contributor license agreements. See the NOTICE file distributed with 3 * this work for additional information regarding copyright ownership. 4 * The ASF licenses this file to You under the Apache License, Version 2.0 5 * (the "License"); you may not use this file except in compliance with 6 * the License. You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17#include "ap_config.h" 18#include "ap_mmn.h" 19#include "httpd.h" 20#include "http_config.h" 21#include "http_connection.h" 22 23#include "apr_buckets.h" 24#include "util_filter.h" 25 26module AP_MODULE_DECLARE_DATA echo_module; 27 28typedef struct { 29 int bEnabled; 30} EchoConfig; 31 32static void *create_echo_server_config(apr_pool_t *p, server_rec *s) 33{ 34 EchoConfig *pConfig = apr_pcalloc(p, sizeof *pConfig); 35 36 pConfig->bEnabled = 0; 37 38 return pConfig; 39} 40 41static const char *echo_on(cmd_parms *cmd, void *dummy, int arg) 42{ 43 EchoConfig *pConfig = ap_get_module_config(cmd->server->module_config, 44 &echo_module); 45 pConfig->bEnabled = arg; 46 47 return NULL; 48} 49 50static int process_echo_connection(conn_rec *c) 51{ 52 apr_bucket_brigade *bb; 53 apr_bucket *b; 54 apr_status_t rv; 55 EchoConfig *pConfig = ap_get_module_config(c->base_server->module_config, 56 &echo_module); 57 58 if (!pConfig->bEnabled) { 59 return DECLINED; 60 } 61 62 do { 63 bb = apr_brigade_create(c->pool, c->bucket_alloc); 64 65 /* Get a single line of input from the client */ 66 if (((rv = ap_get_brigade(c->input_filters, bb, AP_MODE_GETLINE, 67 APR_BLOCK_READ, 0)) != APR_SUCCESS) || 68 APR_BRIGADE_EMPTY(bb)) { 69 apr_brigade_destroy(bb); 70 break; 71 } 72 73 /* Make sure the data is flushed to the client */ 74 b = apr_bucket_flush_create(c->bucket_alloc); 75 APR_BRIGADE_INSERT_TAIL(bb, b); 76 77 /* Send back the data. */ 78 rv = ap_pass_brigade(c->output_filters, bb); 79 } while (rv == APR_SUCCESS); 80 81 return OK; 82} 83 84static const command_rec echo_cmds[] = 85{ 86 AP_INIT_FLAG("ProtocolEcho", echo_on, NULL, RSRC_CONF, 87 "Run an echo server on this host"), 88 { NULL } 89}; 90 91static void register_hooks(apr_pool_t *p) 92{ 93 ap_hook_process_connection(process_echo_connection, NULL, NULL, 94 APR_HOOK_MIDDLE); 95} 96 97module AP_MODULE_DECLARE_DATA echo_module = { 98 STANDARD20_MODULE_STUFF, 99 NULL, /* create per-directory config structure */ 100 NULL, /* merge per-directory config structures */ 101 create_echo_server_config, /* create per-server config structure */ 102 NULL, /* merge per-server config structures */ 103 echo_cmds, /* command apr_table_t */ 104 register_hooks /* register hooks */ 105}; 106