Skip to content

Commit

Permalink
deepcgi apache module complete. Fixed build issues, and added comments.
Browse files Browse the repository at this point in the history
Fixed persistent connection bug, removed unneeded imports and renamed module to mod_deepcgi.
Use pre-processor directive for replayserver binary name.
Removed all references to mod_env and mod_cgi.
  • Loading branch information
deepakn94 committed Oct 16, 2015
1 parent fdb2128 commit 5ce2f0b
Show file tree
Hide file tree
Showing 10 changed files with 182 additions and 30 deletions.
12 changes: 11 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
*.a
*.o
*.lo
*.la
*.slo
.deps
Makefile
Makefile.in
Expand All @@ -10,14 +13,20 @@ Makefile.in
/autom4te.cache
/config.h
/config.h.in
/config.h.in~
/config.log
/config.status
/config.guess
/config.sub
/configure
/depcomp
/install-sh
/missing
/mahimahi-*.tar.gz
/stamp-h1
/libtool
/ltmain.sh
/m4/

compile
src/protobufs/http_record.pb.cc
Expand All @@ -29,4 +38,5 @@ src/frontend/mm-onoff
src/frontend/mm-meter
src/frontend/mm-webrecord
src/frontend/mm-webreplay
src/frontend/nph-replayserver.cgi
src/frontend/mm-replayserver
src/frontend/.libs
1 change: 1 addition & 0 deletions Makefile.am
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
ACLOCAL_AMFLAGS = -I m4
SUBDIRS = src man traces scripts
33 changes: 15 additions & 18 deletions configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ AM_INIT_AUTOMAKE([foreign])
AC_CONFIG_SRCDIR([src/frontend/delayshell.cc])
AC_CONFIG_HEADERS([config.h])

LT_INIT
AC_CONFIG_MACRO_DIR([m4])

# Add picky CXXFLAGS
CXX11_FLAGS="-std=c++11 -pthread"
PICKY_CXXFLAGS="-pedantic -Wall -Wextra -Weffc++ -Werror"
Expand All @@ -15,7 +18,6 @@ AC_SUBST([PICKY_CXXFLAGS])

# Checks for programs.
AC_PROG_CXX
AC_PROG_RANLIB

AC_ARG_VAR([IPTABLES], [path to iptables])
AC_PATH_PROG([IPTABLES], [iptables], [no], [$PATH$PATH_SEPARATOR/sbin$PATH_SEPARATOR/usr/sbin$PATH_SEPARATOR/bin$PATH_SEPARATOR/usr/bin])
Expand Down Expand Up @@ -53,6 +55,14 @@ AC_CHECK_FILE([/usr/lib/apache2], [APACHE_NAME="apache2"],
[AC_CHECK_FILE([/usr/lib/httpd], [APACHE_NAME="httpd"],
[AC_MSG_ERROR([apache module directory not found])])])

AC_CHECK_FILE(
[/usr/include/apache2],
[AC_SUBST([APACHE2_INCLUDE], [/usr/include/apache2])],
[AC_MSG_ERROR([apache2-dev is required])]
)

AC_SUBST([APR_INCLUDE], [/usr/include/apr-1.0])

# Checks for apache configuration modules
AC_CHECK_FILE([/usr/lib/$APACHE_NAME/modules/mod_dir.so], [],
[AC_MSG_ERROR([apache2 mod_dir.so is required])])
Expand All @@ -74,21 +84,6 @@ AC_CHECK_FILE([/usr/lib/$APACHE_NAME/modules/mod_authz_core.so], [],

AC_DEFINE_UNQUOTED([MOD_AUTHZ_CORE], ["/usr/lib/$APACHE_NAME/modules/mod_authz_core.so"], [path to apache2 mod_authz_core])

AC_CHECK_FILE([/usr/lib/$APACHE_NAME/modules/mod_cgi.so], [],
[AC_MSG_ERROR([apache2 mod_cgi.so is required])])

AC_DEFINE_UNQUOTED([MOD_CGI], ["/usr/lib/$APACHE_NAME/modules/mod_cgi.so"], [path to apache2 mod_cgi])

AC_CHECK_FILE([/usr/lib/$APACHE_NAME/modules/mod_rewrite.so], [],
[AC_MSG_ERROR([apache2 mod_rewrite.so is required])])

AC_DEFINE_UNQUOTED([MOD_REWRITE], ["/usr/lib/$APACHE_NAME/modules/mod_rewrite.so"], [path to apache2 mod_rewrite])

AC_CHECK_FILE([/usr/lib/$APACHE_NAME/modules/mod_env.so], [],
[AC_MSG_ERROR([apache2 mod_env.so is required])])

AC_DEFINE_UNQUOTED([MOD_ENV], ["/usr/lib/$APACHE_NAME/modules/mod_env.so"], [path to apache2 mod_env])

AC_CHECK_FILE([/usr/lib/$APACHE_NAME/modules/mod_ssl.so], [],
[AC_MSG_ERROR([apache2 mod_ssl.so is required])])

Expand All @@ -102,11 +97,13 @@ AC_DEFINE_UNQUOTED([MOD_SSL_CERTIFICATE_FILE], ["/etc/ssl/certs/ssl-cert-snakeoi

AC_DEFINE_UNQUOTED([MOD_SSL_KEY], ["/etc/ssl/private/ssl-cert-snakeoil.key"], [path to ssl key])

# Set path to replayshell cgi script
# Set path to mm-replayserver script
if test "${prefix}" = "NONE"; then
prefix=$ac_default_prefix
fi
AC_DEFINE_UNQUOTED([REPLAYSERVER], ["${prefix}/bin/nph-replayserver.cgi"], [path to nph-replayserver.cgi])
AC_DEFINE_UNQUOTED([REPLAYSERVER], ["${prefix}/bin/mm-replayserver"], [path to mm-replayserver])

AC_DEFINE_UNQUOTED([MOD_DEEPCGI], ["${prefix}/lib/libmod_deepcgi.so"], [path to apache2 mod_deepcgi])

# Set path to directory with installed executable programs
AC_DEFINE_UNQUOTED([EXEC_DIR], ["${prefix}/bin/"], [path to directory with installed executable programs])
Expand Down
2 changes: 1 addition & 1 deletion man/Makefile.am
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
dist_man_MANS = mahimahi.1 mm-link.1 nph-replayserver.cgi.1
dist_man_MANS = mahimahi.1 mm-link.1 mm-replayserver.1

# the rest just link to one of the above
dist_man_MANS += mm-delay.1
Expand Down
6 changes: 3 additions & 3 deletions man/nph-replayserver.cgi.1 → man/mm-replayserver.1
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
.\" First parameter, NAME, should be all caps
.\" Second parameter, SECTION, should be 1-8, maybe w/ subsection
.\" other parameters are allowed: see man(7), man(1)
.TH NPH-REPLAYSERVER 1 "March 2015"
.TH MM-REPLAYSERVER 1 "March 2015"
.\" Please adjust this date whenever revising the manpage.
.\"
.\" Some roff macros, for reference:
Expand All @@ -16,12 +16,12 @@
.\" .sp <n> insert n+1 empty lines
.\" for manpage-specific macros, see man(7)
.SH NAME
\fBnph-replayserver.cgi\fP \- helper program used by
\fBmm-replayserver\fP \- helper program used by
.BR mm-webreplay (1).

.SH DESCRIPTION

nph-replayserver.cgi is a CGI program that replies to previously-saved
mm-replayserver is a program that replies to previously-saved
HTTP requests with the corresponding HTTP response. See
.BR mm-webreplay (1).

Expand Down
13 changes: 9 additions & 4 deletions src/frontend/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,15 @@ mm_webreplay_SOURCES = replayshell.cc web_server.hh web_server.cc
mm_webreplay_LDADD = -lrt ../util/libutil.a ../http/libhttp.a ../protobufs/libhttprecordprotos.a $(protobuf_LIBS)
mm_webreplay_LDFLAGS = -pthread

bin_PROGRAMS += nph-replayserver.cgi
nph_replayserver_cgi_SOURCES = replayserver.cc
nph_replayserver_cgi_LDADD = -lrt ../util/libutil.a ../http/libhttp.a ../protobufs/libhttprecordprotos.a $(protobuf_LIBS)
nph_replayserver_cgi_LDFLAGS = -pthread
bin_PROGRAMS += mm-replayserver
mm_replayserver_SOURCES = replayserver.cc
mm_replayserver_LDADD = -lrt ../util/libutil.a ../http/libhttp.a ../protobufs/libhttprecordprotos.a $(protobuf_LIBS)
mm_replayserver_LDFLAGS = -pthread

lib_LTLIBRARIES = libmod_deepcgi.la
libmod_deepcgi_la_SOURCES = mod_deepcgi.c replayserver_filename.cc
libmod_deepcgi_la_CFLAGS = -I@APACHE2_INCLUDE@ -I@APR_INCLUDE@
libmod_deepcgi_la_CPPFLAGS = # empty

install-exec-hook:
chown root $(DESTDIR)$(bindir)/mm-delay
Expand Down
136 changes: 136 additions & 0 deletions src/frontend/mod_deepcgi.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
#include <stdio.h>

#include "httpd.h"
#include "http_core.h"
#include "http_protocol.h"

extern const char* replayserver_filename;

static void deepcgi_hooks( apr_pool_t* inpPool );
static int deepcgi_handler( request_rec* inpRequest );

typedef struct {
const char* working_dir;
const char* recording_dir;
} deepcgi_config;

static deepcgi_config config;

// ============================================================================
// Methods for reading configuration parameters
// ============================================================================

const char* deepcgi_set_workingdir(cmd_parms* cmd, void* cfg, const char* arg) {
config.working_dir = arg;
return NULL;
}

const char* deepcgi_set_recordingdir(cmd_parms* cmd, void* cfg, const char* arg) {
config.recording_dir = arg;
return NULL;
}

// ============================================================================
// Directives to read configuration parameters
// ============================================================================

static const command_rec deepcgi_directives[] =
{
AP_INIT_TAKE1( "workingDir", deepcgi_set_workingdir, NULL, RSRC_CONF, "Working directory" ),
AP_INIT_TAKE1( "recordingDir", deepcgi_set_recordingdir, NULL, RSRC_CONF, "Recording directory" ),
{ NULL }
};

// ============================================================================
// Module definition
// ============================================================================

module AP_MODULE_DECLARE_DATA deepcgi_module =
{
STANDARD20_MODULE_STUFF,
NULL,
NULL,
NULL,
NULL,
deepcgi_directives,
deepcgi_hooks
};

// ============================================================================
// Module handler function
// ============================================================================

int deepcgi_handler( request_rec* inpRequest )
{
if ( !inpRequest->handler || strcmp( inpRequest->handler, "deepcgi-handler" ))
{
return DECLINED;
}

const char* request_method = inpRequest->method;
const char* request_uri = inpRequest->unparsed_uri;
const char* protocol = inpRequest->protocol;
const char* http_host = inpRequest->hostname;
const char* user_agent = apr_table_get( inpRequest->headers_in, "User-Agent" );

setenv( "MAHIMAHI_CHDIR", config.working_dir, TRUE );
setenv( "MAHIMAHI_RECORD_PATH", config.recording_dir, TRUE );
setenv( "REQUEST_METHOD", request_method, TRUE );
setenv( "REQUEST_URI", request_uri, TRUE );
setenv( "SERVER_PROTOCOL", protocol, TRUE );
setenv( "HTTP_HOST", http_host, TRUE );
if ( user_agent != NULL ) {
setenv( "HTTP_USER_AGENT", user_agent, TRUE );
}

FILE* fp = popen( replayserver_filename, "r" );
if ( fp == NULL ) {
// "Error encountered while running script"
return HTTP_INTERNAL_SERVER_ERROR;
}

char line[HUGE_STRING_LEN];
struct ap_filter_t *cur;

// Get rid of all filters up through protocol...since we
// haven't parsed off the headers, there is no way they can
// work
cur = inpRequest->proto_output_filters;
while (cur && cur->frec->ftype < AP_FTYPE_CONNECTION) {
cur = cur->next;
}
inpRequest->output_filters = inpRequest->proto_output_filters = cur;

// Write headers + body
int num_bytes_read;
do {
num_bytes_read = fread( line, sizeof(char), HUGE_STRING_LEN, fp );
int num_bytes_left = num_bytes_read;
while ( num_bytes_left > 0 ) {
int offset = num_bytes_read - num_bytes_left;
int num_bytes_written = ap_rwrite( line + offset, num_bytes_left, inpRequest );
if ( num_bytes_written == -1 ) {
// "Error encountered while writing"
return HTTP_INTERNAL_SERVER_ERROR;
}
num_bytes_left -= num_bytes_written;
}
} while ( num_bytes_read == HUGE_STRING_LEN );

// To ensure that connection is kept-alive
ap_set_keepalive( inpRequest );

pclose( fp );

return OK;
}

// ============================================================================
// Definition of hook for handler
// ============================================================================

void deepcgi_hooks( apr_pool_t* inpPool )
{
ap_hook_handler( deepcgi_handler, NULL, NULL, APR_HOOK_LAST );
}

3 changes: 3 additions & 0 deletions src/frontend/replayserver_filename.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
#include "config.h"

const char *replayserver_filename = REPLAYSERVER;
4 changes: 2 additions & 2 deletions src/frontend/web_server.cc
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@ WebServer::WebServer( const Address & addr, const string & working_directory, co
{
config_file_.write( apache_main_config );

config_file_.write( "SetEnv MAHIMAHI_CHDIR " + working_directory + "\n" );
config_file_.write( "SetEnv MAHIMAHI_RECORD_PATH " + record_path + "\n" );
config_file_.write( "WorkingDir " + working_directory + "\n" );
config_file_.write( "RecordingDir " + record_path + "\n" );

/* if port 443, add ssl components */
if ( addr.port() == 443 ) { /* ssl */
Expand Down
2 changes: 1 addition & 1 deletion src/httpserver/apache_configuration.hh
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
#ifndef APACHE_CONFIGURATION_HH
#define APACHE_CONFIGURATION_HH

const std::string apache_main_config = "LoadModule dir_module " + std::string( MOD_DIR ) + "\nLoadModule mpm_prefork_module " + std::string( MOD_MPM_PREFORK ) + "\nLoadModule mime_module " + std::string( MOD_MIME ) + "\n<IfModule mod_mime.c>\nTypesConfig /etc/mime.types\nAddHandler cgi-script .cgi\n</IfModule>\nLoadModule authz_core_module " + std::string( MOD_AUTHZ_CORE ) + "\nLoadModule cgi_module " + std::string( MOD_CGI ) + "\nMutex pthread\n<Directory " + std::string( EXEC_DIR ) + ">\nAllowOverride None\nOptions +ExecCGI\nRequire all granted\n</Directory>\nLoadModule rewrite_module " + std::string( MOD_REWRITE ) + "\nRewriteEngine On\nRewriteRule ^(.*)$ " + std::string( REPLAYSERVER ) + "\nLoadModule env_module " + std::string( MOD_ENV ) + "\n";
const std::string apache_main_config = "LoadModule dir_module " + std::string( MOD_DIR ) + "\nLoadModule mpm_prefork_module " + std::string( MOD_MPM_PREFORK ) + "\nLoadModule mime_module " + std::string( MOD_MIME ) + "\n<IfModule mod_mime.c>\nTypesConfig /etc/mime.types\nLoadModule authz_core_module " + std::string( MOD_AUTHZ_CORE ) + "\nMutex pthread\n<Directory " + std::string( EXEC_DIR ) + ">\nAllowOverride None\nOptions +ExecCGI\nRequire all granted\n</Directory>\nLoadFile " + std::string( MOD_DEEPCGI ) + "\nLoadModule deepcgi_module " + std::string( MOD_DEEPCGI ) + "\nSetHandler deepcgi-handler\n";

const std::string apache_ssl_config = "LoadModule ssl_module " + std::string( MOD_SSL ) + "\nSSLEngine on\nSSLCertificateFile " + std::string( MOD_SSL_CERTIFICATE_FILE ) + "\nSSLCertificateKeyFile " + std::string( MOD_SSL_KEY ) +"\n";

Expand Down

0 comments on commit 5ce2f0b

Please sign in to comment.