summaryrefslogtreecommitdiffstats
path: root/sca-cpp/trunk/modules
diff options
context:
space:
mode:
Diffstat (limited to 'sca-cpp/trunk/modules')
-rw-r--r--sca-cpp/trunk/modules/http/Makefile.am15
-rw-r--r--sca-cpp/trunk/modules/http/curl-connect.cpp98
-rw-r--r--sca-cpp/trunk/modules/http/curl-get.cpp13
-rw-r--r--sca-cpp/trunk/modules/http/curl-test.cpp2
-rw-r--r--sca-cpp/trunk/modules/http/http.hpp (renamed from sca-cpp/trunk/modules/http/curl.hpp)283
-rwxr-xr-xsca-cpp/trunk/modules/http/httpd-addr54
-rwxr-xr-xsca-cpp/trunk/modules/http/httpd-auth-conf2
-rwxr-xr-xsca-cpp/trunk/modules/http/httpd-conf19
-rwxr-xr-xsca-cpp/trunk/modules/http/httpd-ssl-conf42
-rw-r--r--sca-cpp/trunk/modules/http/httpd.hpp169
-rw-r--r--sca-cpp/trunk/modules/http/mod-ssltunnel.cpp364
-rwxr-xr-xsca-cpp/trunk/modules/http/proxy-member-conf3
-rwxr-xr-xsca-cpp/trunk/modules/http/proxy-ssl-conf4
-rwxr-xr-xsca-cpp/trunk/modules/http/proxy-ssl-member-conf3
-rwxr-xr-xsca-cpp/trunk/modules/http/ssl-ca-conf32
-rwxr-xr-xsca-cpp/trunk/modules/http/ssl-cert-conf23
-rwxr-xr-xsca-cpp/trunk/modules/http/ssl-cert-find (renamed from sca-cpp/trunk/modules/http/ssl-ls)5
-rwxr-xr-xsca-cpp/trunk/modules/http/tunnel-ssl-conf56
-rwxr-xr-xsca-cpp/trunk/modules/http/vhost-conf15
-rwxr-xr-xsca-cpp/trunk/modules/http/vhost-ssl-conf16
-rw-r--r--sca-cpp/trunk/modules/json/json.hpp13
-rw-r--r--sca-cpp/trunk/modules/server/client-test.hpp2
-rw-r--r--sca-cpp/trunk/modules/server/mod-eval.hpp9
-rw-r--r--sca-cpp/trunk/modules/server/mod-wiring.cpp17
-rwxr-xr-xsca-cpp/trunk/modules/server/server-conf22
25 files changed, 1033 insertions, 248 deletions
diff --git a/sca-cpp/trunk/modules/http/Makefile.am b/sca-cpp/trunk/modules/http/Makefile.am
index 03f5c234f5..b17f774da2 100644
--- a/sca-cpp/trunk/modules/http/Makefile.am
+++ b/sca-cpp/trunk/modules/http/Makefile.am
@@ -20,7 +20,7 @@ INCLUDES = -I${HTTPD_INCLUDE}
incl_HEADERS = *.hpp
incldir = $(prefix)/include/modules/http
-dist_mod_SCRIPTS = httpd-conf httpd-start httpd-stop httpd-restart ssl-ca-conf ssl-cert-conf httpd-ssl-conf httpd-auth-conf proxy-conf proxy-ssl-conf proxy-member-conf proxy-ssl-member-conf vhost-conf vhost-ssl-conf
+dist_mod_SCRIPTS = httpd-conf httpd-start httpd-stop httpd-restart ssl-ca-conf ssl-cert-conf ssl-cert-find httpd-ssl-conf httpd-auth-conf proxy-conf proxy-ssl-conf proxy-member-conf proxy-ssl-member-conf vhost-conf vhost-ssl-conf tunnel-ssl-conf
moddir=$(prefix)/modules/http
curl_test_SOURCES = curl-test.cpp
@@ -29,6 +29,17 @@ curl_test_LDFLAGS = -lxml2 -lcurl -lmozjs
curl_get_SOURCES = curl-get.cpp
curl_get_LDFLAGS = -lxml2 -lcurl -lmozjs
+curl_connect_SOURCES = curl-connect.cpp
+curl_connect_LDFLAGS = -lxml2 -lcurl -lmozjs
+
+mod_LTLIBRARIES = libmod_tuscany_ssltunnel.la
+noinst_DATA = libmod_tuscany_ssltunnel.so
+
+libmod_tuscany_ssltunnel_la_SOURCES = mod-ssltunnel.cpp
+libmod_tuscany_ssltunnel_la_LDFLAGS = -lxml2 -lcurl -lmozjs
+libmod_tuscany_ssltunnel.so:
+ ln -s .libs/libmod_tuscany_ssltunnel.so
+
mod_DATA = httpd.prefix httpd-apachectl.prefix httpd-modules.prefix curl.prefix
nobase_dist_mod_DATA = conf/*
@@ -44,6 +55,6 @@ curl.prefix: $(top_builddir)/config.status
echo ${CURL_PREFIX} >curl.prefix
dist_noinst_SCRIPTS = httpd-test http-test proxy-test
-noinst_PROGRAMS = curl-test curl-get
+noinst_PROGRAMS = curl-test curl-get curl-connect
TESTS = httpd-test http-test proxy-test
diff --git a/sca-cpp/trunk/modules/http/curl-connect.cpp b/sca-cpp/trunk/modules/http/curl-connect.cpp
new file mode 100644
index 0000000000..8957fb01b0
--- /dev/null
+++ b/sca-cpp/trunk/modules/http/curl-connect.cpp
@@ -0,0 +1,98 @@
+/*
+ * 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.
+ */
+
+/* $Rev$ $Date$ */
+
+/**
+ * HTTP connect command line test tool.
+ */
+
+#include <assert.h>
+#include <stdio.h>
+#include "stream.hpp"
+#include "string.hpp"
+#include "perf.hpp"
+#include "http.hpp"
+
+namespace tuscany {
+namespace http {
+
+const bool testConnect(const string& url, const string& ca = "", const string& cert = "", const string& key = "") {
+ gc_scoped_pool p;
+
+ CURLSession cs(ca, cert, key);
+ const failable<bool> crc = connect(url, cs);
+ assert(hasContent(crc));
+
+ apr_pollset_t* pollset;
+ apr_status_t cprc = apr_pollset_create(&pollset, 2, pool(p), 0);
+ assert(cprc == APR_SUCCESS);
+ apr_socket_t* csock = sock(0, p);
+ const apr_pollfd_t* cpollfd = pollfd(csock, APR_POLLIN | APR_POLLERR | APR_POLLNVAL | APR_POLLHUP, p);
+ apr_pollset_add(pollset, cpollfd);
+ apr_socket_t* tsock = sock(cs);
+ const apr_pollfd_t* tpollfd = pollfd(tsock, APR_POLLIN | APR_POLLERR | APR_POLLNVAL | APR_POLLHUP, p);
+ apr_pollset_add(pollset, tpollfd);
+
+ const apr_pollfd_t* pollfds;
+ apr_int32_t pollcount;
+ for(;;) {
+ apr_status_t pollrc = apr_pollset_poll(pollset, -1, &pollcount, &pollfds);
+ assert(pollrc == APR_SUCCESS);
+
+ for (; pollcount > 0; pollcount--, pollfds++) {
+ if (pollfds->rtnevents & APR_POLLIN) {
+ char data[8192];
+ if (pollfds->desc.s == csock) {
+ const int rl = ::read(0, data, sizeof(data));
+ if (rl == -1)
+ return false;
+ if (rl > 0) {
+ const failable<bool> src = http::send(data, rl, cs);
+ assert(hasContent(src));
+ }
+ }
+ else {
+ const failable<int> frl = http::recv(data, sizeof(data), cs);
+ assert(hasContent(frl));
+ const int rl = content(frl);
+ if (rl == 0)
+ return true;
+ const int wl = ::write(0, data, rl);
+ assert(wl == rl);
+ }
+ continue;
+ }
+ assert(!(pollfds->rtnevents & (APR_POLLERR | APR_POLLHUP | APR_POLLNVAL)));
+ }
+ }
+ return true;
+}
+
+}
+}
+
+int main(unused const int argc, const char** argv) {
+ if (argc > 2)
+ tuscany::http::testConnect(tuscany::string(argv[1]), tuscany::string(argv[2]), tuscany::string(argv[3]), tuscany::string(argv[4]));
+ else
+ tuscany::http::testConnect(tuscany::string(argv[1]));
+ return 0;
+}
+
diff --git a/sca-cpp/trunk/modules/http/curl-get.cpp b/sca-cpp/trunk/modules/http/curl-get.cpp
index cbd693092a..4d5f1837fc 100644
--- a/sca-cpp/trunk/modules/http/curl-get.cpp
+++ b/sca-cpp/trunk/modules/http/curl-get.cpp
@@ -20,20 +20,20 @@
/* $Rev$ $Date$ */
/**
- * HTTP client command line test tool.
+ * HTTP GET command line test tool.
*/
#include <assert.h>
#include "stream.hpp"
#include "string.hpp"
#include "perf.hpp"
-#include "curl.hpp"
+#include "http.hpp"
namespace tuscany {
namespace http {
-const bool testGet(const string& url) {
- CURLSession ch;
+const bool testGet(const string& url, const string& ca = "", const string& cert = "", const string& key = "") {
+ CURLSession ch(ca, cert, key);
const failable<value> val = get(url, ch);
assert(hasContent(val));
cout << val << endl;
@@ -44,7 +44,10 @@ const bool testGet(const string& url) {
}
int main(unused const int argc, const char** argv) {
- tuscany::http::testGet(tuscany::string(argv[1]));
+ if (argc > 2)
+ tuscany::http::testGet(tuscany::string(argv[1]), tuscany::string(argv[2]), tuscany::string(argv[3]), tuscany::string(argv[4]));
+ else
+ tuscany::http::testGet(tuscany::string(argv[1]));
return 0;
}
diff --git a/sca-cpp/trunk/modules/http/curl-test.cpp b/sca-cpp/trunk/modules/http/curl-test.cpp
index c9b85ad962..1d1b07bff4 100644
--- a/sca-cpp/trunk/modules/http/curl-test.cpp
+++ b/sca-cpp/trunk/modules/http/curl-test.cpp
@@ -27,7 +27,7 @@
#include "stream.hpp"
#include "string.hpp"
#include "perf.hpp"
-#include "curl.hpp"
+#include "http.hpp"
namespace tuscany {
namespace http {
diff --git a/sca-cpp/trunk/modules/http/curl.hpp b/sca-cpp/trunk/modules/http/http.hpp
index 61f40eb475..b6de790028 100644
--- a/sca-cpp/trunk/modules/http/curl.hpp
+++ b/sca-cpp/trunk/modules/http/http.hpp
@@ -19,8 +19,8 @@
/* $Rev$ $Date$ */
-#ifndef tuscany_curl_hpp
-#define tuscany_curl_hpp
+#ifndef tuscany_http_hpp
+#define tuscany_http_hpp
/**
* CURL HTTP client functions.
@@ -30,6 +30,10 @@
#include <curl/curl.h>
#include <curl/types.h>
#include <curl/easy.h>
+#include <apr_network_io.h>
+#include <apr_portable.h>
+#include <apr_poll.h>
+
#include "string.hpp"
#include "gc.hpp"
#include "list.hpp"
@@ -59,10 +63,10 @@ public:
*/
class CURLSession {
public:
- CURLSession(const string& ca = "", const string& cert = "", const string& key = "") : h(curl_easy_init()), owner(true), ca(ca), cert(cert), key(key) {
+ CURLSession(const string& ca = "", const string& cert = "", const string& key = "") : h(curl_easy_init()), p(gc_pool(mkpool())), sock(NULL), wpollset(NULL), wpollfd(NULL), rpollset(NULL), rpollfd(NULL), owner(true), ca(ca), cert(cert), key(key) {
}
- CURLSession(const CURLSession& c) : h(c.h), owner(false), ca(c.ca), cert(c.cert), key(c.key) {
+ CURLSession(const CURLSession& c) : h(c.h), p(c.p), sock(c.sock), wpollset(c.wpollset), wpollfd(c.wpollfd), rpollset(c.rpollset), rpollfd(c.rpollfd), owner(false), ca(c.ca), cert(c.cert), key(c.key) {
}
~CURLSession() {
@@ -71,13 +75,24 @@ public:
if (h == NULL)
return;
curl_easy_cleanup(h);
+ destroy(p);
}
private:
CURL* h;
+ gc_pool p;
+ apr_socket_t* sock;
+ apr_pollset_t* wpollset;
+ apr_pollfd_t* wpollfd;
+ apr_pollset_t* rpollset;
+ apr_pollfd_t* rpollfd;
const bool owner;
- friend CURL* handle(const CURLSession& c);
+ friend CURL* handle(const CURLSession& cs);
+ friend apr_socket_t* sock(const CURLSession& cs);
+ friend const failable<bool> connect(const string& url, CURLSession& cs);
+ friend const failable<bool> send(const char* c, const int l, const CURLSession& cs);
+ friend const failable<int> recv(char* c, const int l, const CURLSession& cs);
public:
const string ca;
@@ -88,8 +103,80 @@ public:
/**
* Returns the CURL handle used by a CURL session.
*/
-CURL* handle(const CURLSession& c) {
- return c.h;
+CURL* handle(const CURLSession& cs) {
+ return cs.h;
+}
+
+/**
+ * Return an apr_socket_t for the socket used by a CURL session.
+ */
+apr_socket_t* sock(const CURLSession& cs) {
+ return cs.sock;
+}
+
+/**
+ * Convert a socket fd to an apr_socket_t.
+ */
+apr_socket_t* sock(const int sd, const gc_pool& p) {
+ int fd = sd;
+ apr_socket_t* s = NULL;
+ apr_os_sock_put(&s, &fd, pool(p));
+ return s;
+}
+
+/**
+ * Convert a CURL return code to an error string.
+ */
+const string curlreason(CURLcode rc) {
+ return curl_easy_strerror(rc);
+}
+
+/**
+ * Convert an APR status to an error string.
+ */
+const string apreason(apr_status_t rc) {
+ char buf[256];
+ return apr_strerror(rc, buf, sizeof(buf));
+}
+
+/**
+ * Setup a CURL session
+ */
+const failable<CURL*> setup(const string& url, const CURLSession& cs) {
+
+ // Init CURL session
+ CURL* ch = handle(cs);
+ curl_easy_reset(ch);
+ curl_easy_setopt(ch, CURLOPT_USERAGENT, "libcurl/1.0");
+
+ // Setup protocol options
+ curl_easy_setopt(ch, CURLOPT_TCP_NODELAY, true);
+ curl_easy_setopt(ch, CURLOPT_FOLLOWLOCATION, true);
+ curl_easy_setopt(ch, CURLOPT_POSTREDIR, CURL_REDIR_POST_ALL);
+
+ // Setup SSL options
+ if (cs.ca != "") {
+ debug(cs.ca, "http::apply::ca");
+ curl_easy_setopt(ch, CURLOPT_CAINFO, c_str(cs.ca));
+ curl_easy_setopt(ch, CURLOPT_SSL_VERIFYPEER, true);
+ curl_easy_setopt(ch, CURLOPT_SSL_VERIFYHOST, 2);
+ } else
+ curl_easy_setopt(ch, CURLOPT_SSL_VERIFYPEER, false);
+ if (cs.cert != "") {
+ debug(cs.cert, "http::apply::cert");
+ curl_easy_setopt(ch, CURLOPT_SSLCERT, c_str(cs.cert));
+ curl_easy_setopt(ch, CURLOPT_SSLCERTTYPE, "PEM");
+ }
+ if (cs.key != "") {
+ debug(cs.key, "http::apply::key");
+ curl_easy_setopt(ch, CURLOPT_SSLKEY, c_str(cs.key));
+ curl_easy_setopt(ch, CURLOPT_SSLKEYTYPE, "PEM");
+ }
+
+ // Set target URL
+ curl_easy_setopt(ch, CURLOPT_URL, c_str(url));
+
+ return ch;
}
/**
@@ -149,18 +236,25 @@ curl_slist* headers(curl_slist* cl, const list<string>& h) {
template<typename R> const failable<list<R> > apply(const list<list<string> >& hdr, const lambda<R(const string&, const R)>& reduce, const R& initial, const string& url, const string& verb, const CURLSession& cs) {
- // Init the curl session
- CURL* ch = handle(cs);
- curl_easy_reset(ch);
- curl_easy_setopt(ch, CURLOPT_USERAGENT, "libcurl/1.0");
+ // Setup the CURL session
+ const failable<CURL*> fch = setup(url, cs);
+ if (!hasContent(fch))
+ return mkfailure<list<R>>(reason(fch));
+ CURL* ch = content(fch);
+
+ // Set the request headers
+ curl_slist* hl = headers(NULL, car(hdr));
+ if (hl != NULL)
+ curl_easy_setopt(ch, CURLOPT_HTTPHEADER, hl);
- //TODO use HTTP chunking, for now just convert request to a single string
+ // Convert request body to a string
+ // TODO use HTTP chunking instead
ostringstream os;
write(cadr(hdr), os);
const string s = str(os);
const int sz = length(s);
- // Setup the read, header and write callbacks
+ // Setup the read, write header and write data callbacks
CURLReadContext rcx(mklist(s));
curl_easy_setopt(ch, CURLOPT_READFUNCTION, (size_t (*)(void*, size_t, size_t, void*))readCallback);
curl_easy_setopt(ch, CURLOPT_READDATA, &rcx);
@@ -171,36 +265,7 @@ template<typename R> const failable<list<R> > apply(const list<list<string> >& h
curl_easy_setopt(ch, CURLOPT_WRITEFUNCTION, (size_t (*)(void*, size_t, size_t, void*))(writeCallback<R>));
curl_easy_setopt(ch, CURLOPT_WRITEDATA, &wcx);
- // Setup protocol options
- curl_easy_setopt(ch, CURLOPT_TCP_NODELAY, true);
- curl_easy_setopt(ch, CURLOPT_FOLLOWLOCATION, true);
- curl_easy_setopt(ch, CURLOPT_POSTREDIR, CURL_REDIR_POST_ALL);
-
- // Setup SSL options
- if (cs.ca != "") {
- debug(cs.ca, "http::apply::ca");
- curl_easy_setopt(ch, CURLOPT_CAINFO, c_str(cs.ca));
- curl_easy_setopt(ch, CURLOPT_SSL_VERIFYPEER, true);
- curl_easy_setopt(ch, CURLOPT_SSL_VERIFYHOST, 2);
- }
- if (cs.cert != "") {
- debug(cs.cert, "http::apply::cert");
- curl_easy_setopt(ch, CURLOPT_SSLCERT, c_str(cs.cert));
- curl_easy_setopt(ch, CURLOPT_SSLCERTTYPE, "PEM");
- }
- if (cs.key != "") {
- debug(cs.key, "http::apply::key");
- curl_easy_setopt(ch, CURLOPT_SSLKEY, c_str(cs.key));
- curl_easy_setopt(ch, CURLOPT_SSLKEYTYPE, "PEM");
- }
-
- // Set the request headers
- curl_slist* hl = headers(NULL, car(hdr));
- if (hl != NULL)
- curl_easy_setopt(ch, CURLOPT_HTTPHEADER, hl);
-
// Apply the HTTP verb
- curl_easy_setopt(ch, CURLOPT_URL, c_str(url));
if (verb == "POST") {
curl_easy_setopt(ch, CURLOPT_POST, true);
curl_easy_setopt(ch, CURLOPT_POSTFIELDSIZE, sz);
@@ -211,6 +276,7 @@ template<typename R> const failable<list<R> > apply(const list<list<string> >& h
curl_easy_setopt(ch, CURLOPT_CUSTOMREQUEST, "DELETE");
const CURLcode rc = curl_easy_perform(ch);
+ // Free the headers
if (hl != NULL)
curl_slist_free_all(hl);
@@ -230,7 +296,7 @@ template<typename R> const failable<list<R> > apply(const list<list<string> >& h
/**
* Evaluate an expression remotely, at the given URL.
*/
-const failable<value> evalExpr(const value& expr, const string& url, const CURLSession& ch) {
+const failable<value> evalExpr(const value& expr, const string& url, const CURLSession& cs) {
debug(url, "http::evalExpr::url");
debug(expr, "http::evalExpr::input");
@@ -242,7 +308,7 @@ const failable<value> evalExpr(const value& expr, const string& url, const CURLS
// POST it to the URL
const list<string> h = mklist<string>("Content-Type: application/json-rpc");
- const failable<list<list<string> > > res = apply<list<string> >(mklist<list<string> >(h, content(jsreq)), rcons<string>, list<string>(), url, "POST", ch);
+ const failable<list<list<string> > > res = apply<list<string> >(mklist<list<string> >(h, content(jsreq)), rcons<string>, list<string>(), url, "POST", cs);
if (!hasContent(res))
return mkfailure<value>(reason(res));
@@ -294,20 +360,20 @@ const failable<string> contentType(const list<string>& h) {
/**
* HTTP GET, return the resource at the given URL.
*/
-template<typename R> const failable<list<R> > get(const lambda<R(const string&, const R)>& reduce, const R& initial, const string& url, const CURLSession& ch) {
+template<typename R> const failable<list<R> > get(const lambda<R(const string&, const R)>& reduce, const R& initial, const string& url, const CURLSession& cs) {
debug(url, "http::get::url");
const list<list<string> > req = mklist(list<string>(), list<string>());
- return apply(req, reduce, initial, url, "GET", ch);
+ return apply(req, reduce, initial, url, "GET", cs);
}
/**
* HTTP GET, return a list of values representing the resource at the given URL.
*/
-const failable<value> getcontent(const string& url, const CURLSession& ch) {
+const failable<value> getcontent(const string& url, const CURLSession& cs) {
debug(url, "http::get::url");
// Get the contents of the resource at the given URL
- const failable<list<list<string> > > res = get<list<string>>(rcons<string>, list<string>(), url, ch);
+ const failable<list<list<string> > > res = get<list<string>>(rcons<string>, list<string>(), url, cs);
if (!hasContent(res))
return mkfailure<value>(reason(res));
const list<string> ls(reverse(cadr(content(res))));
@@ -321,11 +387,11 @@ const failable<value> getcontent(const string& url, const CURLSession& ch) {
/**
* HTTP GET, return a list of values representing the resource at the given URL.
*/
-const failable<value> get(const string& url, const CURLSession& ch) {
+const failable<value> get(const string& url, const CURLSession& cs) {
debug(url, "http::get::url");
// Get the contents of the resource at the given URL
- const failable<list<list<string> > > res = get<list<string> >(rcons<string>, list<string>(), url, ch);
+ const failable<list<list<string> > > res = get<list<string> >(rcons<string>, list<string>(), url, cs);
if (!hasContent(res))
return mkfailure<value>(reason(res));
const list<string> ls(reverse(cadr(content(res))));
@@ -359,7 +425,7 @@ const failable<value> get(const string& url, const CURLSession& ch) {
/**
* HTTP POST.
*/
-const failable<value> post(const value& val, const string& url, const CURLSession& ch) {
+const failable<value> post(const value& val, const string& url, const CURLSession& cs) {
// Convert value to an ATOM entry
const failable<list<string> > entry = atom::writeATOMEntry(atom::entryValuesToElements(val));
@@ -371,7 +437,7 @@ const failable<value> post(const value& val, const string& url, const CURLSessio
// POST it to the URL
const list<string> h = mklist<string>("Content-Type: application/atom+xml");
const list<list<string> > req = mklist<list<string> >(h, content(entry));
- const failable<list<list<string> > > res = apply<list<string>>(req, rcons<string>, list<string>(), url, "POST", ch);
+ const failable<list<list<string> > > res = apply<list<string>>(req, rcons<string>, list<string>(), url, "POST", cs);
if (!hasContent(res))
return mkfailure<value>(reason(res));
@@ -384,7 +450,7 @@ const failable<value> post(const value& val, const string& url, const CURLSessio
/**
* HTTP PUT.
*/
-const failable<value> put(const value& val, const string& url, const CURLSession& ch) {
+const failable<value> put(const value& val, const string& url, const CURLSession& cs) {
// Convert value to an ATOM entry
const failable<list<string> > entry = atom::writeATOMEntry(atom::entryValuesToElements(val));
@@ -396,7 +462,7 @@ const failable<value> put(const value& val, const string& url, const CURLSession
// PUT it to the URL
const list<string> h = mklist<string>("Content-Type: application/atom+xml");
const list<list<string> > req = mklist<list<string> >(h, content(entry));
- const failable<list<list<string> > > res = apply<list<string> >(req, rcons<string>, list<string>(), url, "PUT", ch);
+ const failable<list<list<string> > > res = apply<list<string> >(req, rcons<string>, list<string>(), url, "PUT", cs);
if (!hasContent(res))
return mkfailure<value>(reason(res));
@@ -407,11 +473,11 @@ const failable<value> put(const value& val, const string& url, const CURLSession
/**
* HTTP DELETE.
*/
-const failable<value, string> del(const string& url, const CURLSession& ch) {
+const failable<value, string> del(const string& url, const CURLSession& cs) {
debug(url, "http::delete::url");
const list<list<string> > req = mklist(list<string>(), list<string>());
- const failable<list<list<string> > > res = apply<list<string> >(req, rcons<string>, list<string>(), url, "DELETE", ch);
+ const failable<list<list<string> > > res = apply<list<string> >(req, rcons<string>, list<string>(), url, "DELETE", cs);
if (!hasContent(res))
return mkfailure<value>(reason(res));
@@ -430,6 +496,109 @@ const string hostname() {
}
/**
+ * Create an APR pollfd for a socket.
+ */
+apr_pollfd_t* pollfd(apr_socket_t* s, const int e, const gc_pool& p) {
+ apr_pollfd_t* pfd = gc_new<apr_pollfd_t>(p);
+ pfd->p = pool(p);
+ pfd->desc_type = APR_POLL_SOCKET;
+ pfd->reqevents = (apr_int16_t)e;
+ pfd->rtnevents = (apr_int16_t)e;
+ pfd->desc.s = s;
+ pfd->client_data = NULL;
+ return pfd;
+}
+
+/**
+ * Connect to a URL.
+ */
+const failable<bool> connect(const string& url, CURLSession& cs) {
+
+ // Setup the CURL session
+ const failable<CURL*> fch = setup(url, cs);
+ if (!hasContent(fch))
+ return mkfailure<bool>(reason(fch));
+ CURL* ch = content(fch);
+
+ // Connect
+ curl_easy_setopt(ch, CURLOPT_CONNECT_ONLY, true);
+ const CURLcode rc = curl_easy_perform(ch);
+ if (rc)
+ return mkfailure<bool>(string(curl_easy_strerror(rc)));
+
+ // Convert the connected socket to an apr_socket_t
+ int sd;
+ const CURLcode grc = curl_easy_getinfo(ch, CURLINFO_LASTSOCKET, &sd);
+ if (grc)
+ return mkfailure<bool>(string(curl_easy_strerror(grc)));
+ cs.sock = sock(sd, cs.p);
+
+ // Create pollsets and pollfds which can be used to poll the socket
+ apr_status_t rpcrc = apr_pollset_create(&cs.rpollset, 1, pool(cs.p), 0);
+ if (rpcrc != APR_SUCCESS)
+ return mkfailure<bool>(apreason(rpcrc));
+ cs.rpollfd = pollfd(cs.sock, APR_POLLIN, cs.p);
+ apr_pollset_add(cs.rpollset, cs.rpollfd);
+ apr_status_t wpcrc = apr_pollset_create(&cs.wpollset, 1, pool(cs.p), 0);
+ if (wpcrc != APR_SUCCESS)
+ return mkfailure<bool>(apreason(wpcrc));
+ cs.wpollfd = pollfd(cs.sock, APR_POLLOUT, cs.p);
+ apr_pollset_add(cs.wpollset, cs.wpollfd);
+
+ return true;
+}
+
+/**
+ * Send an array of chars.
+ */
+const failable<bool> send(const char* c, const int l, const CURLSession& cs) {
+
+ // Send the data
+ size_t wl = 0;
+ const CURLcode rc = curl_easy_send(cs.h, c, (size_t)l, &wl);
+ if (rc == CURLE_OK && wl == (size_t)l)
+ return true;
+ if (rc != CURLE_AGAIN)
+ return mkfailure<bool>(curlreason(rc));
+
+ // If the socket was not ready, wait for it to become ready
+ const apr_pollfd_t* pollfds;
+ apr_int32_t pollcount;
+ apr_status_t pollrc = apr_pollset_poll(cs.wpollset, -1, &pollcount, &pollfds);
+ if (pollrc != APR_SUCCESS)
+ return mkfailure<bool>(apreason(pollrc));
+
+ // Send what's left
+ return send(c + wl, (int)((size_t)l - wl), cs);
+}
+
+/**
+ * Receive an array of chars.
+ */
+const failable<int> recv(char* c, const int l, const CURLSession& cs) {
+
+ // Receive data
+ size_t rl;
+ const CURLcode rc = curl_easy_recv(cs.h, c, (size_t)l, &rl);
+ if (rc == CURLE_OK)
+ return (int)rl;
+ if (rc == 1)
+ return 0;
+ if (rc != CURLE_AGAIN)
+ return mkfailure<int>(curlreason(rc));
+
+ // If the socket was not ready, wait for it to become ready
+ const apr_pollfd_t* pollfds;
+ apr_int32_t pollcount;
+ apr_status_t pollrc = apr_pollset_poll(cs.rpollset, -1, &pollcount, &pollfds);
+ if (pollrc != APR_SUCCESS)
+ return mkfailure<int>(apreason(pollrc));
+
+ // Receive again
+ return recv(c, l, cs);
+}
+
+/**
* HTTP client proxy function.
*/
struct proxy {
@@ -453,4 +622,4 @@ struct proxy {
}
}
-#endif /* tuscany_curl_hpp */
+#endif /* tuscany_http_hpp */
diff --git a/sca-cpp/trunk/modules/http/httpd-addr b/sca-cpp/trunk/modules/http/httpd-addr
new file mode 100755
index 0000000000..62fc775ea7
--- /dev/null
+++ b/sca-cpp/trunk/modules/http/httpd-addr
@@ -0,0 +1,54 @@
+#!/bin/sh
+
+# 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.
+
+# Parse a string in the form ip-addr:local-port/public-port
+addr=`echo $2 | awk -F "/" '{ print $1 }'`
+ip=`echo $addr | awk -F ":" '{ print $1 }'`
+port=`echo $addr | awk -F ":" '{ print $2 }'`
+if [ "$port" = "" ]; then
+ port=$ip
+ ip=""
+ listen=$port
+ vhost="*:$port"
+else
+ listen="$ip:$port"
+ vhost="$ip:$port"
+fi
+pport=`echo $2 | awk -F "/" '{ print $2 }'`
+if [ "$pport" = "" ]; then
+ pport=$port
+fi
+
+# Return the requested part
+if [ "$1" = "ip" ]; then
+ echo $ip
+fi
+if [ "$1" = "port" ]; then
+ echo $port
+fi
+if [ "$1" = "pport" ]; then
+ echo $pport
+fi
+if [ "$1" = "listen" ]; then
+ echo $listen
+fi
+if [ "$1" = "vhost" ]; then
+ echo $vhost
+fi
+return 0
diff --git a/sca-cpp/trunk/modules/http/httpd-auth-conf b/sca-cpp/trunk/modules/http/httpd-auth-conf
index cfe81f778a..ffe745db9d 100755
--- a/sca-cpp/trunk/modules/http/httpd-auth-conf
+++ b/sca-cpp/trunk/modules/http/httpd-auth-conf
@@ -20,8 +20,10 @@
# Generate a minimal HTTPD SSL configuration
here=`readlink -f $0`; here=`dirname $here`
root=`readlink -f $1`
+
conf=`cat $root/conf/httpd.conf | grep "# Generated by: httpd-conf"`
host=`echo $conf | awk '{ print $6 }'`
+
httpd_prefix=`cat $here/httpd.prefix`
# Generate basic authentication configuration
diff --git a/sca-cpp/trunk/modules/http/httpd-conf b/sca-cpp/trunk/modules/http/httpd-conf
index 2cbf5120e9..09d78351ff 100755
--- a/sca-cpp/trunk/modules/http/httpd-conf
+++ b/sca-cpp/trunk/modules/http/httpd-conf
@@ -21,16 +21,19 @@
here=`readlink -f $0`; here=`dirname $here`
mkdir -p $1
root=`readlink -f $1`
+
host=$2
-port=`echo $3 | awk -F "/" '{ print $1 }'`
-pport=`echo $3 | awk -F "/" '{ print $2 }'`
-if [ "$pport" = "" ]; then
- pport=$port
-fi
+port=`$here/httpd-addr port $3`
+pport=`$here/httpd-addr pport $3`
+listen=`$here/httpd-addr listen $3`
+vhost=`$here/httpd-addr vhost $3`
+
mkdir -p $4
htdocs=`readlink -f $4`
+
user=`id -un`
group=`id -gn`
+
modules_prefix=`cat $here/httpd-modules.prefix`
mkdir -p $root
@@ -74,6 +77,8 @@ LoadModule log_config_module ${modules_prefix}/modules/mod_log_config.so
</IfModule>
LoadModule vhost_alias_module ${modules_prefix}/modules/mod_vhost_alias.so
+LoadModule mod_tuscany_ssltunnel $here/libmod_tuscany_ssltunnel.so
+
# Basic security precautions
User $user
Group $group
@@ -124,10 +129,10 @@ Allow from all
</Location>
# Listen on HTTP port
-Listen $port
+Listen $listen
# Setup HTTP virtual host
-<VirtualHost *:$port>
+<VirtualHost $vhost>
ServerName http://$host:$pport
Include conf/svhost.conf
diff --git a/sca-cpp/trunk/modules/http/httpd-ssl-conf b/sca-cpp/trunk/modules/http/httpd-ssl-conf
index f36da55b12..7b57539f5d 100755
--- a/sca-cpp/trunk/modules/http/httpd-ssl-conf
+++ b/sca-cpp/trunk/modules/http/httpd-ssl-conf
@@ -20,20 +20,21 @@
# Generate a minimal HTTPD SSL configuration
here=`readlink -f $0`; here=`dirname $here`
root=`readlink -f $1`
+
conf=`cat $root/conf/httpd.conf | grep "# Generated by: httpd-conf"`
host=`echo $conf | awk '{ print $6 }'`
-port=`echo $conf | awk '{ print $7 }' | awk -F "/" '{ print $1 }'`
-sslport=`echo $2 | awk -F "/" '{ print $1 }'`
-sslpport=`echo $2 | awk -F "/" '{ print $2 }'`
-if [ "$sslpport" = "" ]; then
- sslpport=$sslport
-fi
+
+sslpport=`$here/httpd-addr pport $2`
+ssllisten=`$here/httpd-addr listen $2`
+sslvhost=`$here/httpd-addr vhost $2`
+
htdocs=`echo $conf | awk '{ print $8 }'`
htdocs=`readlink -f $htdocs`
+
httpd_prefix=`cat $here/httpd.prefix`
# Extract organization name from our CA certificate
-org=`openssl x509 -noout -subject -nameopt multiline -in $root/conf/ca.crt | grep organizationName | awk -F "= " '{ print $2 }'`
+org=`openssl x509 -noout -subject -nameopt multiline -in $root/cert/ca.crt | grep organizationName | awk -F "= " '{ print $2 }'`
# Generate HTTPD configuration
cat >>$root/conf/httpd.conf <<EOF
@@ -41,7 +42,7 @@ cat >>$root/conf/httpd.conf <<EOF
# Redirect all HTTP traffic to HTTPS
<Location />
RewriteEngine on
-RewriteCond %{SERVER_PORT} !^$sslpport$
+RewriteCond %{HTTPS} !^on$
RewriteRule .* https://%{SERVER_NAME}:$sslpport%{REQUEST_URI} [R,L]
</Location>
@@ -56,10 +57,10 @@ SSLRandomSeed startup builtin
SSLRandomSeed connect builtin
# Listen on HTTPS port
-Listen $sslport
+Listen $ssllisten
# HTTPS virtual host
-<VirtualHost *:$sslport>
+<VirtualHost $sslvhost>
ServerName https://$host:$sslpport
Include conf/svhost-ssl.conf
@@ -156,6 +157,7 @@ else
# - another valid form of authentication as per the Satisfy directive
SSLRequire %{SSL_CIPHER_USEKEYSIZE} >= 128 and ( \
( %{SSL_CLIENT_I_DN_O} == "$org" and %{SSL_CLIENT_S_DN_OU} == "server" ) or \
+( %{SSL_CLIENT_I_DN_O} == "$org" and %{SSL_CLIENT_S_DN_OU} == "tunnel" ) or \
( %{SSL_CLIENT_I_DN_O} == "$org" and %{SSL_CLIENT_S_DN_OU} == "proxy" and \
%{HTTP:X-Forwarded-SSL-Issuer-DN-O} == "$org" and %{HTTP:X-Forwarded-SSL-Client-DN-OU} == "server" ) or \
%{REQUEST_URI} =~ m/^.(login|logout|openid|unprotected).*$/ )
@@ -177,6 +179,10 @@ RewriteCond %{SSL:SSL_CLIENT_S_DN_OU} "server"
RewriteRule .* - [E=SSL_REMOTE_USER:%{SSL:SSL_CLIENT_S_DN}]
RewriteCond %{SSL:SSL_CLIENT_I_DN_O} "$org"
+RewriteCond %{SSL:SSL_CLIENT_S_DN_OU} "tunnel"
+RewriteRule .* - [E=SSL_REMOTE_USER:%{SSL:SSL_CLIENT_S_DN}]
+
+RewriteCond %{SSL:SSL_CLIENT_I_DN_O} "$org"
RewriteCond %{SSL:SSL_CLIENT_S_DN_OU} "proxy"
RewriteCond %{HTTP:X-Forwarded-SSL-Issuer-DN-O} "$org"
RewriteCond %{HTTP:X-Forwarded-SSL-Client-DN-OU} "server"
@@ -196,10 +202,10 @@ cat >$root/conf/svhost-ssl.conf <<EOF
Include conf/vhost-ssl.conf
# Declare SSL certificates used in this virtual host
-SSLCACertificateFile "$root/conf/ca.crt"
-SSLCertificateChainFile "$root/conf/ca.crt"
-SSLCertificateFile "$root/conf/server.crt"
-SSLCertificateKeyFile "$root/conf/server.key"
+SSLCACertificateFile "$root/cert/ca.crt"
+SSLCertificateChainFile "$root/cert/ca.crt"
+SSLCertificateFile "$root/cert/server.crt"
+SSLCertificateKeyFile "$root/cert/server.key"
EOF
@@ -209,10 +215,10 @@ cat >$root/conf/dvhost-ssl.conf <<EOF
Include conf/vhost-ssl.conf
# Declare wildcard SSL certificates used in this virtual host
-SSLCACertificateFile "$root/conf/ca.crt"
-SSLCertificateChainFile "$root/conf/ca.crt"
-SSLCertificateFile "$root/conf/vhost.crt"
-SSLCertificateKeyFile "$root/conf/vhost.key"
+SSLCACertificateFile "$root/cert/ca.crt"
+SSLCertificateChainFile "$root/cert/ca.crt"
+SSLCertificateFile "$root/cert/vhost.crt"
+SSLCertificateKeyFile "$root/cert/vhost.key"
EOF
diff --git a/sca-cpp/trunk/modules/http/httpd.hpp b/sca-cpp/trunk/modules/http/httpd.hpp
index 486bc7fa82..767af11cf9 100644
--- a/sca-cpp/trunk/modules/http/httpd.hpp
+++ b/sca-cpp/trunk/modules/http/httpd.hpp
@@ -26,24 +26,25 @@
* HTTPD module implementation functions.
*/
-#include "apr_strings.h"
-#include "apr_fnmatch.h"
-#include "apr_lib.h"
+#include <apr_strings.h>
+#include <apr_fnmatch.h>
+#include <apr_lib.h>
#define APR_WANT_STRFUNC
-#include "apr_want.h"
-
-#include "httpd.h"
-#include "http_config.h"
-#include "http_core.h"
-#include "http_request.h"
-#include "http_protocol.h"
-#include "http_log.h"
-#include "http_main.h"
-#include "util_script.h"
-#include "util_md5.h"
-#include "http_config.h"
-#include "ap_mpm.h"
-#include "mod_core.h"
+#include <apr_want.h>
+
+#include <httpd.h>
+#include <http_config.h>
+#include <http_core.h>
+#include <http_connection.h>
+#include <http_request.h>
+#include <http_protocol.h>
+#include <http_log.h>
+#include <http_main.h>
+#include <util_script.h>
+#include <util_md5.h>
+#include <http_config.h>
+#include <ap_mpm.h>
+#include <mod_core.h>
#include "string.hpp"
#include "stream.hpp"
@@ -131,66 +132,13 @@ const bool isVirtualHostRequest(const server_rec* s, request_rec* r) {
/**
* Return the content type of a request.
*/
-const char* optional(const char* s) {
- if (s == NULL)
- return "";
- return s;
-}
-
const string contentType(const request_rec* r) {
- return optional(apr_table_get(r->headers_in, "Content-Type"));
-}
-
-#ifdef WANT_MAINTAINER_MODE
-
-/**
- * Debug log.
- */
-int debugHeader(unused void* r, const char* key, const char* value) {
- cerr << " header key: " << key << ", value: " << value << endl;
- return 1;
-}
-
-int debugEnv(unused void* r, const char* key, const char* value) {
- cerr << " var key: " << key << ", value: " << value << endl;
- return 1;
-}
-
-int debugNote(unused void* r, const char* key, const char* value) {
- cerr << " note key: " << key << ", value: " << value << endl;
- return 1;
-}
-
-const bool debugRequest(request_rec* r, const string& msg) {
- cerr << msg << ":" << endl;
- cerr << " server: " << optional(r->server->server_hostname) << endl;
- cerr << " protocol: " << optional(r->protocol) << endl;
- cerr << " method: " << optional(r->method) << endl;
- cerr << " method number: " << r->method_number << endl;
- cerr << " content type: " << contentType(r) << endl;
- cerr << " content encoding: " << optional(r->content_encoding) << endl;
- apr_table_do(debugHeader, r, r->headers_in, NULL);
- cerr << " unparsed uri: " << optional(r->unparsed_uri) << endl;
- cerr << " uri: " << optional(r->uri) << endl;
- cerr << " path info: " << optional(r->path_info) << endl;
- cerr << " filename: " << optional(r->filename) << endl;
- cerr << " uri tokens: " << pathTokens(r->uri) << endl;
- cerr << " args: " << optional(r->args) << endl;
- cerr << " user: " << optional(r->user) << endl;
- cerr << " auth type: " << optional(r->ap_auth_type) << endl;
- apr_table_do(debugEnv, r, r->subprocess_env, NULL);
- apr_table_do(debugEnv, r, r->notes, NULL);
- return true;
+ const char* ct = apr_table_get(r->headers_in, "Content-Type");
+ if (ct == NULL)
+ return "";
+ return ct;
}
-#define httpdDebugRequest(r, msg) httpd::debugRequest(r, msg)
-
-#else
-
-#define httpdDebugRequest(r, msg)
-
-#endif
-
/**
* Return the remaining part of a uri after the given path (aka the path info.)
*/
@@ -216,19 +164,6 @@ const list<list<value> > queryArgs(const request_rec* r) {
}
/**
- * Returns a list of param values other than the id and method args from a list
- * of key value pairs.
- */
-const list<value> queryParams(const list<list<value> >& a) {
- if (isNil(a))
- return list<value>();
- const list<value> p = car(a);
- if (car(p) == value("id") || car(p) == value("method"))
- return queryParams(cdr(a));
- return cons(cadr(p), queryParams(cdr(a)));
-}
-
-/**
* Converts the args received in a POST to a list of key value pairs.
*/
const list<list<value> > postArgs(const list<value>& a) {
@@ -303,7 +238,7 @@ const failable<int> writeResult(const failable<list<string> >& ls, const string&
}
/**
- * Report request execution status.
+ * Report a request execution status.
*/
const int reportStatus(const failable<int>& rc) {
if (!hasContent(rc))
@@ -337,7 +272,7 @@ const value requestValue(request_rec* r) {
}
/**
- * Update filters in an HTTPD redirect request.
+ * Update request filters in an HTTPD redirect request.
* Similar to httpd/modules/http/http_request.c::update_r_in_filters.
*/
const bool redirectFilters(ap_filter_t* f, request_rec* from, request_rec* to) {
@@ -468,6 +403,62 @@ const void* userData(const string& k, const server_rec* s) {
return v;
}
+#ifdef WANT_MAINTAINER_MODE
+
+/**
+ * Debug log.
+ */
+const char* debugOptional(const char* s) {
+ if (s == NULL)
+ return "";
+ return s;
+}
+
+int debugHeader(unused void* r, const char* key, const char* value) {
+ cerr << " header key: " << key << ", value: " << value << endl;
+ return 1;
+}
+
+int debugEnv(unused void* r, const char* key, const char* value) {
+ cerr << " var key: " << key << ", value: " << value << endl;
+ return 1;
+}
+
+int debugNote(unused void* r, const char* key, const char* value) {
+ cerr << " note key: " << key << ", value: " << value << endl;
+ return 1;
+}
+
+const bool debugRequest(request_rec* r, const string& msg) {
+ cerr << msg << ":" << endl;
+ cerr << " server: " << debugOptional(r->server->server_hostname) << endl;
+ cerr << " protocol: " << debugOptional(r->protocol) << endl;
+ cerr << " method: " << debugOptional(r->method) << endl;
+ cerr << " method number: " << r->method_number << endl;
+ cerr << " content type: " << contentType(r) << endl;
+ cerr << " content encoding: " << debugOptional(r->content_encoding) << endl;
+ apr_table_do(debugHeader, r, r->headers_in, NULL);
+ cerr << " unparsed uri: " << debugOptional(r->unparsed_uri) << endl;
+ cerr << " uri: " << debugOptional(r->uri) << endl;
+ cerr << " path info: " << debugOptional(r->path_info) << endl;
+ cerr << " filename: " << debugOptional(r->filename) << endl;
+ cerr << " uri tokens: " << pathTokens(r->uri) << endl;
+ cerr << " args: " << debugOptional(r->args) << endl;
+ cerr << " user: " << debugOptional(r->user) << endl;
+ cerr << " auth type: " << debugOptional(r->ap_auth_type) << endl;
+ apr_table_do(debugEnv, r, r->subprocess_env, NULL);
+ apr_table_do(debugEnv, r, r->notes, NULL);
+ return true;
+}
+
+#define httpdDebugRequest(r, msg) httpd::debugRequest(r, msg)
+
+#else
+
+#define httpdDebugRequest(r, msg)
+
+#endif
+
}
}
diff --git a/sca-cpp/trunk/modules/http/mod-ssltunnel.cpp b/sca-cpp/trunk/modules/http/mod-ssltunnel.cpp
new file mode 100644
index 0000000000..5337a4cac2
--- /dev/null
+++ b/sca-cpp/trunk/modules/http/mod-ssltunnel.cpp
@@ -0,0 +1,364 @@
+/*
+ * 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.
+ */
+
+/* $Rev$ $Date$ */
+
+/**
+ * HTTPD module used to tunnel traffic over an HTTPS connection.
+ */
+
+#include <sys/stat.h>
+
+#include "string.hpp"
+#include "stream.hpp"
+#include "list.hpp"
+#include "tree.hpp"
+#include "value.hpp"
+#include "monad.hpp"
+#include "httpd.hpp"
+#include "http.hpp"
+
+extern "C" {
+extern module AP_MODULE_DECLARE_DATA mod_tuscany_ssltunnel;
+}
+
+namespace tuscany {
+namespace httpd {
+namespace modssltunnel {
+
+/**
+ * Server configuration.
+ */
+class ServerConf {
+public:
+ ServerConf(server_rec* s) : server(s) {
+ }
+ server_rec* server;
+ string pass;
+ string host;
+ string path;
+ string ca;
+ string cert;
+ string key;
+};
+
+extern "C" {
+extern module AP_DECLARE_DATA core_module;
+}
+
+/**
+ * Process the module configuration.
+ */
+int M_SSLTUNNEL;
+int postConfigParse(ServerConf& mainsc, apr_pool_t* p, server_rec* s) {
+ if (s == NULL)
+ return OK;
+ ServerConf& sc = httpd::serverConf<ServerConf>(s, &mod_tuscany_ssltunnel);
+ debug(httpd::serverName(s), "modwiring::postConfigParse::serverName");
+
+ // Merge configuration from main server
+ if (length(sc.ca) == 0 && length(mainsc.ca) !=0)
+ sc.ca = mainsc.ca;
+ if (length(sc.cert) == 0 && length(mainsc.cert) !=0)
+ sc.cert = mainsc.cert;
+ if (length(sc.key) == 0 && length(mainsc.key) !=0)
+ sc.key = mainsc.key;
+
+ // Parse the configured TunnelPass URI
+ if (length(sc.pass) != 0) {
+ apr_uri_t uri;
+ apr_status_t prc = apr_uri_parse(p, c_str(sc.pass), &uri);
+ if (prc != APR_SUCCESS) {
+ mkfailure<int>("Couldn't parse TunnelPass: " + sc.pass + ", " + http::apreason(prc));
+ return prc;
+ }
+ sc.host = uri.hostname;
+ sc.path = uri.path;
+ }
+ return postConfigParse(mainsc, p, s->next);
+}
+
+int postConfig(apr_pool_t* p, unused apr_pool_t* plog, unused apr_pool_t* ptemp, server_rec* s) {
+ gc_scoped_pool pool(p);
+ ServerConf& sc = httpd::serverConf<ServerConf>(s, &mod_tuscany_ssltunnel);
+ debug(httpd::serverName(s), "modwiring::postConfig::serverName");
+
+ // Register the SSLTUNNEL method
+ M_SSLTUNNEL = ap_method_register(p, "SSLTUNNEL");
+
+ // Parse the configured TunnelPass URI
+ return postConfigParse(sc, p, s);
+}
+
+/**
+ * Close a connection.
+ */
+extern "C" {
+ AP_DECLARE(void) ap_lingering_close(conn_rec *c);
+}
+
+const int close(conn_rec* conn) {
+ debug("modssltunnel::close");
+ ap_lingering_close(conn);
+ return OK;
+}
+
+/**
+ * Abort a connection.
+ */
+const int abort(unused conn_rec* conn, const string& reason) {
+ debug("modssltunnel::abort");
+ return httpd::reportStatus(mkfailure<int>(reason));
+}
+
+/**
+ * Tunnel traffic from a client connection to a target URL.
+ */
+int tunnel(conn_rec* conn, http::CURLSession& cs, const string& url, const string& preamble, const gc_pool& p, unused ap_filter_t* ifilter, ap_filter_t* ofilter) {
+
+ // Get client connection socket
+ apr_socket_t* csock = (apr_socket_t*)ap_get_module_config(conn->conn_config, &core_module);
+
+ // Open connection to target
+ const failable<bool> crc = http::connect(url, cs);
+ if (!hasContent(crc))
+ return abort(conn, reason(crc));
+ apr_socket_t* tsock = http::sock(cs);
+
+ // Send preamble string
+ if (length(preamble) != 0) {
+ debug(preamble, "modssltunnel::tunnel::sendToTarget");
+ const failable<bool> src = http::send(c_str(preamble), length(preamble), cs);
+ if (!hasContent(src))
+ return abort(conn, string("Couldn't send to target: ") + reason(src));
+ }
+
+ // Create input/output bucket brigades
+ apr_bucket_brigade* ib = apr_brigade_create(pool(p), conn->bucket_alloc);
+ apr_bucket_brigade* ob = apr_brigade_create(pool(p), conn->bucket_alloc);
+
+ // Create a pollset for the client and target sockets
+ apr_pollset_t* pollset;
+ apr_status_t cprc = apr_pollset_create(&pollset, 2, pool(p), 0);
+ if (cprc != APR_SUCCESS)
+ return abort(conn, http::apreason(cprc));
+ const apr_pollfd_t* cpollfd = http::pollfd(csock, APR_POLLIN, p);
+ apr_pollset_add(pollset, cpollfd);
+ const apr_pollfd_t* tpollfd = http::pollfd(tsock, APR_POLLIN, p);
+ apr_pollset_add(pollset, tpollfd);
+
+ // Relay traffic in both directions until end of stream
+ const apr_pollfd_t* pollfds = cpollfd;
+ apr_int32_t pollcount = 1;
+ for(;;) {
+ for (; pollcount > 0; pollcount--, pollfds++) {
+ if (pollfds->rtnevents & APR_POLLIN) {
+ if (pollfds->desc.s == csock) {
+
+ // Receive buckets from client
+ const apr_status_t getrc = ap_get_brigade(conn->input_filters, ib, AP_MODE_READBYTES, APR_BLOCK_READ, HUGE_STRING_LEN);
+ if (getrc != APR_SUCCESS)
+ return OK;
+
+ for (apr_bucket* bucket = APR_BRIGADE_FIRST(ib); bucket != APR_BRIGADE_SENTINEL(ib); bucket = APR_BUCKET_NEXT(bucket)) {
+ if (APR_BUCKET_IS_FLUSH(bucket))
+ continue;
+
+ // Client connection closed
+ if (APR_BUCKET_IS_EOS(bucket))
+ return close(conn);
+
+ const char *data;
+ apr_size_t rl;
+ apr_bucket_read(bucket, &data, &rl, APR_BLOCK_READ);
+ if (rl > 0) {
+ debug(string(data, rl), "modssltunnel::tunnel::sendToTarget");
+
+ // Send to target
+ const failable<bool> src = http::send(data, rl, cs);
+ if (!hasContent(src))
+ return abort(conn, string("Couldn't send to target: ") + reason(src));
+ }
+ }
+ apr_brigade_cleanup(ib);
+ } else {
+
+ // Receive from target
+ char data[8192];
+ const failable<int> frl = http::recv(data, sizeof(data), cs);
+ if (!hasContent(frl))
+ return abort(conn, string("Couldn't receive from target") + reason(frl));
+ const int rl = content(frl);
+
+ // Target connection closed
+ if (rl == 0)
+ return close(conn);
+
+ // Send bucket to client
+ APR_BRIGADE_INSERT_TAIL(ob, apr_bucket_transient_create(data, rl, conn->bucket_alloc));
+ APR_BRIGADE_INSERT_TAIL(ob, apr_bucket_flush_create(conn->bucket_alloc));
+ if (ap_pass_brigade(ofilter, ob) != APR_SUCCESS)
+ return abort(conn, "Couldn't send data bucket to client");
+ apr_brigade_cleanup(ob);
+ }
+ }
+
+ // Error
+ if (pollfds->rtnevents & (APR_POLLERR | APR_POLLHUP | APR_POLLNVAL)) {
+ if (pollfds->desc.s == csock)
+ return abort(conn, "Couldn't receive from client");
+ else
+ return abort(conn, "Couldn't receive from target");
+ }
+ }
+
+ // Poll the client and target sockets
+ debug("modssltunnel::tunnel::poll");
+ apr_status_t pollrc = apr_pollset_poll(pollset, -1, &pollcount, &pollfds);
+ if (pollrc != APR_SUCCESS)
+ return abort(conn, "Couldn't poll sockets");
+ debug(pollcount, "modssltunnel::tunnel::pollfds");
+ }
+
+ // Close client connection
+ return close(conn);
+}
+
+/**
+ * Return the first connection filter in a list of filters.
+ */
+ap_filter_t* connectionFilter(ap_filter_t* f) {
+ if (f == NULL)
+ return f;
+ if (f->frec->ftype < AP_FTYPE_CONNECTION)
+ return connectionFilter(f->next);
+ return f;
+}
+
+/**
+ * Process a client connection and relay it to a tunnel.
+ */
+int processConnection(conn_rec *conn) {
+ // Only allow configured virtual hosts
+ if (!conn->base_server->is_virtual)
+ return DECLINED;
+ if (ap_get_module_config(conn->base_server->module_config, &mod_tuscany_ssltunnel) == NULL)
+ return DECLINED;
+
+ gc_scoped_pool(conn->pool);
+ const ServerConf& sc = httpd::serverConf<ServerConf>(conn->base_server, &mod_tuscany_ssltunnel);
+ if (length(sc.pass) == 0)
+ return DECLINED;
+ debug(sc.pass, "modssltunnel::processConnection::pass");
+
+ // Create the target connection
+ http::CURLSession cs(sc.ca, sc.cert, sc.key);
+
+ // Run the tunnel
+ const string preamble = string("SSLTUNNEL ") + sc.path + string(" HTTP/1.1\r\nHost: ") + sc.host + string("\r\n\r\n");
+ debug(preamble, "modssltunnel::processConnection::preamble");
+ return tunnel(conn, cs, sc.pass, preamble, gc_pool(conn->pool), connectionFilter(conn->input_filters), connectionFilter(conn->output_filters));
+}
+
+/**
+ * Tunnel a SSLTUNNEL request to a target host/port.
+ */
+int handler(request_rec* r) {
+ if (r->method_number != M_SSLTUNNEL)
+ return DECLINED;
+
+ // Only allow HTTPS
+ if (strcmp(r->server->server_scheme, "https"))
+ return DECLINED;
+
+ // Build the target URL
+ debug(r->uri, "modssltunnel::handler::uri");
+ const list<value> path(pathValues(r->uri));
+ const string url = string(cadr(path)) + ":" + caddr(path);
+ debug(url, "modssltunnel::handler::target");
+
+ // Create the target connection
+ http::CURLSession cs;
+
+ // Run the tunnel
+ return tunnel(r->connection, cs, url, "", gc_pool(r->pool), connectionFilter(r->proto_input_filters), connectionFilter(r->proto_output_filters));
+}
+
+/**
+ * Configuration commands.
+ */
+const char* confTunnelPass(cmd_parms *cmd, unused void *c, const char *arg) {
+ gc_scoped_pool pool(cmd->pool);
+ ServerConf& sc = httpd::serverConf<ServerConf>(cmd, &mod_tuscany_ssltunnel);
+ sc.pass = arg;
+ return NULL;
+}
+const char* confCAFile(cmd_parms *cmd, unused void *c, const char *arg) {
+ gc_scoped_pool pool(cmd->pool);
+ ServerConf& sc = httpd::serverConf<ServerConf>(cmd, &mod_tuscany_ssltunnel);
+ sc.ca = arg;
+ return NULL;
+}
+const char* confCertFile(cmd_parms *cmd, unused void *c, const char *arg) {
+ gc_scoped_pool pool(cmd->pool);
+ ServerConf& sc = httpd::serverConf<ServerConf>(cmd, &mod_tuscany_ssltunnel);
+ sc.cert = arg;
+ return NULL;
+}
+const char* confCertKeyFile(cmd_parms *cmd, unused void *c, const char *arg) {
+ gc_scoped_pool pool(cmd->pool);
+ ServerConf& sc = httpd::serverConf<ServerConf>(cmd, &mod_tuscany_ssltunnel);
+ sc.key = arg;
+ return NULL;
+}
+
+/**
+ * HTTP server module declaration.
+ */
+const command_rec commands[] = {
+ AP_INIT_TAKE1("TunnelPass", (const char*(*)())confTunnelPass, NULL, RSRC_CONF, "Tunnel server name"),
+ AP_INIT_TAKE1("TunnelSSLCACertificateFile", (const char*(*)())confCAFile, NULL, RSRC_CONF, "Tunnel SSL CA certificate file"),
+ AP_INIT_TAKE1("TunnelSSLCertificateFile", (const char*(*)())confCertFile, NULL, RSRC_CONF, "Tunnel SSL certificate file"),
+ AP_INIT_TAKE1("TunnelSSLCertificateKeyFile", (const char*(*)())confCertKeyFile, NULL, RSRC_CONF, "Tunnel SSL certificate key file"),
+ {NULL, NULL, NULL, 0, NO_ARGS, NULL}
+};
+
+void registerHooks(unused apr_pool_t *p) {
+ ap_hook_post_config(postConfig, NULL, NULL, APR_HOOK_MIDDLE);
+ ap_hook_handler(handler, NULL, NULL, APR_HOOK_MIDDLE);
+ ap_hook_process_connection(processConnection, NULL, NULL, APR_HOOK_MIDDLE);
+}
+
+}
+}
+}
+
+extern "C" {
+
+module AP_MODULE_DECLARE_DATA mod_tuscany_ssltunnel = {
+ STANDARD20_MODULE_STUFF,
+ // dir config and merger
+ NULL, NULL,
+ // server config and merger
+ tuscany::httpd::makeServerConf<tuscany::httpd::modssltunnel::ServerConf>, NULL,
+ // commands and hooks
+ tuscany::httpd::modssltunnel::commands, tuscany::httpd::modssltunnel::registerHooks
+};
+
+}
diff --git a/sca-cpp/trunk/modules/http/proxy-member-conf b/sca-cpp/trunk/modules/http/proxy-member-conf
index 73c448c065..43f31c97b0 100755
--- a/sca-cpp/trunk/modules/http/proxy-member-conf
+++ b/sca-cpp/trunk/modules/http/proxy-member-conf
@@ -20,8 +20,9 @@
# Add a proxy balancer member
here=`readlink -f $0`; here=`dirname $here`
root=`readlink -f $1`
+
host=$2
-port=`echo $3 | awk -F "/" '{ print $1 }'`
+port=`$here/httpd-addr port $3`
cat >>$root/conf/vhost.conf <<EOF
# Generated by: proxy-member-conf $*
diff --git a/sca-cpp/trunk/modules/http/proxy-ssl-conf b/sca-cpp/trunk/modules/http/proxy-ssl-conf
index fe7e6a5be6..be9174c5fa 100755
--- a/sca-cpp/trunk/modules/http/proxy-ssl-conf
+++ b/sca-cpp/trunk/modules/http/proxy-ssl-conf
@@ -60,8 +60,8 @@ EOF
cat >>$root/conf/vhost-ssl.conf <<EOF
# Generated by: proxy-ssl-conf $*
# Declare the proxy SSL client certificates
-SSLProxyCACertificateFile "$root/conf/ca.crt"
-SSLProxyMachineCertificateFile "$root/conf/proxy.pem"
+SSLProxyCACertificateFile "$root/cert/ca.crt"
+SSLProxyMachineCertificateFile "$root/cert/proxy.pem"
EOF
diff --git a/sca-cpp/trunk/modules/http/proxy-ssl-member-conf b/sca-cpp/trunk/modules/http/proxy-ssl-member-conf
index 55930b7ef2..5ed1f4959f 100755
--- a/sca-cpp/trunk/modules/http/proxy-ssl-member-conf
+++ b/sca-cpp/trunk/modules/http/proxy-ssl-member-conf
@@ -20,8 +20,9 @@
# Add a proxy balancer member
here=`readlink -f $0`; here=`dirname $here`
root=`readlink -f $1`
+
host=$2
-sslport=`echo $3 | awk -F "/" '{ print $1 }'`
+sslport=`$here/httpd-addr port $3`
cat >>$root/conf/vhost-ssl.conf <<EOF
# Generated by: proxy-ssl-member-conf $*
diff --git a/sca-cpp/trunk/modules/http/ssl-ca-conf b/sca-cpp/trunk/modules/http/ssl-ca-conf
index bd24ca8c21..e7b9f96ee2 100755
--- a/sca-cpp/trunk/modules/http/ssl-ca-conf
+++ b/sca-cpp/trunk/modules/http/ssl-ca-conf
@@ -21,17 +21,18 @@
here=`readlink -f $0`; here=`dirname $here`
mkdir -p $1
root=`readlink -f $1`
+
host=$2
# Don't override existing certificate
-if [ -f $root/conf/ca.crt ]; then
+if [ -f $root/cert/ca.crt ]; then
return 0
fi
# Generate openssl configuration
-mkdir -p $root/conf
+mkdir -p $root/cert
umask 0007
-cat >$root/conf/openssl-ca.conf <<EOF
+cat >$root/cert/openssl-ca.conf <<EOF
[ req ]
default_bits = 1024
encrypt_key = no
@@ -57,11 +58,11 @@ basicConstraints = CA:true
default_ca = ca_default
[ca_default]
-certificate = $root/conf/ca.crt
-private_key = $root/conf/ca.key
-serial = $root/conf/ca-serial
-database = $root/conf/ca-database
-new_certs_dir = $root/conf
+certificate = $root/cert/ca.crt
+private_key = $root/cert/ca.key
+serial = $root/cert/ca-serial
+database = $root/cert/ca-database
+new_certs_dir = $root/cert
default_md = sha1
email_in_dn = no
default_days = 365
@@ -80,11 +81,16 @@ emailAddress = optional
EOF
-rm -rf $root/conf/*.pem
-rm -f $root/conf/ca-database
-echo 1000 > $root/conf/ca-serial
-touch $root/conf/ca-database
+rm -rf $root/cert/*.crt $root/cert/*.pem $root/cert/hash
+rm -f $root/cert/ca-database
+echo 1000 > $root/cert/ca-serial
+touch $root/cert/ca-database
# Generate the certification authority certificate
-openssl req -new -x509 -config $root/conf/openssl-ca.conf -out $root/conf/ca.crt -keyout $root/conf/ca.key
+openssl req -new -x509 -config $root/cert/openssl-ca.conf -out $root/cert/ca.crt -keyout $root/cert/ca.key
+
+# Add to the hash directory and rehash
+mkdir -p $root/cert/hash
+cp $root/cert/ca.crt $root/cert/hash
+c_rehash $root/cert/hash
diff --git a/sca-cpp/trunk/modules/http/ssl-cert-conf b/sca-cpp/trunk/modules/http/ssl-cert-conf
index 8b6208a449..57c4522535 100755
--- a/sca-cpp/trunk/modules/http/ssl-cert-conf
+++ b/sca-cpp/trunk/modules/http/ssl-cert-conf
@@ -21,6 +21,7 @@
here=`readlink -f $0`; here=`dirname $here`
mkdir -p $1
root=`readlink -f $1`
+
host=$2
if [ "$3" != "" ]; then
certname=$3
@@ -29,14 +30,14 @@ else
fi
# Don't regenerate the certificate if it already exists
-if [ -f $root/conf/$certname.crt ]; then
+if [ -f $root/cert/$certname.crt ]; then
return 0
fi
# Generate openssl configuration
-mkdir -p $root/conf
+mkdir -p $root/cert
umask 0007
-cat >$root/conf/openssl-cert-$certname.conf <<EOF
+cat >$root/cert/openssl-cert-$certname.conf <<EOF
[ req ]
default_bits = 1024
encrypt_key = no
@@ -54,16 +55,22 @@ emailAddress = admin@$host
EOF
# Generate a certificate request
-openssl req -new -config $root/conf/openssl-cert-$certname.conf -out $root/conf/$certname-req.crt -keyout $root/conf/$certname.key
+openssl req -new -config $root/cert/openssl-cert-$certname.conf -out $root/cert/$certname-req.crt -keyout $root/cert/$certname.key
# Generate a certificate, signed with our test certification authority certificate
-openssl ca -batch -config $root/conf/openssl-ca.conf -out $root/conf/$certname.crt -infiles $root/conf/$certname-req.crt
+openssl ca -batch -config $root/cert/openssl-ca.conf -out $root/cert/$certname.crt -infiles $root/cert/$certname-req.crt
# Export it to PKCS12 format, that's the format Web browsers want to import
-openssl pkcs12 -export -passout pass: -out $root/conf/$certname.p12 -inkey $root/conf/$certname.key -in $root/conf/$certname.crt -certfile $root/conf/ca.crt
+openssl pkcs12 -export -passout pass: -out $root/cert/$certname.p12 -inkey $root/cert/$certname.key -in $root/cert/$certname.crt -certfile $root/cert/ca.crt
# Convert the certificate to PEM format and concatenate the key to it, for use
# by mod_proxy
-openssl x509 -in $root/conf/$certname.crt -out $root/conf/$certname.pem
-cat $root/conf/$certname.key >> $root/conf/$certname.pem
+openssl x509 -in $root/cert/$certname.crt -out $root/cert/$certname.pem
+cat $root/cert/$certname.key >> $root/cert/$certname.pem
+
+# Add to the hash directory and rehash
+mkdir -p $root/cert/hash
+cp $root/cert/$certname.crt $root/cert/hash
+cp $root/cert/$certname.pem $root/cert/hash
+c_rehash $root/cert/hash
diff --git a/sca-cpp/trunk/modules/http/ssl-ls b/sca-cpp/trunk/modules/http/ssl-cert-find
index 71d40719ca..b5aefb8e38 100755
--- a/sca-cpp/trunk/modules/http/ssl-ls
+++ b/sca-cpp/trunk/modules/http/ssl-cert-find
@@ -17,9 +17,10 @@
# specific language governing permissions and limitations
# under the License.
-# Generate a test certification authority certificate
+# List certificate files, useful to distribute them to another host
here=`readlink -f $0`; here=`dirname $here`
root=`readlink -f $1`
-ls $root/conf/*.crt $root/conf/*.key $root/conf/*.pem $root/conf/*.p12 2>/dev/null
+cd $root
+find -regex '.*\.\(\(crt\)\|\(pem\)\|\(p12\)\|\(key\)\|\(0\)\)' 2>/dev/null
diff --git a/sca-cpp/trunk/modules/http/tunnel-ssl-conf b/sca-cpp/trunk/modules/http/tunnel-ssl-conf
new file mode 100755
index 0000000000..cdcb79e4e7
--- /dev/null
+++ b/sca-cpp/trunk/modules/http/tunnel-ssl-conf
@@ -0,0 +1,56 @@
+#!/bin/sh
+
+# 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.
+
+# Generate an SSL tunnel configuration
+here=`readlink -f $0`; here=`dirname $here`
+root=`readlink -f $1`
+
+conf=`cat $root/conf/httpd.conf | grep "# Generated by: httpd-conf"`
+host=`echo $conf | awk '{ print $6 }'`
+
+port=`$here/httpd-addr port $2`
+sslhost=$3
+sslport=$4
+tport=$5
+
+httpd_prefix=`cat $here/httpd.prefix`
+
+# Generate HTTPD configuration
+cat >>$root/conf/httpd.conf <<EOF
+# Generated by: tunnel-ssl-conf $*
+# Tunnel TCP/IP traffic over HTTPS
+
+# Listen on local port
+Listen 127.0.0.1:$port
+
+# Tunnel virtual host
+<VirtualHost 127.0.0.1:$port>
+ServerName http://localhost:$port
+
+TunnelPass https://$sslhost:$sslport/tunnel/localhost/$tport
+
+# Declare SSL certificates used in this virtual host
+#TunnelSSLCACertificateFile "$root/cert/ca.crt"
+TunnelSSLCertificateFile "$root/cert/tunnel.crt"
+TunnelSSLCertificateKeyFile "$root/cert/tunnel.key"
+
+</VirtualHost>
+
+EOF
+
diff --git a/sca-cpp/trunk/modules/http/vhost-conf b/sca-cpp/trunk/modules/http/vhost-conf
index 4f563b673e..9dff38d6e7 100755
--- a/sca-cpp/trunk/modules/http/vhost-conf
+++ b/sca-cpp/trunk/modules/http/vhost-conf
@@ -20,22 +20,23 @@
# Generate mass dynamic virtual hosting configuration
here=`readlink -f $0`; here=`dirname $here`
root=`readlink -f $1`
+
conf=`cat $root/conf/httpd.conf | grep "# Generated by: httpd-conf"`
host=`echo $conf | awk '{ print $6 }'`
-port=`echo $conf | awk '{ print $7 }' | awk -F "/" '{ print $1 }'`
-pport=`echo $conf | awk '{ print $7 }' | awk -F "/" '{ print $2 }'`
-if [ "$pport" = "" ]; then
- pport=$port
-fi
+addr=`echo $conf | awk '{ print $7 }'`
+port=`$here/httpd-addr port $addr`
+pport=`$here/httpd-addr pport $addr`
+vhost=`$here/httpd-addr vhost $addr`
+
htdocs=`echo $conf | awk '{ print $8 }'`
htdocs=`readlink -f $htdocs`
cat >>$root/conf/httpd.conf <<EOF
# Generated by: vhost-conf $*
# Enable mass dynamic virtual hosting
-NameVirtualHost *:$port
+NameVirtualHost $vhost
-<VirtualHost *:$port>
+<VirtualHost $vhost>
ServerName http://vhost.$host:$pport
ServerAlias *.$host
VirtualDocumentRoot $htdocs/domains/%1/
diff --git a/sca-cpp/trunk/modules/http/vhost-ssl-conf b/sca-cpp/trunk/modules/http/vhost-ssl-conf
index e6801248c4..433f26e6b3 100755
--- a/sca-cpp/trunk/modules/http/vhost-ssl-conf
+++ b/sca-cpp/trunk/modules/http/vhost-ssl-conf
@@ -20,24 +20,26 @@
# Generate mass dynamic virtual hosting configuration
here=`readlink -f $0`; here=`dirname $here`
root=`readlink -f $1`
+
conf=`cat $root/conf/httpd.conf | grep "# Generated by: httpd-conf"`
host=`echo $conf | awk '{ print $6 }'`
+
sslconf=`cat $root/conf/httpd.conf | grep "# Generated by: httpd-ssl-conf"`
-sslport=`echo $sslconf | awk '{ print $6 }' | awk -F "/" '{ print $1 }'`
-sslpport=`echo $sslconf | awk '{ print $6 }' | awk -F "/" '{ print $2 }'`
-if [ "$sslpport" = "" ]; then
- sslpport=$sslport
-fi
+ssladdr=`echo $sslconf | awk '{ print $6 }'`
+sslport=`$here/httpd-addr port $ssladdr`
+sslpport=`$here/httpd-addr pport $ssladdr`
+sslvhost=`$here/httpd-addr vhost $ssladdr`
+
htdocs=`echo $conf | awk '{ print $8 }'`
htdocs=`readlink -f $htdocs`
cat >>$root/conf/httpd.conf <<EOF
# Generated by: vhost-ssl-conf $*
# Enable mass dynamic virtual hosting over HTTPS
-NameVirtualHost *:$sslport
+NameVirtualHost $sslvhost
SSLStrictSNIVHostCheck Off
-<VirtualHost *:$sslport>
+<VirtualHost $sslvhost>
ServerName https://vhost.$host:$sslpport
ServerAlias *.$host
VirtualDocumentRoot $htdocs/domains/%1/
diff --git a/sca-cpp/trunk/modules/json/json.hpp b/sca-cpp/trunk/modules/json/json.hpp
index 1d966d3f67..4e02cbf2c9 100644
--- a/sca-cpp/trunk/modules/json/json.hpp
+++ b/sca-cpp/trunk/modules/json/json.hpp
@@ -397,6 +397,19 @@ const string funcName(const string& f) {
return f;
}
+/**
+ * Returns a list of param values other than the id and method args from a list
+ * of key value pairs.
+ */
+const list<value> queryParams(const list<list<value> >& a) {
+ if (isNil(a))
+ return list<value>();
+ const list<value> p = car(a);
+ if (car(p) == value("id") || car(p) == value("method"))
+ return queryParams(cdr(a));
+ return cons(cadr(p), queryParams(cdr(a)));
+}
+
}
}
diff --git a/sca-cpp/trunk/modules/server/client-test.hpp b/sca-cpp/trunk/modules/server/client-test.hpp
index 9b37a73803..f2fdb60877 100644
--- a/sca-cpp/trunk/modules/server/client-test.hpp
+++ b/sca-cpp/trunk/modules/server/client-test.hpp
@@ -31,7 +31,7 @@
#include "string.hpp"
#include "parallel.hpp"
#include "perf.hpp"
-#include "../http/curl.hpp"
+#include "../http/http.hpp"
namespace tuscany {
namespace server {
diff --git a/sca-cpp/trunk/modules/server/mod-eval.hpp b/sca-cpp/trunk/modules/server/mod-eval.hpp
index 0aff56f59d..0d90cb7ceb 100644
--- a/sca-cpp/trunk/modules/server/mod-eval.hpp
+++ b/sca-cpp/trunk/modules/server/mod-eval.hpp
@@ -37,7 +37,7 @@
#include "../atom/atom.hpp"
#include "../json/json.hpp"
#include "../scdl/scdl.hpp"
-#include "../http/curl.hpp"
+#include "../http/http.hpp"
#include "../http/httpd.hpp"
extern "C" {
@@ -113,7 +113,7 @@ const failable<int> get(request_rec* r, const lambda<value(const list<value>&)>&
const value func = c_str(json::funcName(string(cadr(ma))));
// Apply the requested function
- const failable<value> val = failableResult(impl(cons(func, httpd::queryParams(args))));
+ const failable<value> val = failableResult(impl(cons(func, json::queryParams(args))));
if (!hasContent(val))
return mkfailure<int>(reason(val));
@@ -250,6 +250,8 @@ const failable<int> del(request_rec* r, const lambda<value(const list<value>&)>&
* Translate a component request.
*/
int translate(request_rec *r) {
+ if(r->method_number != M_GET && r->method_number != M_POST && r->method_number != M_PUT && r->method_number != M_DELETE)
+ return DECLINED;
if (strncmp(r->uri, "/components/", 12) != 0)
return DECLINED;
r->handler = "mod_tuscany_eval";
@@ -544,8 +546,11 @@ const failable<bool> virtualHostCleanup(const ServerConf& sc) {
* HTTP request handler.
*/
int handler(request_rec *r) {
+ if(r->method_number != M_GET && r->method_number != M_POST && r->method_number != M_PUT && r->method_number != M_DELETE)
+ return DECLINED;
if(strcmp(r->handler, "mod_tuscany_eval"))
return DECLINED;
+
gc_scoped_pool pool(r->pool);
ScopedRequest sr(r);
httpdDebugRequest(r, "modeval::handler::input");
diff --git a/sca-cpp/trunk/modules/server/mod-wiring.cpp b/sca-cpp/trunk/modules/server/mod-wiring.cpp
index 964f7efc82..7ed47c7f48 100644
--- a/sca-cpp/trunk/modules/server/mod-wiring.cpp
+++ b/sca-cpp/trunk/modules/server/mod-wiring.cpp
@@ -299,13 +299,15 @@ const failable<bool> virtualHostConfig(ServerConf& sc, request_rec* r) {
* to the target component.
*/
int translate(request_rec *r) {
- gc_scoped_pool pool(r->pool);
+ if(r->method_number != M_GET && r->method_number != M_POST && r->method_number != M_PUT && r->method_number != M_DELETE)
+ return DECLINED;
- // No translation needed for a component request
+ // No translation needed for a component or tunnel request
if (!strncmp(r->uri, "/components/", 12))
return DECLINED;
// Get the server configuration
+ gc_scoped_pool pool(r->pool);
const ServerConf& sc = httpd::serverConf<ServerConf>(r, &mod_tuscany_wiring);
// Process dynamic virtual host configuration, if any
@@ -329,14 +331,17 @@ int translate(request_rec *r) {
* HTTP request handler, redirect to a target component.
*/
int handler(request_rec *r) {
- gc_scoped_pool pool(r->pool);
+ if(r->method_number != M_GET && r->method_number != M_POST && r->method_number != M_PUT && r->method_number != M_DELETE)
+ return DECLINED;
if(strcmp(r->handler, "mod_tuscany_wiring"))
return DECLINED;
+ if (r->filename == NULL || strncmp(r->filename, "/redirect:", 10) != 0)
+ return DECLINED;
+
+ gc_scoped_pool pool(r->pool);
httpdDebugRequest(r, "modwiring::handler::input");
// Do an internal redirect
- if (r->filename == NULL || strncmp(r->filename, "/redirect:", 10) != 0)
- return DECLINED;
debug(r->uri, "modwiring::handler::uri");
debug(r->filename, "modwiring::handler::filename");
debug(r->path_info, "modwiring::handler::path info");
@@ -364,7 +369,7 @@ const int postConfigMerge(const ServerConf& mainsc, server_rec* s) {
return postConfigMerge(mainsc, s->next);
}
-int postConfig(unused apr_pool_t *p, unused apr_pool_t *plog, unused apr_pool_t *ptemp, server_rec *s) {
+int postConfig(apr_pool_t *p, unused apr_pool_t *plog, unused apr_pool_t *ptemp, server_rec *s) {
gc_scoped_pool pool(p);
// Count the calls to post config, skip the first one as
diff --git a/sca-cpp/trunk/modules/server/server-conf b/sca-cpp/trunk/modules/server/server-conf
index 4a318c6fce..7c72233ca9 100755
--- a/sca-cpp/trunk/modules/server/server-conf
+++ b/sca-cpp/trunk/modules/server/server-conf
@@ -57,27 +57,11 @@ ssl=`cat $root/conf/httpd.conf | grep "# Generated by: httpd-ssl-conf"`
if [ "$ssl" != "" ]; then
cat >>$root/conf/httpd.conf <<EOF
# Configure SSL certificates
-SCAWiringSSLCACertificateFile "$root/conf/ca.crt"
-SCAWiringSSLCertificateFile "$root/conf/server.crt"
-SCAWiringSSLCertificateKeyFile "$root/conf/server.key"
+SCAWiringSSLCACertificateFile "$root/cert/ca.crt"
+SCAWiringSSLCertificateFile "$root/cert/server.crt"
+SCAWiringSSLCertificateKeyFile "$root/cert/server.key"
EOF
fi
-vhost=`cat $root/conf/httpd.conf | grep VirtualDocumentRoot`
-proxy=`cat $root/conf/httpd.conf | grep ProxyPass`
-
-vhost=`cat $root/conf/httpd.conf | grep "# Generated by: vhost-conf"`
-if [ "$vhost" != "" ]; then
- proxy=`cat $root/conf/httpd.conf | grep "# Generated by: proxy-conf"`
- if [ "$proxy" = "" ]; then
- cat >>$root/conf/httpd.conf <<EOF
-# Isolate requests from different virtual hosts
-MaxRequestsPerChild 1
-
-EOF
-
- fi
-fi
-