diff options
Diffstat (limited to 'sca-cpp/trunk')
47 files changed, 1667 insertions, 1770 deletions
diff --git a/sca-cpp/trunk/modules/http/Makefile.am b/sca-cpp/trunk/modules/http/Makefile.am index a504adcda5..42504d57ec 100644 --- a/sca-cpp/trunk/modules/http/Makefile.am +++ b/sca-cpp/trunk/modules/http/Makefile.am @@ -20,28 +20,28 @@ INCLUDES = -I${HTTPD_INCLUDE} incl_HEADERS = *.hpp incldir = $(prefix)/include/modules/http -dist_mod_SCRIPTS = httpd-conf httpd-addr httpd-start httpd-stop httpd-restart ssl-ca-conf ssl-cert-conf ssl-cert-find httpd-ssl-conf basic-auth-conf cert-auth-conf form-auth-conf open-auth-conf passwd-auth-conf group-auth-conf cache-conf cache-ssl-conf cache-manifest proxy-conf proxy-base-conf proxy-ssl-conf proxy-balancer-conf proxy-member-conf proxy-ssl-member-conf proxy-ssl-nossl-member-conf alt-host-conf mass-host-conf mass-host-ssl-conf httpd-tunnel-ssl-conf tunnel-ssl-conf httpd-worker-conf httpd-event-conf httpd-loglevel-conf minify-html minify-js minify-css +dist_mod_SCRIPTS = httpd-conf httpd-addr httpd-start httpd-stop httpd-restart ssl-ca-conf ssl-cert-conf ssl-cert-find httpd-ssl-conf base64-encode basic-auth-conf cert-auth-conf form-auth-conf open-auth-conf passwd-auth-conf group-auth-conf cache-conf cache-ssl-conf cache-manifest proxy-conf proxy-base-conf proxy-ssl-conf proxy-balancer-conf proxy-member-conf proxy-ssl-member-conf proxy-ssl-nossl-member-conf alt-host-conf mass-host-conf mass-host-ssl-conf httpd-tunnel-ssl-conf tunnel-ssl-conf httpd-worker-conf httpd-event-conf httpd-loglevel-conf minify-html minify-js minify-css moddir = $(prefix)/modules/http curl_test_SOURCES = curl-test.cpp -curl_test_LDFLAGS = -lxml2 -lcurl -lmozjs +curl_test_LDFLAGS = -lxml2 -lcurl -ljansson curl_get_SOURCES = curl-get.cpp -curl_get_LDFLAGS = -lxml2 -lcurl -lmozjs +curl_get_LDFLAGS = -lxml2 -lcurl -ljansson curl_connect_SOURCES = curl-connect.cpp -curl_connect_LDFLAGS = -lxml2 -lcurl -lmozjs +curl_connect_LDFLAGS = -lxml2 -lcurl -ljansson mod_LTLIBRARIES = libmod_tuscany_ssltunnel.la libmod_tuscany_openauth.la noinst_DATA = libmod_tuscany_ssltunnel${libsuffix} libmod_tuscany_openauth${libsuffix} libmod_tuscany_ssltunnel_la_SOURCES = mod-ssltunnel.cpp -libmod_tuscany_ssltunnel_la_LDFLAGS = -lxml2 -lcurl -lmozjs +libmod_tuscany_ssltunnel_la_LDFLAGS = -lxml2 -lcurl -ljansson libmod_tuscany_ssltunnel${libsuffix}: ln -s .libs/libmod_tuscany_ssltunnel${libsuffix} libmod_tuscany_openauth_la_SOURCES = mod-openauth.cpp -libmod_tuscany_openauth_la_LDFLAGS = -lxml2 -lcurl -lmozjs +libmod_tuscany_openauth_la_LDFLAGS = -lxml2 -lcurl -ljansson libmod_tuscany_openauth${libsuffix}: ln -s .libs/libmod_tuscany_openauth${libsuffix} @@ -82,7 +82,7 @@ modsecuritydir = $(prefix)/modules/http endif -dist_noinst_SCRIPTS = httpd-test http-test proxy-test +dist_noinst_SCRIPTS = httpd-test http-test proxy-test httpd-memgrind httpd-callgrind 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 index 9f5ee17368..6e16da7163 100644 --- a/sca-cpp/trunk/modules/http/curl-connect.cpp +++ b/sca-cpp/trunk/modules/http/curl-connect.cpp @@ -34,14 +34,14 @@ namespace tuscany { namespace http { const bool testConnect(const string& url, const string& ca = "", const string& cert = "", const string& key = "") { - gc_scoped_pool p; + const gc_scoped_pool p; - CURLSession cs(ca, cert, key, "", 0); + const CURLSession cs(ca, cert, key, "", 0); 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); + const 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); @@ -53,7 +53,7 @@ const bool testConnect(const string& url, const string& ca = "", const string& c const apr_pollfd_t* pollfds; apr_int32_t pollcount; for(;;) { - apr_status_t pollrc = apr_pollset_poll(pollset, -1, &pollcount, &pollfds); + const apr_status_t pollrc = apr_pollset_poll(pollset, -1, &pollcount, &pollfds); assert(pollrc == APR_SUCCESS); for (; pollcount > 0; pollcount--, pollfds++) { @@ -88,7 +88,7 @@ const bool testConnect(const string& url, const string& ca = "", const string& c } } -int main(unused const int argc, const char** argv) { +int main(unused const int argc, const char** const argv) { if (argc > 2) tuscany::http::testConnect(tuscany::string(argv[1]), tuscany::string(argv[2]), tuscany::string(argv[3]), tuscany::string(argv[4])); else diff --git a/sca-cpp/trunk/modules/http/curl-get.cpp b/sca-cpp/trunk/modules/http/curl-get.cpp index a16daeeae3..983dd20fc5 100644 --- a/sca-cpp/trunk/modules/http/curl-get.cpp +++ b/sca-cpp/trunk/modules/http/curl-get.cpp @@ -33,7 +33,7 @@ namespace tuscany { namespace http { const bool testGet(const string& url, const string& ca = "", const string& cert = "", const string& key = "") { - CURLSession ch(ca, cert, key, "", 0); + const CURLSession ch(ca, cert, key, "", 0); const failable<value> val = get(url, ch); assert(hasContent(val)); cout << content(val) << endl; @@ -43,7 +43,7 @@ const bool testGet(const string& url, const string& ca = "", const string& cert } } -int main(unused const int argc, const char** argv) { +int main(unused const int argc, const char** const argv) { if (argc > 2) tuscany::http::testGet(tuscany::string(argv[1]), tuscany::string(argv[2]), tuscany::string(argv[3]), tuscany::string(argv[4])); else diff --git a/sca-cpp/trunk/modules/http/curl-test.cpp b/sca-cpp/trunk/modules/http/curl-test.cpp index f0806ea577..6a1174a404 100644 --- a/sca-cpp/trunk/modules/http/curl-test.cpp +++ b/sca-cpp/trunk/modules/http/curl-test.cpp @@ -40,7 +40,7 @@ ostream* curlWriter(const string& s, ostream* os) { } const bool testGet() { - CURLSession ch("", "", "", "", 0); + const CURLSession ch("", "", "", "", 0); { ostringstream os; const failable<list<ostream*> > r = get<ostream*>(curlWriter, &os, testURI, ch); @@ -56,21 +56,14 @@ const bool testGet() { return true; } -struct getLoop { - CURLSession& ch; - getLoop(CURLSession& ch) : ch(ch) { - } - const bool operator()() const { +const bool testGetPerf() { + const CURLSession ch("", "", "", "", 0); + blambda gl = [ch]() -> const bool { const failable<value> r = getcontent(testURI, ch); assert(hasContent(r)); assert(contains(car(reverse(list<value>(content(r)))), "It works")); return true; - } -}; - -const bool testGetPerf() { - CURLSession ch("", "", "", "", 0); - lambda<bool()> gl = getLoop(ch); + }; cout << "Static GET test " << time(gl, 5, 200) << " ms" << endl; return true; } @@ -79,7 +72,7 @@ const bool testGetPerf() { } int main() { - tuscany::gc_scoped_pool p; + const tuscany::gc_scoped_pool p; tuscany::cout << "Testing..." << tuscany::endl; //tuscany::http::testURI = tuscany::string("http://") + tuscany::http::hostName() + ":8090"; diff --git a/sca-cpp/trunk/modules/http/http.hpp b/sca-cpp/trunk/modules/http/http.hpp index 408b9fdee5..1153f61840 100644 --- a/sca-cpp/trunk/modules/http/http.hpp +++ b/sca-cpp/trunk/modules/http/http.hpp @@ -71,86 +71,91 @@ public: */ class CURLSession { public: - CURLSession() : h(NULL), p(), sock(NULL), wpollset(NULL), wpollfd(NULL), rpollset(NULL), rpollfd(NULL), owner(false), ca(""), cert(""), key(""), cookie(""), timeout(0) { + CURLSession() : p(), h(*(new (gc_new<handles>()) handles())), owner(false), ca(emptyString), cert(emptyString), key(emptyString), cookie(emptyString), timeout(0) { } - CURLSession(const string& ca, const string& cert, const string& key, const string& cookie, const int timeout) : h(NULL), p(), sock(NULL), wpollset(NULL), wpollfd(NULL), rpollset(NULL), rpollfd(NULL), owner(true), ca(ca), cert(cert), key(key), cookie(cookie), timeout(timeout) { + CURLSession(const string& ca, const string& cert, const string& key, const string& cookie, const int timeout) : p(), h(*(new (gc_new<handles>()) handles())), owner(true), ca(ca), cert(cert), key(key), cookie(cookie), timeout(timeout) { } - 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), cookie(c.cookie), timeout(c.timeout) { + CURLSession(const CURLSession& c) : p(c.p), h(c.h), owner(false), ca(c.ca), cert(c.cert), key(c.key), cookie(c.cookie), timeout(c.timeout) { } - const CURLSession& operator=(const CURLSession& c) { - if(this == &c) - return *this; - 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; - cookie = c.cookie; - timeout = c.timeout; - return *this; - } + CURLSession& operator=(const CURLSession& c) = delete; ~CURLSession() { if (!owner) return; - if (h == NULL) + if (h.h == NULL) return; - curl_easy_cleanup(h); + debug(h.h, "http::~CURLSession::cleanup::h"); + curl_easy_cleanup(h.h); } private: - CURL* h; - gc_child_pool p; - apr_socket_t* sock; - apr_pollset_t* wpollset; - apr_pollfd_t* wpollfd; - apr_pollset_t* rpollset; - apr_pollfd_t* rpollfd; - bool owner; - - friend CURL* handle(const CURLSession& cs); - friend apr_socket_t* sock(const CURLSession& cs); - friend const failable<CURL*> setup(const string& url, CURLSession& cs); - friend const failable<bool> cleanup(CURLSession& cs); - friend const failable<bool> connect(const string& url, CURLSession& cs); - friend const failable<bool> send(const char* c, const size_t l, CURLSession& cs); - friend const failable<size_t> recv(char* c, const size_t l, CURLSession& cs); + class handles { + public: + handles() : h(NULL), sock(NULL), wpollset(NULL), wpollfd(NULL), rpollset(NULL), rpollfd(NULL) { + } + + handles(const handles& c) : h(c.h), sock(c.sock), wpollset(c.wpollset), wpollfd(c.wpollfd), rpollset(c.rpollset), rpollfd(c.rpollfd) { + } + + private: + CURL* h; + apr_socket_t* sock; + apr_pollset_t* wpollset; + apr_pollfd_t* wpollfd; + apr_pollset_t* rpollset; + apr_pollfd_t* rpollfd; + + friend class CURLSession; + friend CURL* const handle(const CURLSession& cs); + friend apr_socket_t* const sock(const CURLSession& cs); + friend const failable<CURL*> setup(const string& url, const CURLSession& cs); + friend const failable<bool> cleanup(const CURLSession& cs); + friend const failable<bool> connect(const string& url, const CURLSession& cs); + friend const failable<bool> send(const char* const c, const size_t l, const CURLSession& cs); + friend const failable<size_t> recv(char* const c, const size_t l, const CURLSession& cs); + }; + + const gc_child_pool p; + handles& h; + const bool owner; + + friend CURL* const handle(const CURLSession& cs); + friend apr_socket_t* const sock(const CURLSession& cs); + friend const failable<CURL*> setup(const string& url, const CURLSession& cs); + friend const failable<bool> cleanup(const CURLSession& cs); + friend const failable<bool> connect(const string& url, const CURLSession& cs); + friend const failable<bool> send(const char* const c, const size_t l, const CURLSession& cs); + friend const failable<size_t> recv(char* const c, const size_t l, const CURLSession& cs); public: - string ca; - string cert; - string key; - string cookie; - int timeout; + const string ca; + const string cert; + const string key; + const string cookie; + const int timeout; }; /** * Returns the CURL handle used by a CURL session. */ -CURL* handle(const CURLSession& cs) { - return cs.h; +CURL* const handle(const CURLSession& cs) { + return cs.h.h; } /** * Return an apr_socket_t for the socket used by a CURL session. */ -apr_socket_t* sock(const CURLSession& cs) { - return cs.sock; +apr_socket_t* const sock(const CURLSession& cs) { + return cs.h.sock; } /** * Convert a socket fd to an apr_socket_t. */ -apr_socket_t* sock(const int sd, const gc_pool& p) { +apr_socket_t* const sock(const int sd, const gc_pool& p) { int fd = sd; apr_socket_t* s = NULL; apr_os_sock_put(&s, &fd, pool(p)); @@ -160,14 +165,14 @@ apr_socket_t* sock(const int sd, const gc_pool& p) { /** * Convert a CURL return code to an error string. */ -const string curlreason(CURLcode rc) { +const string curlreason(const CURLcode rc) { return curl_easy_strerror(rc); } /** * Convert an APR status to an error string. */ -const string apreason(apr_status_t rc) { +const string apreason(const apr_status_t rc) { char buf[256]; return apr_strerror(rc, buf, sizeof(buf)); } @@ -178,7 +183,7 @@ const string apreason(apr_status_t rc) { const char escape_c2x[] = "0123456789ABCDEF"; const string escape(const string& unesc, const char* reserv) { - char* copy = (char*)apr_palloc(gc_current_pool(), 3 * length(unesc) + 3); + char* const copy = (char*)apr_palloc(gc_current_pool(), 3 * length(unesc) + 3); const unsigned char* s = (const unsigned char *)c_str(unesc); unsigned char* d = (unsigned char*)copy; unsigned c; @@ -225,9 +230,9 @@ const string hostName(const string& uri, const gc_pool& p) { apr_uri_t u; const apr_status_t rc = apr_uri_parse(pool(p), c_str(uri), &u); if (rc != APR_SUCCESS) - return ""; + return emptyString; if (u.hostname == NULL) - return ""; + return emptyString; return u.hostname; } @@ -238,9 +243,9 @@ const string scheme(const string& uri, const gc_pool& p) { apr_uri_t u; const apr_status_t rc = apr_uri_parse(pool(p), c_str(uri), &u); if (rc != APR_SUCCESS) - return ""; + return emptyString; if (u.scheme == NULL) - return ""; + return emptyString; return u.scheme; } @@ -262,13 +267,14 @@ const string topDomain(const string& host) { /** * Setup a CURL session */ -const failable<CURL*> setup(const string& url, CURLSession& cs) { +const failable<CURL*> setup(const string& url, const CURLSession& cs) { // Init CURL session - if (cs.h != NULL) + if (cs.h.h != NULL) cleanup(cs); - cs.h = curl_easy_init(); - CURL* ch = cs.h; + cs.h.h = curl_easy_init(); + debug(cs.h.h, "http::setup::init::h"); + CURL* const ch = cs.h.h; curl_easy_setopt(ch, CURLOPT_USERAGENT, "libcurl/1.0"); #ifdef WANT_MAINTAINER_CURL_VERBOSE curl_easy_setopt(ch, CURLOPT_VERBOSE, true); @@ -279,34 +285,35 @@ const failable<CURL*> setup(const string& url, CURLSession& cs) { curl_easy_setopt(ch, CURLOPT_FOLLOWLOCATION, true); curl_easy_setopt(ch, CURLOPT_POSTREDIR, CURL_REDIR_POST_ALL); curl_easy_setopt(ch, CURLOPT_NOSIGNAL, 1); + curl_easy_setopt(ch, CURLOPT_DNS_USE_GLOBAL_CACHE, 0); curl_easy_setopt(ch, CURLOPT_TIMEOUT, cs.timeout); // Setup SSL options - if (cs.ca != "") { + if (cs.ca != emptyString) { debug(cs.ca, "http::setup::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 != "") { + if (cs.cert != emptyString) { debug(cs.cert, "http::setup::cert"); curl_easy_setopt(ch, CURLOPT_SSLCERT, c_str(cs.cert)); curl_easy_setopt(ch, CURLOPT_SSLCERTTYPE, "PEM"); } - if (cs.key != "") { + if (cs.key != emptyString) { debug(cs.key, "http::setup::key"); curl_easy_setopt(ch, CURLOPT_SSLKEY, c_str(cs.key)); curl_easy_setopt(ch, CURLOPT_SSLKEYTYPE, "PEM"); } - if (cs.cookie != "") { + if (cs.cookie != emptyString) { debug(cs.cookie, "http::setup::cookie"); curl_easy_setopt(ch, CURLOPT_COOKIE, c_str(cs.cookie)); } // Set up HTTP basic auth if requested apr_uri_t u; - apr_pool_t* p = gc_current_pool(); + apr_pool_t* const p = gc_current_pool(); const apr_status_t prc = apr_uri_parse(p, c_str(url), &u); if (prc == APR_SUCCESS) { if (u.user != NULL) { @@ -336,11 +343,12 @@ const failable<CURL*> setup(const string& url, CURLSession& cs) { /** * Cleanup a CURL session */ -const failable<bool> cleanup(CURLSession& cs) { - if (cs.h == NULL) +const failable<bool> cleanup(const CURLSession& cs) { + if (cs.h.h == NULL) return true; - curl_easy_cleanup(cs.h); - cs.h = NULL; + debug(cs.h.h, "http::cleanup::cleanup::h"); + curl_easy_cleanup(cs.h.h); + cs.h.h = NULL; return true; } @@ -351,15 +359,16 @@ class CURLReadContext { public: CURLReadContext(const list<string>& ilist) : ilist(ilist) { } - list<string> ilist; + + gc_mutable_ref<list<string> > ilist; }; /** * Called by CURL to read data to send. */ size_t readCallback(void *ptr, size_t size, size_t nmemb, void *data) { - CURLReadContext& rcx = *static_cast<CURLReadContext*>(data); - if (isNil(rcx.ilist)) + CURLReadContext& rcx = *(CURLReadContext*)data; + if (isNil((const list<string>)rcx.ilist)) return 0; const list<string> f(fragment(rcx.ilist, size * nmemb)); const string s = car(f); @@ -373,17 +382,18 @@ size_t readCallback(void *ptr, size_t size, size_t nmemb, void *data) { */ template<typename R> class CURLWriteContext { public: - CURLWriteContext(const lambda<R(const string&, const R)>& reduce, const R& accum) : reduce(reduce), accum(accum) { + CURLWriteContext(const lambda<const R(const string&, const R)>& reduce, const R& accum) : reduce(reduce), accum(accum) { } - const lambda<R(const string&, const R)> reduce; - R accum; + + const lambda<const R(const string&, const R)> reduce; + gc_mutable_ref<R> accum; }; /** * Called by CURL to write received data. */ template<typename R> size_t writeCallback(void *ptr, size_t size, size_t nmemb, void *data) { - CURLWriteContext<R>& wcx = *(static_cast<CURLWriteContext<R>*> (data)); + CURLWriteContext<R>& wcx = *(CURLWriteContext<R>*)data; const size_t realsize = size * nmemb; wcx.accum = wcx.reduce(string((const char*)ptr, realsize), wcx.accum); return realsize; @@ -393,13 +403,13 @@ template<typename R> size_t writeCallback(void *ptr, size_t size, size_t nmemb, * Apply an HTTP verb to a list containing a list of headers and a list of content, and * a reduce function used to process the response. */ -curl_slist* headers(curl_slist* cl, const list<string>& h) { +curl_slist* headers(curl_slist* const cl, const list<string>& h) { if (isNil(h)) return cl; return headers(curl_slist_append(cl, c_str(string(car(h)))), cdr(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, CURLSession& cs) { +template<typename R> const failable<list<R> > apply(const list<list<string> >& hdr, const lambda<const R(const string&, const R)>& reduce, const R& initial, const string& url, const string& verb, const CURLSession& cs) { debug(url, "http::apply::url"); debug(verb, "http::apply::verb"); @@ -409,12 +419,12 @@ template<typename R> const failable<list<R> > apply(const list<list<string> >& h cleanup(cs); return mkfailure<list<R>>(fch); } - CURL* ch = content(fch); + CURL* const ch = content(fch); // Set the request headers curl_slist* hl = headers(NULL, car(hdr)); - if (hl != NULL) - curl_easy_setopt(ch, CURLOPT_HTTPHEADER, hl); + hl = curl_slist_append(hl, "X-Accept: text/x-scheme; charset=utf-8"); + curl_easy_setopt(ch, CURLOPT_HTTPHEADER, hl); // Convert request body to a string // TODO use HTTP chunking instead @@ -462,9 +472,7 @@ template<typename R> const failable<list<R> > apply(const list<list<string> >& h curl_easy_getinfo (ch, CURLINFO_RESPONSE_CODE, &httprc); if (httprc != 200 && httprc != 201) { cleanup(cs); - ostringstream es; - es << "HTTP code " << httprc; - return mkfailure<list<R> >(str(es)); + return mkfailure<list<R> >(string("HTTP code not 200"), (int)httprc, (httprc != 301 && httprc != 302 && httprc != 404)); } cleanup(cs); @@ -474,13 +482,12 @@ 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, CURLSession& cs) { +const failable<value> evalExpr(const value& expr, const string& url, const CURLSession& cs) { debug(url, "http::evalExpr::url"); debug(expr, "http::evalExpr::input"); // Convert expression to a JSON-RPC request - js::JSContext cx; - const failable<list<string> > jsreq = json::jsonRequest(1, car<value>(expr), cdr<value>(expr), cx); + const failable<list<string> > jsreq = json::jsonRequest(1, car<value>(expr), cdr<value>(expr)); if (!hasContent(jsreq)) return mkfailure<value>(jsreq); @@ -491,7 +498,7 @@ const failable<value> evalExpr(const value& expr, const string& url, CURLSession return mkfailure<value>(res); // Parse and return JSON-RPC result - const failable<value> rval = json::jsonResultValue(cadr<list<string> >(content(res)), cx); + const failable<value> rval = json::jsonResultValue(cadr<list<string> >(content(res))); debug(rval, "http::evalExpr::result"); if (!hasContent(rval)) return mkfailure<value>(rval); @@ -501,7 +508,7 @@ const failable<value> evalExpr(const value& expr, const string& url, CURLSession /** * Find and return a header. */ -const maybe<string> header(const char* prefix, const list<string>& h) { +const maybe<string> header(const char* const prefix, const list<string>& h) { if (isNil(h)) return maybe<string>(); const string s = car(h); @@ -516,7 +523,7 @@ const maybe<string> header(const char* prefix, const list<string>& h) { */ const string location(const list<string>& h) { const maybe<string> l = header("Location: ", h); - return hasContent(l)? content(l) : ""; + return hasContent(l)? content(l) : emptyString; } /** @@ -524,7 +531,7 @@ const string location(const list<string>& h) { */ const value entryId(const failable<string> l) { if (!hasContent(l)) - return list<value>(); + return nilListValue; const string ls(content(l)); return value(mklist<value>(string(substr(ls, find_last(ls, '/') + 1)))); } @@ -534,13 +541,13 @@ const value entryId(const failable<string> l) { */ const string contentType(const list<string>& h) { const maybe<string> ct = header("Content-Type: ", h); - return hasContent(ct)? content(ct) : ""; + return hasContent(ct)? content(ct) : emptyString; } /** * 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, CURLSession& cs) { +template<typename R> const failable<list<R> > get(const lambda<const 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", cs); @@ -549,7 +556,7 @@ template<typename R> const failable<list<R> > get(const lambda<R(const string&, /** * HTTP GET, return a list of values representing the resource at the given URL. */ -const failable<value> getcontent(const string& url, CURLSession& cs) { +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 @@ -576,6 +583,15 @@ const failable<value> responseValue(const list<list<string> > res) { const list<string> ls(reverse(cadr(res))); debug(ls, "http::responseValue::content"); + if (contains(ct, "text/x-scheme")) { + // Read a Scheme value + ostringstream os; + write(ls, os); + istringstream is(str(os)); + const value val(content(scheme::readValue(is))); + debug(val, "http::responseValue::result"); + return val; + } if (atom::isATOMEntry(ls)) { // Read an ATOM entry const value val(elementsToValues(content(atom::readATOMEntry(ls)))); @@ -596,8 +612,7 @@ const failable<value> responseValue(const list<list<string> > res) { } if (contains(ct, "text/javascript") || contains(ct, "application/json") || json::isJSON(ls)) { // Read a JSON document - js::JSContext cx; - const value val(json::jsonValues(content(json::readJSON(ls, cx)))); + const value val(content(json::readValue(ls))); debug(val, "http::responseValue::result"); return val; } @@ -612,14 +627,13 @@ const failable<value> responseValue(const list<list<string> > res) { const list<string> jls = mklist<string>(substr(s, fp + 1, lp - (fp + 1))); debug(jls, "http::responseValue::javascript::content"); - js::JSContext cx; - const value val(json::jsonValues(content(json::readJSON(jls, cx)))); + const value val(content(json::readValue(jls))); debug(val, "http::responseValue::result"); return val; } - if (contains(ct, "text/xml") || contains(ct, "application/xml") || isXML(ls)) { + if (contains(ct, "text/xml") || contains(ct, "application/xml") || xml::isXML(ls)) { // Read an XML document - const value val(elementsToValues(readXML(ls))); + const value val(elementsToValues(content(xml::readElements(ls)))); debug(val, "http::responseValue::result"); return val; } @@ -633,7 +647,7 @@ const failable<value> responseValue(const list<list<string> > res) { /** * HTTP GET, return a list of values representing the resource at the given URL. */ -const failable<value> get(const string& url, CURLSession& cs) { +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 @@ -661,58 +675,41 @@ const failable<list<list<string> > > writeRequest(const failable<list<string> >& */ const failable<list<list<string> > > contentRequest(const value& c, unused const string& url) { - // Check if the client requested a specific format - //TODO derive that from given URL - const list<value> fmt = assoc<value>("format", list<value>()); - - // Write as a scheme value if requested by the client - if (!isNil(fmt) && cadr(fmt) == "scheme") - return writeRequest(mklist<string>(scheme::writeValue(c)), "text/plain; charset=utf-8"); + // Write in the format requested by the client, if any + const list<value> fmt = assoc<value>("format", nilListValue); + if (!isNil(fmt)) { + if (cadr(fmt) == "scheme") + return writeRequest(scheme::writeValue(c), "text/x-scheme; charset=utf-8"); + if (cadr(fmt) == "json") + return writeRequest(json::writeValue(c), "application/json; charset=utf-8"); + if (cadr(fmt) == "xml") + return writeRequest(xml::writeElements(valuesToElements(c)), "text/xml; charset=utf-8"); + } // Write a simple value as a JSON value if (!isList(c)) { - js::JSContext cx; - if (isSymbol(c)) { - const list<value> lc = mklist<value>(mklist<value>("name", value(string(c)))); - debug(lc, "http::contentRequest::symbol"); - return writeRequest(json::writeJSON(valuesToElements(lc), cx), "application/json; charset=utf-8"); - } - const list<value> lc = mklist<value>(mklist<value>("value", c)); - debug(lc, "http::contentRequest::value"); - return writeRequest(json::writeJSON(valuesToElements(lc), cx), "application/json; charset=utf-8"); + debug(c, "http::contentRequest::value"); + return writeRequest(json::writeValue(c), "application/json; charset=utf-8"); } - // Write an empty list as a JSON empty value + // Write an empty list as a JSON value if (isNil((list<value>)c)) { - js::JSContext cx; - debug(list<value>(), "http::contentRequest::empty"); - return writeRequest(json::writeJSON(list<value>(), cx), "application/json; charset=utf-8"); + debug(nilListValue, "http::contentRequest::empty"); + return writeRequest(json::writeValue(c), "application/json; charset=utf-8"); } // Write content-type / content-list pair if (isString(car<value>(c)) && !isNil(cdr<value>(c)) && isList(cadr<value>(c))) return writeRequest(convertValues<string>(cadr<value>(c)), car<value>(c)); - // Write an assoc value as JSON + // Write an assoc value as a JSON value if (isSymbol(car<value>(c)) && !isNil(cdr<value>(c))) { - js::JSContext cx; - const list<value> lc = mklist<value>(c); - debug(lc, "http::contentRequest::assoc"); - debug(valuesToElements(lc), "http::contentRequest::assoc::element"); - return writeRequest(json::writeJSON(valuesToElements(lc), cx), "application/json; charset=utf-8"); - } - - // Write value as JSON if requested by the client - if (!isNil(fmt) && cadr(fmt) == "json") { - js::JSContext cx; - return writeRequest(json::writeJSON(valuesToElements(c), cx), "application/json; charset=utf-8"); + debug(c, "http::contentRequest::assoc"); + return writeRequest(json::writeValue(c), "application/json; charset=utf-8"); } - // Convert list of values to element values - const list<value> e = valuesToElements(c); - debug(e, "http::contentRequest::elements"); - // Write an ATOM feed or entry + const list<value> e = valuesToElements(c); if (isList(car<value>(e)) && !isNil(car<value>(e))) { const list<value> el = car<value>(e); if (isSymbol(car<value>(el)) && car<value>(el) == element && !isNil(cdr<value>(el)) && isSymbol(cadr<value>(el)) && elementHasChildren(el) && !elementHasValue(el)) { @@ -724,14 +721,13 @@ const failable<list<list<string> > > contentRequest(const value& c, unused const } // Write any other compound value as a JSON value - js::JSContext cx; - return writeRequest(json::writeJSON(e, cx), "application/json; charset=utf-8"); + return writeRequest(json::writeValue(c), "application/json; charset=utf-8"); } /** * HTTP POST. */ -const failable<value> post(const value& val, const string& url, CURLSession& cs) { +const failable<value> post(const value& val, const string& url, const CURLSession& cs) { debug(url, "http::post::url"); // Convert value to a content request @@ -760,7 +756,7 @@ const failable<value> post(const value& val, const string& url, CURLSession& cs) /** * HTTP PUT. */ -const failable<value> put(const value& val, const string& url, CURLSession& cs) { +const failable<value> put(const value& val, const string& url, const CURLSession& cs) { debug(url, "http::put::url"); // Convert value to a content request @@ -775,13 +771,13 @@ const failable<value> put(const value& val, const string& url, CURLSession& cs) return mkfailure<value>(res); debug(true, "http::put::result"); - return value(true); + return trueValue; } /** * HTTP PATCH. */ -const failable<value> patch(const value& val, const string& url, CURLSession& cs) { +const failable<value> patch(const value& val, const string& url, const CURLSession& cs) { debug(url, "http::put::patch"); // Convert value to a content request @@ -796,13 +792,13 @@ const failable<value> patch(const value& val, const string& url, CURLSession& cs return mkfailure<value>(res); debug(true, "http::patch::result"); - return value(true); + return trueValue; } /** * HTTP DELETE. */ -const failable<value, string> del(const string& url, CURLSession& cs) { +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>()); @@ -811,7 +807,7 @@ const failable<value, string> del(const string& url, CURLSession& cs) { return mkfailure<value>(res); debug(true, "http::delete::result"); - return value(true); + return trueValue; } /** @@ -827,7 +823,7 @@ 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* const pollfd(apr_socket_t* const 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; @@ -841,7 +837,7 @@ apr_pollfd_t* pollfd(apr_socket_t* s, const int e, const gc_pool& p) { /** * Connect to a URL. */ -const failable<bool> connect(const string& url, CURLSession& cs) { +const failable<bool> connect(const string& url, const CURLSession& cs) { debug(url, "http::connect::url"); // Setup the CURL session @@ -850,7 +846,7 @@ const failable<bool> connect(const string& url, CURLSession& cs) { cleanup(cs); return mkfailure<bool>(fch); } - CURL* ch = content(fch); + CURL* const ch = content(fch); // Connect curl_easy_setopt(ch, CURLOPT_CONNECT_ONLY, true); @@ -867,23 +863,23 @@ const failable<bool> connect(const string& url, CURLSession& cs) { cleanup(cs); return mkfailure<bool>(string(curl_easy_strerror(grc))); } - cs.sock = sock(sd, cs.p); + cs.h.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); + const apr_status_t rpcrc = apr_pollset_create(&cs.h.rpollset, 1, pool(cs.p), 0); if (rpcrc != APR_SUCCESS) { cleanup(cs); 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); + cs.h.rpollfd = pollfd(cs.h.sock, APR_POLLIN, cs.p); + apr_pollset_add(cs.h.rpollset, cs.h.rpollfd); + const apr_status_t wpcrc = apr_pollset_create(&cs.h.wpollset, 1, pool(cs.p), 0); if (wpcrc != APR_SUCCESS) { cleanup(cs); return mkfailure<bool>(apreason(wpcrc)); } - cs.wpollfd = pollfd(cs.sock, APR_POLLOUT, cs.p); - apr_pollset_add(cs.wpollset, cs.wpollfd); + cs.h.wpollfd = pollfd(cs.h.sock, APR_POLLOUT, cs.p); + apr_pollset_add(cs.h.wpollset, cs.h.wpollfd); return true; } @@ -891,11 +887,11 @@ const failable<bool> connect(const string& url, CURLSession& cs) { /** * Send an array of chars. */ -const failable<bool> send(const char* c, const size_t l, CURLSession& cs) { +const failable<bool> send(const char* const c, const size_t l, const CURLSession& cs) { // Send the data size_t wl = 0; - const CURLcode rc = curl_easy_send(cs.h, c, (size_t)l, &wl); + const CURLcode rc = curl_easy_send(cs.h.h, c, (size_t)l, &wl); if (rc == CURLE_OK && wl == (size_t)l) return true; if (rc != CURLE_AGAIN) { @@ -906,7 +902,7 @@ const failable<bool> send(const char* c, const size_t l, CURLSession& cs) { // 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); + const apr_status_t pollrc = apr_pollset_poll(cs.h.wpollset, -1, &pollcount, &pollfds); if (pollrc != APR_SUCCESS) return mkfailure<bool>(apreason(pollrc)); @@ -917,11 +913,11 @@ const failable<bool> send(const char* c, const size_t l, CURLSession& cs) { /** * Receive an array of chars. */ -const failable<size_t> recv(char* c, const size_t l, CURLSession& cs) { +const failable<size_t> recv(char* const c, const size_t l, const CURLSession& cs) { // Receive data size_t rl; - const CURLcode rc = curl_easy_recv(cs.h, c, (size_t)l, &rl); + const CURLcode rc = curl_easy_recv(cs.h.h, c, (size_t)l, &rl); if (rc == CURLE_OK) return (size_t)rl; if (rc == 1) @@ -934,7 +930,7 @@ const failable<size_t> recv(char* c, const size_t l, CURLSession& cs) { // 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); + const apr_status_t pollrc = apr_pollset_poll(cs.h.rpollset, -1, &pollcount, &pollfds); if (pollrc != APR_SUCCESS) { cleanup(cs); return mkfailure<size_t>(apreason(pollrc)); @@ -990,8 +986,9 @@ const value escapeQuery(const value& arg) { /** * HTTP client proxy function. */ -struct proxy { - proxy(const string& uri, const string& ca, const string& cert, const string& key, const string& cookie, const int timeout, const gc_pool& p) : p(p), uri(uri), ca(ca), cert(cert), key(key), cookie(cookie), cs(*(new (gc_new<CURLSession>(p)) CURLSession(ca, cert, key, cookie, timeout))) { +class proxy { +public: + proxy(const string& uri, const string& ca, const string& cert, const string& key, const string& cookie, const int timeout) : uri(uri), cs(mksession(ca, cert, key, cookie, timeout)) { } const value operator()(const list<value>& args) const { @@ -1001,39 +998,44 @@ struct proxy { const list<value> lp = filter<value>(filterPath, cadr(args)); debug(lp, "http::proxy::path"); const list<value> lq = map<value, value>(escapeQuery, filter<value>(filterQuery, cadr(args))); - debug(lp, "http::proxy::query"); - const value p = path(lp); + debug(lq, "http::proxy::query"); const value q = queryString(lq); - const failable<value> val = get(uri + p + (q != ""? string("?") + q : string("")), cs); + const failable<value> val = get(uri + (string)path(lp) + (q != emptyString? string("?") + (string)q : emptyString), *cs); return content(val); } if (fun == "post") { - const failable<value> val = post(caddr(args), uri + path(cadr(args)), cs); + const failable<value> val = post(caddr(args), uri + (string)path(cadr(args)), *cs); return content(val); } if (fun == "put") { - const failable<value> val = put(caddr(args), uri + path(cadr(args)), cs); + const failable<value> val = put(caddr(args), uri + (string)path(cadr(args)), *cs); return content(val); } if (fun == "patch") { - const failable<value> val = patch(caddr(args), uri + path(cadr(args)), cs); + const failable<value> val = patch(caddr(args), uri + (string)path(cadr(args)), *cs); return content(val); } if (fun == "delete") { - const failable<value> val = del(uri + path(cadr(args)), cs); + const failable<value> val = del(uri + (string)path(cadr(args)), *cs); return content(val); } - const failable<value> val = evalExpr(args, uri, cs); + const failable<value> val = evalExpr(args, uri, *cs); return content(val); } - const gc_pool p; +private: const string uri; - const string ca; - const string cert; - const string key; - const string cookie; - CURLSession& cs; + const perthread_ptr<http::CURLSession> cs; + + + const perthread_ptr<http::CURLSession> mksession(const string& ca, const string& cert, const string& key, const string& cookie, const int timeout) { + const gc_pool cp = gc_current_pool(); + const lambda<const gc_ptr<http::CURLSession>()> newsession = [ca, cert, key, cookie, timeout, cp]() -> const gc_ptr<http::CURLSession> { + const gc_scoped_pool sp(pool(cp)); + return new (gc_new<http::CURLSession>()) http::CURLSession(ca, cert, key, cookie, timeout); + }; + return *(new (gc_new<perthread_ptr<http::CURLSession> >()) perthread_ptr<CURLSession>(newsession)); + } }; } diff --git a/sca-cpp/trunk/modules/http/httpd-callgrind b/sca-cpp/trunk/modules/http/httpd-callgrind new file mode 100755 index 0000000000..964b046638 --- /dev/null +++ b/sca-cpp/trunk/modules/http/httpd-callgrind @@ -0,0 +1,25 @@ +#!/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. + +# Start httpd server +here=`echo "import os; print os.path.realpath('$0')" | python`; here=`dirname $here` +root=`echo "import os; print os.path.realpath('$1')" | python` + +httpd=`cat $here/httpd.prefix` +$here/../../etc/callgrind $httpd/bin/httpd -X -E $root/logs/error_log -d $root -f $root/conf/httpd.conf diff --git a/sca-cpp/trunk/modules/http/httpd.hpp b/sca-cpp/trunk/modules/http/httpd.hpp index 6470d6c587..e090c2fc35 100644 --- a/sca-cpp/trunk/modules/http/httpd.hpp +++ b/sca-cpp/trunk/modules/http/httpd.hpp @@ -46,14 +46,14 @@ extern "C" { #include <http_request.h> // Ignore conversion warnings in HTTPD 2.3.15 header #ifdef WANT_MAINTAINER_WARNINGS -#ifndef IS_DARWIN +#ifndef __clang__ #pragma GCC diagnostic ignored "-Wconversion" #endif #endif #include <http_protocol.h> // Re-enable conversion warnings #ifdef WANT_MAINTAINER_WARNINGS -#ifndef IS_DARWIN +#ifndef __clang__ #pragma GCC diagnostic warning "-Wconversion" #endif #endif @@ -94,15 +94,15 @@ template<typename C> void* makeServerConf(apr_pool_t* p, server_rec* s) { return new (gc_new<C>(p)) C(p, s); } -template<typename C> const C& serverConf(const request_rec* r, const module* mod) { +template<typename C> const C& serverConf(const request_rec* const r, const module* const mod) { return *(C*)ap_get_module_config(r->server->module_config, mod); } -template<typename C> C& serverConf(const server_rec* s, const module* mod) { +template<typename C> C& serverConf(const server_rec* const s, const module* const mod) { return *(C*)ap_get_module_config(s->module_config, mod); } -template<typename C> C& serverConf(const cmd_parms* cmd, const module* mod) { +template<typename C> C& serverConf(const cmd_parms* const cmd, const module* const mod) { return *(C*)ap_get_module_config(cmd->server->module_config, mod); } @@ -113,25 +113,25 @@ template<typename C> void* makeDirConf(apr_pool_t *p, char* d) { return new (gc_new<C>(p)) C(p, d); } -template<typename C> const C& dirConf(const request_rec* r, const module* mod) { +template<typename C> const C& dirConf(const request_rec* const r, const module* const mod) { return *(C*)ap_get_module_config(r->per_dir_config, mod); } -template<typename C> C& dirConf(const void* c) { +template<typename C> C& dirConf(const void* const c) { return *(C*)c; } /** * Returns a request-scoped module configuration. */ -template<typename C> C& makeRequestConf(const request_rec* r, const module* mod) { - C* c = new (gc_new<C>(r->pool)) C(r->pool, r); +template<typename C> C& makeRequestConf(const request_rec* const r, const module* const mod) { + C* const c = new (gc_new<C>(r->pool)) C(r->pool, r); ap_set_module_config(r->request_config, mod, c); return *c; } -template<typename C> C& requestConf(const request_rec* r, const module* mod) { - C* c = (C*)ap_get_module_config(r->request_config, mod); +template<typename C> C& requestConf(const request_rec* const r, const module* const mod) { + C* const c = (C*)ap_get_module_config(r->request_config, mod); if (c == NULL) return makeRequestConf<C>(r, mod); return *c; @@ -140,18 +140,18 @@ template<typename C> C& requestConf(const request_rec* r, const module* mod) { /** * Return the host name for a server. */ -const string hostName(const server_rec* s, const string& def = "localhost") { +const string hostName(const server_rec* const s, const string& def = "localhost") { return s->server_hostname != NULL? s->server_hostname : def; } /** * Return the host name from an HTTP request. */ -const string hostName(request_rec* r, const string& def = "localhost") { - const char* fh = apr_table_get(r->headers_in, "X-Forwarded-Server"); +const string hostName(request_rec* const r, const string& def = "localhost") { + const char* const fh = apr_table_get(r->headers_in, "X-Forwarded-Server"); if (fh != NULL) return fh; - const char* h = ap_get_server_name(r); + const char* const h = ap_get_server_name(r); return h != NULL? h : (r->server->server_hostname != NULL? r->server->server_hostname : def); } @@ -166,15 +166,15 @@ const string realm(const string& host) { /** * Return the protocol scheme for a server. */ -const string scheme(const server_rec* s, const string& def = "http") { +const string scheme(const server_rec* const s, const string& def = "http") { return s->server_scheme != NULL? s->server_scheme : def; } /** * Return the protocol scheme from an HTTP request. */ -const string scheme(request_rec* r, const string& def = "http") { - const char* fs = apr_table_get(r->headers_in, "X-Forwarded-HTTPS"); +const string scheme(const request_rec* const r, const string& def = "http") { + const char* const fs = apr_table_get(r->headers_in, "X-Forwarded-HTTPS"); if (fs != NULL) return !strcmp(fs, "on")? "https" : "http"; return r->server->server_scheme != NULL? r->server->server_scheme : def; @@ -183,15 +183,15 @@ const string scheme(request_rec* r, const string& def = "http") { /** * Return the port number for a server. */ -const int port(const server_rec* s, const int def = 80) { +const int port(const server_rec* const s, const int def = 80) { return s->port != 0? s->port : def; } /** * Return the port number from an HTTP request. */ -const int port(request_rec* r, const int def = 80) { - const char* fp = apr_table_get(r->headers_in, "X-Forwarded-Port"); +const int port(const request_rec* const r, const int def = 80) { + const char* const fp = apr_table_get(r->headers_in, "X-Forwarded-Port"); if (fp != NULL) return atoi(fp); const int p = ap_get_server_port(r); @@ -201,7 +201,7 @@ const int port(request_rec* r, const int def = 80) { /** * Return the name of a server. */ -const string serverName(const server_rec* s, const string& def = "localhost") { +const string serverName(server_rec* const s, const string& def = "localhost") { ostringstream n; const string sc = scheme(s); const string h = hostName(s, def); @@ -209,14 +209,14 @@ const string serverName(const server_rec* s, const string& def = "localhost") { n << sc << "://" << h; if (!((sc == "http" && p == 80) || (sc == "https" && p == 443))) n << ":" << p; - n << (s->path != NULL? string(s->path, s->pathlen) : ""); + n << (s->path != NULL? string(s->path, s->pathlen) : emptyString); return str(n); } /** * Determine the name of a server from an HTTP request. */ -const string serverName(request_rec* r, const string& def = "localhost") { +const string serverName(request_rec* const r, const string& def = "localhost") { ostringstream n; const string s = scheme(r); const string h = hostName(r, def); @@ -224,14 +224,14 @@ const string serverName(request_rec* r, const string& def = "localhost") { n << s << "://" << h; if (!((s == "http" && p == 80) || (s == "https" && p == 443))) n << ":" << p; - n << (r->server->path != NULL? string(r->server->path, r->server->pathlen) : ""); + n << (r->server->path != NULL? string(r->server->path, r->server->pathlen) : emptyString); return str(n); } /** * Return true if a request is targeting a virtual host. */ -const bool isVhostRequest(const server_rec* s, const string& d, request_rec* r) { +const bool isVhostRequest(const server_rec* const s, const string& d, request_rec* const r) { const string rh = hostName(r); return rh != hostName(s) && http::topDomain(rh) == d; } @@ -239,20 +239,20 @@ const bool isVhostRequest(const server_rec* s, const string& d, request_rec* r) /** * Return the content type of a request. */ -const string contentType(const request_rec* r) { +const string contentType(const request_rec* const r) { const char* ct = apr_table_get(r->headers_in, "Content-Type"); if (ct == NULL) - return ""; + return emptyString; return ct; } /** * Return the cookie header of a request. */ -const string cookie(const request_rec* r) { +const string cookie(const request_rec* const r) { const char* c = apr_table_get(r->headers_in, "Cookie"); if (c == NULL) - return ""; + return emptyString; return c; } @@ -268,7 +268,7 @@ const list<value> pathInfo(const list<value>& uri, const list<value>& path) { /** * Convert a URI to an absolute URL. */ -const string url(const string& uri, request_rec* r) { +const string url(const string& uri, request_rec* const r) { if (contains(uri, "://")) return uri; ostringstream n; @@ -285,8 +285,8 @@ const string url(const string& uri, request_rec* r) { /** * Convert a URI and a path to an absolute URL. */ -const string url(const string& uri, const list<value>& p, request_rec* r) { - return url(uri + path(p), r); +const string url(const string& uri, const list<value>& p, request_rec* const r) { + return url(uri + (string)path(p), r); } /** @@ -295,7 +295,7 @@ const string url(const string& uri, const list<value>& p, request_rec* r) { const char escape_c2x[] = "0123456789ABCDEF"; const string escape(const string& uri) { debug(uri, "httpd::escape::uri"); - char* copy = (char*)apr_palloc(gc_current_pool(), 3 * length(uri) + 3); + char* const copy = (char*)apr_palloc(gc_current_pool(), 3 * length(uri) + 3); const unsigned char* s = (const unsigned char *)c_str(uri); unsigned char* d = (unsigned char*)copy; unsigned c; @@ -321,7 +321,7 @@ const string escape(const string& uri) { */ const string unescape(const string& uri) { debug(uri, "httpd::unescape::uri"); - char* b = const_cast<char*>(c_str(string(c_str(uri)))); + char* const b = const_cast<char*>(c_str(string(c_str(uri)))); ap_unescape_url(b); debug(b, "httpd::unescape::result"); return b; @@ -348,7 +348,7 @@ const list<value> queryArg(const string& s) { debug(s, "httpd::queryArg::string"); const list<string> t = tokenize("=", s); if (isNil(cdr(t))) - return mklist<value>(c_str(car(t)), ""); + return mklist<value>(c_str(car(t)), emptyString); return mklist<value>(c_str(car(t)), cadr(t)); } @@ -366,7 +366,7 @@ const list<list<value> > queryArgs(const string& a) { /** * Returns a list of key value pairs from the args in an HTTP request. */ -const list<list<value> > queryArgs(const request_rec* r) { +const list<list<value> > queryArgs(const request_rec* const r) { if (r->args == NULL) return list<list<value> >(); return queryArgs(r->args); @@ -385,7 +385,7 @@ const list<list<value> > postArgs(const list<value>& a) { /** * Setup the HTTP read policy. */ -const int setupReadPolicy(request_rec* r) { +const int setupReadPolicy(request_rec* const r) { const int rc = ap_setup_client_block(r, REQUEST_CHUNKED_DECHUNK); if(rc != OK) return rc; @@ -399,7 +399,7 @@ const int setupReadPolicy(request_rec* r) { /** * Read the content of a POST or PUT. */ -const list<string> read(request_rec* r) { +const list<string> read(request_rec* const r) { char b[1024]; const size_t n = ap_get_client_block(r, b, sizeof(b)); if (n <= 0) @@ -410,7 +410,7 @@ const list<string> read(request_rec* r) { /** * Write an HTTP result. */ -const failable<int> writeResult(const failable<list<string> >& ls, const string& ct, request_rec* r) { +const failable<int> writeResult(const failable<list<string> >& ls, const string& ct, request_rec* const r) { if (!hasContent(ls)) return mkfailure<int>(ls); ostringstream os; @@ -456,16 +456,16 @@ const int reportStatus(const failable<int>& rc) { } /** - * Convert a value to an HTTPD request struc + * Convert a value to an HTTPD request struct. */ request_rec* request(const value& v) { return (request_rec*)(long)(double)v; } /** - * Convert an HTTPD request struct to a value + * Convert an HTTPD request struct to a value. */ -const value requestValue(request_rec* r) { +const value requestValue(const request_rec* const r) { return value((double)(long)r); } @@ -473,19 +473,37 @@ const value requestValue(request_rec* r) { * 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) { - if (f == NULL) - return true; - if (f->r == from) - f->r = to; - return redirectFilters(f->next, from, to); +const bool internalUpdateFilters(ap_filter_t *f, const request_rec* const from, request_rec* const to) { + while(f) { + if(f->r == from) + f->r = to; + f = f->next; + } + return true; +} + +/** + * Rename original env in an HTTPD redirect request. + * Similar to httpd/modules/http/http_request.c::rename_original_env. + */ +apr_table_t* const internalRenameOriginalEnv(apr_pool_t* const p, apr_table_t* const t) { + const apr_array_header_t *env_arr = apr_table_elts(t); + const apr_table_entry_t *elts = (const apr_table_entry_t *) (void*)env_arr->elts; + apr_table_t *nt = apr_table_make(p, env_arr->nalloc); + int i; + for(i = 0; i < env_arr->nelts; ++i) { + if (!elts[i].key) + continue; + apr_table_setn(nt, apr_pstrcat(p, "REDIRECT_", elts[i].key, NULL), elts[i].val); + } + return nt; } /** * Create an HTTPD internal redirect request. * Similar to httpd/modules/http/http_request.c::internal_internal_redirect. */ -const failable<request_rec*> internalRedirectRequest(const string& nr_uri, request_rec* r) { +const failable<request_rec*> internalRedirectRequest(const string& nr_uri, request_rec* const r) { if (ap_is_recursion_limit_exceeded(r)) return mkfailure<request_rec*>("Redirect recursion limit exceeded", HTTP_INTERNAL_SERVER_ERROR); @@ -498,11 +516,15 @@ const failable<request_rec*> internalRedirectRequest(const string& nr_uri, reque nr->method_number = r->method_number; nr->allowed_methods = ap_make_method_list(nr->pool, 2); ap_parse_uri(nr, apr_pstrdup(nr->pool, c_str(nr_uri))); + nr->parsed_uri.port_str = r->parsed_uri.port_str; + nr->parsed_uri.port = r->parsed_uri.port; nr->filename = apr_pstrdup(nr->pool, c_str(string("/redirected:") + nr_uri)); nr->request_config = ap_create_request_config(r->pool); nr->per_dir_config = r->server->lookup_defaults; nr->prev = r; r->next = nr; + nr->useragent_addr = r->useragent_addr; + nr->useragent_ip = r->useragent_ip; // Run create request hook ap_run_create_request(nr); @@ -520,10 +542,15 @@ const failable<request_rec*> internalRedirectRequest(const string& nr_uri, reque nr->main = r->main; nr->headers_in = r->headers_in; nr->headers_out = apr_table_make(r->pool, 12); + if (ap_is_HTTP_REDIRECT(nr->status)) { + const char *location = apr_table_get(r->headers_out, "Location"); + if (location) + apr_table_setn(nr->headers_out, "Location", location); + } nr->err_headers_out = r->err_headers_out; nr->subprocess_env = r->subprocess_env; + nr->subprocess_env = internalRenameOriginalEnv(r->pool, r->subprocess_env); nr->notes = apr_table_make(r->pool, 5); - nr->allowed_methods = ap_make_method_list(nr->pool, 2); nr->htaccess = r->htaccess; nr->no_cache = r->no_cache; nr->expecting_100 = r->expecting_100; @@ -537,10 +564,28 @@ const failable<request_rec*> internalRedirectRequest(const string& nr_uri, reque nr->proto_input_filters = r->proto_input_filters; nr->output_filters = nr->proto_output_filters; nr->input_filters = nr->proto_input_filters; - if (nr->main) - ap_add_output_filter_handle(ap_subreq_core_filter_handle, NULL, nr, nr->connection); - redirectFilters(nr->input_filters, r, nr); - redirectFilters(nr->output_filters, r, nr); + if (nr->main) { + ap_filter_t *f, *nextf; + nr->output_filters = r->output_filters; + f = nr->output_filters; + do { + nextf = f->next; + if (f->r == r && f->frec != ap_subreq_core_filter_handle) { + f->r = nr; + ap_remove_output_filter(f); + } + f = nextf; + } while(f && f != nr->proto_output_filters); + } + else { + nr->output_filters = nr->proto_output_filters; + } + internalUpdateFilters(nr->input_filters, r, nr); + internalUpdateFilters(nr->output_filters, r, nr); + + apr_table_setn(nr->subprocess_env, "REDIRECT_STATUS", apr_itoa(r->pool, r->status)); + nr->used_path_info = AP_REQ_DEFAULT_PATH_INFO; + const int rrc = ap_run_post_read_request(nr); if (rrc != OK && rrc != DECLINED) return mkfailure<request_rec*>("Error handling internal redirect", rrc); @@ -552,7 +597,7 @@ const failable<request_rec*> internalRedirectRequest(const string& nr_uri, reque * Process an HTTPD internal redirect request. * Similar to httpd/modules/http/http_request.c::ap_internal_redirect. */ -const int internalRedirect(request_rec* nr) { +const int internalRedirect(request_rec* const nr) { int status = ap_run_quick_handler(nr, 0); if (status == DECLINED) { status = ap_process_request_internal(nr); @@ -570,8 +615,10 @@ const int internalRedirect(request_rec* nr) { /** * Create and process an HTTPD internal redirect request. */ -const int internalRedirect(const string& uri, request_rec* r) { +const int internalRedirect(const string& uri, request_rec* const r) { debug(uri, "httpd::internalRedirect"); + //ap_internal_redirect(c_str(uri), r); + //return OK; const failable<request_rec*> nr = httpd::internalRedirectRequest(uri, r); if (!hasContent(nr)) return rcode(nr); @@ -582,7 +629,7 @@ const int internalRedirect(const string& uri, request_rec* r) { * Create an HTTPD sub request. * Similar to httpd/server/request.c::make_sub_request */ -const failable<request_rec*> internalSubRequest(const string& nr_uri, request_rec* r) { +const failable<request_rec*> internalSubRequest(const string& nr_uri, request_rec* const r) { if (ap_is_recursion_limit_exceeded(r)) return mkfailure<request_rec*>("Redirect recursion limit exceeded", HTTP_INTERNAL_SERVER_ERROR); @@ -647,7 +694,7 @@ const failable<request_rec*> internalSubRequest(const string& nr_uri, request_re /** * Return an HTTP external redirect request. */ -const int externalRedirect(const string& uri, request_rec* r) { +const int externalRedirect(const string& uri, request_rec* const r) { debug(uri, "httpd::externalRedirect"); r->status = HTTP_MOVED_TEMPORARILY; apr_table_setn(r->headers_out, "Location", apr_pstrdup(r->pool, c_str(uri))); @@ -660,7 +707,7 @@ const int externalRedirect(const string& uri, request_rec* r) { /** * Put a value in the process user data. */ -const bool putUserData(const string& k, const void* v, const server_rec* s) { +const bool putUserData(const string& k, const void* const v, const server_rec* const s) { apr_pool_userdata_set((const void *)v, c_str(k), apr_pool_cleanup_null, s->process->pool); return true; } @@ -668,7 +715,7 @@ const bool putUserData(const string& k, const void* v, const server_rec* s) { /** * Return a user data value. */ -const void* userData(const string& k, const server_rec* s) { +const void* const userData(const string& k, const server_rec* const s) { void* v = NULL; apr_pool_userdata_get(&v, c_str(k), s->process->pool); return v; @@ -683,7 +730,7 @@ const void* userData(const string& k, const server_rec* s) { /** * Log an optional value. */ -const char* debugOptional(const char* s) { +const char* const debugOptional(const char* const s) { if (s == NULL) return ""; return s; @@ -692,7 +739,7 @@ const char* debugOptional(const char* s) { /** * Log a header */ -int debugHeader(unused void* r, const char* key, const char* value) { +int debugHeader(unused void* r, const char* const key, const char* const value) { cdebug << " header key: " << key << ", value: " << value << endl; return 1; } @@ -700,7 +747,7 @@ int debugHeader(unused void* r, const char* key, const char* value) { /** * Log an environment variable */ -int debugEnv(unused void* r, const char* key, const char* value) { +int debugEnv(unused void* r, const char* const key, const char* const value) { cdebug << " var key: " << key << ", value: " << value << endl; return 1; } @@ -708,7 +755,7 @@ int debugEnv(unused void* r, const char* key, const char* value) { /** * Log a note. */ -int debugNote(unused void* r, const char* key, const char* value) { +int debugNote(unused void* r, const char* const key, const char* const value) { cdebug << " note key: " << key << ", value: " << value << endl; return 1; } @@ -716,8 +763,8 @@ int debugNote(unused void* r, const char* key, const char* value) { /** * Log a request. */ -const bool debugRequest(request_rec* r, const string& msg) { - gc_scoped_pool pool; +const bool debugRequest(request_rec* const r, const string& msg) { + const gc_scoped_pool pool; cdebug << msg << ":" << endl; cdebug << " unparsed uri: " << debugOptional(r->unparsed_uri) << endl; cdebug << " uri: " << debugOptional(r->uri) << endl; diff --git a/sca-cpp/trunk/modules/http/mod-openauth.cpp b/sca-cpp/trunk/modules/http/mod-openauth.cpp index 2e308ecedb..797e8c10b5 100644 --- a/sca-cpp/trunk/modules/http/mod-openauth.cpp +++ b/sca-cpp/trunk/modules/http/mod-openauth.cpp @@ -57,11 +57,11 @@ namespace openauth { */ class ServerConf { public: - ServerConf(apr_pool_t* p, server_rec* s) : p(p), server(s) { + ServerConf(apr_pool_t* const p, server_rec* const s) : p(p), server(s) { } const gc_pool p; - server_rec* server; + server_rec* const server; }; /** @@ -71,11 +71,11 @@ class AuthnProviderConf { public: AuthnProviderConf() : name(), provider(NULL) { } - AuthnProviderConf(const string name, const authn_provider* provider) : name(name), provider(provider) { + AuthnProviderConf(const string name, const authn_provider* const provider) : name(name), provider(provider) { } - string name; - const authn_provider* provider; + const string name; + const authn_provider* const provider; }; /** @@ -83,14 +83,14 @@ public: */ class DirConf { public: - DirConf(apr_pool_t* p, char* d) : p(p), dir(d), enabled(false), login("") { + DirConf(apr_pool_t* const p, const char* d) : p(p), dir(d), enabled(false), login(emptyString) { } const gc_pool p; - const char* dir; + const char* const dir; bool enabled; - string login; - list<AuthnProviderConf> apcs; + gc_mutable_ref<string> login; + gc_mutable_ref<list<AuthnProviderConf> > apcs; }; #ifdef WANT_MAINTAINER_LOG @@ -98,17 +98,17 @@ public: /** * Log session entries. */ -int debugSessionEntry(unused void* r, const char* key, const char* value) { +int debugSessionEntry(unused void* r, const char* const key, const char* const value) { cdebug << " session key: " << key << ", value: " << value << endl; return 1; } -const bool debugSession(request_rec* r, session_rec* z) { +const bool debugSession(request_rec* const r, const session_rec* const z) { apr_table_do(debugSessionEntry, r, z->entries, NULL); return true; } -#define debug_authSession(r, z) if (debug_islogging()) openauth::debugSession(r, z) +#define debug_authSession(r, z) if(debug_islogging()) openauth::debugSession(r, z) #else @@ -117,28 +117,35 @@ const bool debugSession(request_rec* r, session_rec* z) { #endif /** + * Session hook functions. + */ +static int (*ap_session_load_fn) (request_rec * r, session_rec ** z) = NULL; +static apr_status_t (*ap_session_get_fn) (request_rec * r, session_rec * z, const char *key, const char **value) = NULL; +static apr_status_t (*ap_session_set_fn)(request_rec * r, session_rec * z, const char *key, const char *value) = NULL; + +/** * Run the authnz hooks to authenticate a request. */ -const failable<int> checkAuthnzProviders(const string& user, const string& pw, request_rec* r, const list<AuthnProviderConf>& apcs) { - if (isNil(apcs)) - return mkfailure<int>("Authentication failure for: " + user); +const failable<int> checkAuthnzProviders(const string& user, const string& pw, request_rec* const r, const list<AuthnProviderConf>& apcs) { + if(isNil(apcs)) + return mkfailure<int>("Authentication failure for: " + user, HTTP_UNAUTHORIZED); const AuthnProviderConf apc = car<AuthnProviderConf>(apcs); - if (apc.provider == NULL || !apc.provider->check_password) + if(apc.provider == NULL || !apc.provider->check_password) return checkAuthnzProviders(user, pw, r, cdr(apcs)); apr_table_setn(r->notes, AUTHN_PROVIDER_NAME_NOTE, c_str(apc.name)); const authn_status auth_result = apc.provider->check_password(r, c_str(user), c_str(pw)); apr_table_unset(r->notes, AUTHN_PROVIDER_NAME_NOTE); - if (auth_result != AUTH_GRANTED) + if(auth_result != AUTH_GRANTED) return checkAuthnzProviders(user, pw, r, cdr(apcs)); return OK; } -const failable<int> checkAuthnz(const string& user, const string& pw, request_rec* r, const DirConf& dc) { - if (substr(user, 0, 1) == "/" && pw == "password") +const failable<int> checkAuthnz(const string& user, const string& pw, request_rec* const r, const DirConf& dc) { + if(substr(user, 0, 1) == "/" && pw == "password") return mkfailure<int>(string("Encountered FakeBasicAuth spoof: ") + user, HTTP_UNAUTHORIZED); - if (isNil(dc.apcs)) { + if(isNil((const list<AuthnProviderConf>)dc.apcs)) { const authn_provider* provider = (const authn_provider*)ap_lookup_provider(AUTHN_PROVIDER_GROUP, AUTHN_DEFAULT_PROVIDER, AUTHN_PROVIDER_VERSION); return checkAuthnzProviders(user, pw, r, mklist<AuthnProviderConf>(AuthnProviderConf(AUTHN_DEFAULT_PROVIDER, provider))); } @@ -148,54 +155,47 @@ const failable<int> checkAuthnz(const string& user, const string& pw, request_re /** * Return the user info from a form auth encrypted session cookie. */ -static int (*ap_session_load_fn) (request_rec * r, session_rec ** z) = NULL; -static int (*ap_session_get_fn) (request_rec * r, session_rec * z, const char *key, const char **value) = NULL; - -const failable<value> userInfoFromSession(const string& realm, request_rec* r) { +const failable<value> userInfoFromSession(const string& realm, request_rec* const r) { debug("modopenauth::userInfoFromSession"); - if (ap_session_load_fn == NULL) - ap_session_load_fn = APR_RETRIEVE_OPTIONAL_FN(ap_session_load); session_rec *z = NULL; ap_session_load_fn(r, &z); - if (z == NULL) - return mkfailure<value>("Couldn't retrieve user session"); + if(z == NULL) + return mkfailure<value>("Couldn't retrieve user session", HTTP_UNAUTHORIZED); debug_authSession(r, z); - if (ap_session_get_fn == NULL) - ap_session_get_fn = APR_RETRIEVE_OPTIONAL_FN(ap_session_get); const char* user = NULL; ap_session_get_fn(r, z, c_str(realm + "-user"), &user); - if (user == NULL) - return mkfailure<value>("Couldn't retrieve user id"); + if(user == NULL) + return mkfailure<value>("Couldn't retrieve user id", HTTP_UNAUTHORIZED); const char* pw = NULL; ap_session_get_fn(r, z, c_str(realm + "-pw"), &pw); - if (pw == NULL) - return mkfailure<value>("Couldn't retrieve password"); + if(pw == NULL) + return mkfailure<value>("Couldn't retrieve password", HTTP_UNAUTHORIZED); return value(mklist<value>(mklist<value>("realm", realm), mklist<value>("id", string(user)), mklist<value>("password", string(pw)))); } /** * Return the user info from a form auth session cookie. */ -const failable<value> userInfoFromCookie(const value& sid, const string& realm, request_rec* r) { +const failable<value> userInfoFromCookie(const value& sid, const string& realm, request_rec* const r) { const list<list<value>> info = httpd::queryArgs(sid); debug(info, "modopenauth::userInfoFromCookie::info"); const list<value> user = assoc<value>(realm + "-user", info); - if (isNil(user)) + if(isNil(user)) return userInfoFromSession(realm, r); const list<value> pw = assoc<value>(realm + "-pw", info); - if (isNil(pw)) - return mkfailure<value>("Couldn't retrieve password"); + if(isNil(pw)) + return mkfailure<value>("Couldn't retrieve password", HTTP_UNAUTHORIZED); return value(mklist<value>(mklist<value>("realm", realm), mklist<value>("id", cadr(user)), mklist<value>("password", cadr(pw)))); } /** * Return the user info from a basic auth header. */ -const failable<value> userInfoFromHeader(const char* header, const string& realm, request_rec* r) { +const failable<value> userInfoFromHeader(const char* header, const string& realm, request_rec* const r) { debug(header, "modopenauth::userInfoFromHeader::header"); - if (strcasecmp(ap_getword(r->pool, &header, ' '), "Basic")) - return mkfailure<value>("Wrong authentication scheme"); + if(strcasecmp(ap_getword(r->pool, &header, ' '), "Basic")) + return mkfailure<value>("Wrong authentication scheme", HTTP_UNAUTHORIZED); while (apr_isspace(*header)) header++; @@ -212,18 +212,18 @@ const failable<value> userInfoFromHeader(const char* header, const string& realm /** * Handle an authenticated request. */ -const failable<int> authenticated(const list<list<value> >& info, request_rec* r) { +const failable<int> authenticated(const list<list<value> >& info, request_rec* const r) { debug(info, "modopenauth::authenticated::info"); // Store user info in the request const list<value> realm = assoc<value>("realm", info); - if (isNil(realm) || isNil(cdr(realm))) - return mkfailure<int>("Couldn't retrieve realm"); + if(isNil(realm) || isNil(cdr(realm))) + return mkfailure<int>("Couldn't retrieve realm", HTTP_UNAUTHORIZED); apr_table_set(r->subprocess_env, apr_pstrdup(r->pool, "REALM"), apr_pstrdup(r->pool, c_str(cadr(realm)))); const list<value> id = assoc<value>("id", info); - if (isNil(id) || isNil(cdr(id))) - return mkfailure<int>("Couldn't retrieve user id"); + if(isNil(id) || isNil(cdr(id))) + return mkfailure<int>("Couldn't retrieve user id", HTTP_UNAUTHORIZED); r->user = apr_pstrdup(r->pool, c_str(cadr(id))); apr_table_set(r->subprocess_env, apr_pstrdup(r->pool, "NICKNAME"), apr_pstrdup(r->pool, c_str(cadr(id)))); @@ -233,127 +233,113 @@ const failable<int> authenticated(const list<list<value> >& info, request_rec* r /** * Check user authentication. */ -static int checkAuthn(request_rec *r) { - gc_scoped_pool pool(r->pool); +static int checkAuthn(request_rec* const r) { + const gc_scoped_pool sp(r->pool); // Decline if we're not enabled or AuthType is not set to Open const DirConf& dc = httpd::dirConf<DirConf>(r, &mod_tuscany_openauth); - if (!dc.enabled) + if(!dc.enabled) return DECLINED; const char* atype = ap_auth_type(r); - if (atype == NULL || strcasecmp(atype, "Open")) - return DECLINED; debug_httpdRequest(r, "modopenauth::checkAuthn::input"); debug(atype, "modopenauth::checkAuthn::auth_type"); + if(atype == NULL || strcasecmp(atype, "Open")) + return DECLINED; + debug(atype, "modopenauth::checkAuthn::auth_type"); // Get the request args const list<list<value> > args = httpd::queryArgs(r); // Get session id from the request const maybe<string> sid = sessionID(r, "TuscanyOpenAuth"); - if (hasContent(sid)) { + if(hasContent(sid)) { // Decline if the session id was not created by this module const string stype = substr(content(sid), 0, 7); - if (stype == "OAuth2_" || stype == "OAuth1_" || stype == "OpenID_") + if(stype == "OAuth2_" || stype == "OAuth1_" || stype == "OpenID_") return DECLINED; // Retrieve the auth realm const char* aname = ap_auth_name(r); - if (aname == NULL) - return httpd::reportStatus(mkfailure<int>("Missing AuthName")); + if(aname == NULL) + return reportStatus(mkfailure<int>("Missing AuthName", HTTP_UNAUTHORIZED), dc.login, nilValue, r); // Extract user info from the session id const failable<value> userinfo = userInfoFromCookie(content(sid), aname, r); - if (hasContent(userinfo)) { + if(hasContent(userinfo)) { // Try to authenticate the request const value uinfo = content(userinfo); const failable<int> authz = checkAuthnz(cadr(assoc<value>("id", uinfo)), cadr(assoc<value>("password", uinfo)), r, dc); - if (!hasContent(authz)) { + if(!hasContent(authz)) { // Authentication failed, redirect to login page r->ap_auth_type = const_cast<char*>(atype); - return httpd::reportStatus(login(dc.login, value(), 1, r)); + return reportStatus(authz, dc.login, 1, r); } // Successfully authenticated, store the user info in the request r->ap_auth_type = const_cast<char*>(atype); - return httpd::reportStatus(authenticated(uinfo, r)); + return reportStatus(authenticated(uinfo, r), dc.login, nilValue, r); } } // Get basic auth header from the request - const char* header = apr_table_get(r->headers_in, (PROXYREQ_PROXY == r->proxyreq) ? "Proxy-Authorization" : "Authorization"); - if (header != NULL) { + const char* const header = apr_table_get(r->headers_in, (PROXYREQ_PROXY == r->proxyreq) ? "Proxy-Authorization" : "Authorization"); + if(header != NULL) { // Retrieve the auth realm - const char* aname = ap_auth_name(r); - if (aname == NULL) - return httpd::reportStatus(mkfailure<int>("Missing AuthName")); + const char* const aname = ap_auth_name(r); + if(aname == NULL) + return reportStatus(mkfailure<int>("Missing AuthName", HTTP_UNAUTHORIZED), dc.login, nilValue, r); // Extract user info from the session id const failable<value> info = userInfoFromHeader(header, aname, r); - if (hasContent(info)) { + if(hasContent(info)) { // Try to authenticate the request const value uinfo = content(info); const failable<int> authz = checkAuthnz(cadr(assoc<value>("id", uinfo)), cadr(assoc<value>("password", uinfo)), r, dc); - if (!hasContent(authz)) { + if(!hasContent(authz)) { // Authentication failed, redirect to login page r->ap_auth_type = const_cast<char*>(atype); - return httpd::reportStatus(login(dc.login, value(), 1, r)); + return reportStatus(authz, dc.login, 1, r); } // Successfully authenticated, store the user info in the request r->ap_auth_type = const_cast<char*>(atype); - return httpd::reportStatus(authenticated(uinfo, r)); + return reportStatus(authenticated(uinfo, r), dc.login, nilValue, r); } } // Decline if the request is for another authentication provider - if (!isNil(assoc<value>("openid_identifier", args))) + if(!isNil(assoc<value>("openid_identifier", args))) return DECLINED; // Redirect to the login page, unless we have a session id from another module - if (hasContent(sessionID(r, "TuscanyOpenIDAuth")) || + if(hasContent(sessionID(r, "TuscanyOpenIDAuth")) || hasContent(sessionID(r, "TuscanyOAuth1")) || hasContent(sessionID(r, "TuscanyOAuth2"))) return DECLINED; r->ap_auth_type = const_cast<char*>(atype); - return httpd::reportStatus(login(dc.login, value(), value(), r)); + return httpd::reportStatus(login(dc.login, nilValue, nilValue, r)); } /** - * Save the auth session cookie in the response. - */ -static int sessionCookieSave(request_rec* r, session_rec* z) { - gc_scoped_pool pool(r->pool); - - const DirConf& dc = httpd::dirConf<DirConf>(r, &mod_tuscany_openauth); - if (!dc.enabled) - return DECLINED; - - debug(c_str(cookie("TuscanyOpenAuth", z->encoded, httpd::hostName(r))), "modopenauth::setcookie"); - apr_table_set(r->err_headers_out, "Set-Cookie", c_str(cookie("TuscanyOpenAuth", z->encoded, httpd::hostName(r)))); - return OK; -} - -/** - * Load the auth session cookie from the request. Similar + * Load the auth session cookie from the request. */ -static int sessionCookieLoad(request_rec* r, session_rec** z) { - gc_scoped_pool pool(r->pool); +static int sessionCookieLoad(request_rec* const r, session_rec** const z) { + const gc_scoped_pool sp(r->pool); const DirConf& dc = httpd::dirConf<DirConf>(r, &mod_tuscany_openauth); - if (!dc.enabled) + if(!dc.enabled) return DECLINED; // First look in the notes - const char* note = apr_pstrcat(r->pool, "mod_openauth", "TuscanyOpenAuth", NULL); + const char* const note = apr_pstrcat(r->pool, "mod_openauth", "TuscanyOpenAuth", NULL); session_rec* zz = (session_rec*)(void*)apr_table_get(r->notes, note); - if (zz != NULL) { + if(zz != NULL) { *z = zz; return OK; } @@ -376,22 +362,86 @@ static int sessionCookieLoad(request_rec* r, session_rec** z) { } /** + * Save the auth session cookie in the response. + */ +static int sessionCookieSave(request_rec* const r, session_rec* const z) { + const gc_scoped_pool sp(r->pool); + + const DirConf& dc = httpd::dirConf<DirConf>(r, &mod_tuscany_openauth); + if(!dc.enabled) + return DECLINED; + if(z->encoded == NULL || *(z->encoded) == '\0') { + const maybe<string> sid = sessionID(r, "TuscanyOpenAuth"); + if(!hasContent(sid)) + return OK; + } + + debug(c_str(cookie("TuscanyOpenAuth", z->encoded, httpd::hostName(r))), "modopenauth::sessioncookiesave::setcookie"); + apr_table_set(r->err_headers_out, "Set-Cookie", c_str(cookie("TuscanyOpenAuth", z->encoded, httpd::hostName(r)))); + return OK; +} + +/** + * Logout request handler. + */ +int logoutHandler(request_rec* const r) { + if(r->handler == NULL || strcmp(r->handler, "mod_tuscany_openauth_logout")) + return DECLINED; + + const gc_scoped_pool sp(r->pool); + debug_httpdRequest(r, "modopenauth::handler::input"); + const DirConf& dc = httpd::dirConf<DirConf>(r, &mod_tuscany_openauth); + if(!dc.enabled) + return DECLINED; + + // Clear the current session + if(hasContent(sessionID(r, "TuscanyOpenAuth"))) { + const char* const authname = ap_auth_name(r); + session_rec* z = NULL; + ap_session_load_fn(r, &z); + if(z != NULL && authname != NULL) { + ap_session_set_fn(r, z, apr_pstrcat(r->pool, authname, "-user", NULL), NULL); + ap_session_set_fn(r, z, apr_pstrcat(r->pool, authname, "-pw", NULL), NULL); + ap_session_set_fn(r, z, apr_pstrcat(r->pool, authname, "-site", NULL), NULL); + } else + apr_table_set(r->err_headers_out, "Set-Cookie", c_str(cookie("TuscanyOpenAuth", emptyString, httpd::hostName(r)))); + } + if(hasContent(sessionID(r, "TuscanyOpenIDAuth"))) + apr_table_set(r->err_headers_out, "Set-Cookie", c_str(cookie("TuscanyOpenIDAuth", emptyString, httpd::hostName(r)))); + if(hasContent(sessionID(r, "TuscanyOAuth1"))) + apr_table_set(r->err_headers_out, "Set-Cookie", c_str(cookie("TuscanyOAuth1", emptyString, httpd::hostName(r)))); + if(hasContent(sessionID(r, "TuscanyOAuth2"))) + apr_table_set(r->err_headers_out, "Set-Cookie", c_str(cookie("TuscanyOAuth2", emptyString, httpd::hostName(r)))); + + // Redirect to the login page + return httpd::reportStatus(login(dc.login, "/", nilValue, r)); +} + +/** * Process the module configuration. */ -int postConfigMerge(ServerConf& mainsc, server_rec* s) { - if (s == NULL) +int postConfigMerge(const ServerConf& mainsc, server_rec* const s) { + if(s == NULL) return OK; debug(httpd::serverName(s), "modopenauth::postConfigMerge::serverName"); return postConfigMerge(mainsc, 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); +int postConfig(apr_pool_t* const p, unused apr_pool_t* const plog, unused apr_pool_t* const ptemp, server_rec* const s) { + const gc_scoped_pool sp(p); - ServerConf& sc = httpd::serverConf<ServerConf>(s, &mod_tuscany_openauth); + const ServerConf& sc = httpd::serverConf<ServerConf>(s, &mod_tuscany_openauth); debug(httpd::serverName(s), "modopenauth::postConfig::serverName"); + // Retrieve session hook functions + if(ap_session_load_fn == NULL) + ap_session_load_fn = APR_RETRIEVE_OPTIONAL_FN(ap_session_load); + if(ap_session_get_fn == NULL) + ap_session_get_fn = APR_RETRIEVE_OPTIONAL_FN(ap_session_get); + if(ap_session_set_fn == NULL) + ap_session_set_fn = APR_RETRIEVE_OPTIONAL_FN(ap_session_set); + // Merge server configurations return postConfigMerge(sc, s); } @@ -399,15 +449,15 @@ int postConfig(apr_pool_t* p, unused apr_pool_t* plog, unused apr_pool_t* ptemp, /** * Child process initialization. */ -void childInit(apr_pool_t* p, server_rec* s) { - gc_scoped_pool pool(p); +void childInit(apr_pool_t* const p, server_rec* const s) { + const gc_scoped_pool sp(p); - ServerConf* psc = (ServerConf*)ap_get_module_config(s->module_config, &mod_tuscany_openauth); + const ServerConf* const psc = (ServerConf*)ap_get_module_config(s->module_config, &mod_tuscany_openauth); if(psc == NULL) { cfailure << "[Tuscany] Due to one or more errors mod_tuscany_openauth loading failed. Causing apache to stop loading." << endl; exit(APEXIT_CHILDFATAL); } - ServerConf& sc = *psc; + const ServerConf& sc = *psc; // Merge the updated configuration into the virtual hosts postConfigMerge(sc, s->next); @@ -416,27 +466,27 @@ void childInit(apr_pool_t* p, server_rec* s) { /** * Configuration commands. */ -const char* confEnabled(cmd_parms *cmd, void *c, const int arg) { - gc_scoped_pool pool(cmd->pool); +char* confEnabled(cmd_parms* cmd, void *c, const int arg) { + const gc_scoped_pool sp(cmd->pool); DirConf& dc = httpd::dirConf<DirConf>(c); dc.enabled = (bool)arg; return NULL; } -const char* confLogin(cmd_parms *cmd, void *c, const char* arg) { - gc_scoped_pool pool(cmd->pool); +char* confLogin(cmd_parms *cmd, void *c, const char* arg) { + const gc_scoped_pool sp(cmd->pool); DirConf& dc = httpd::dirConf<DirConf>(c); dc.login = arg; return NULL; } -const char* confAuthnProvider(cmd_parms *cmd, void *c, const char* arg) { - gc_scoped_pool pool(cmd->pool); +char* confAuthnProvider(cmd_parms *cmd, void *c, const char* arg) { + const gc_scoped_pool sp(cmd->pool); DirConf& dc = httpd::dirConf<DirConf>(c); // Lookup and cache the Authn provider const authn_provider* provider = (authn_provider*)ap_lookup_provider(AUTHN_PROVIDER_GROUP, arg, AUTHN_PROVIDER_VERSION); - if (provider == NULL) + if(provider == NULL) return apr_psprintf(cmd->pool, "Unknown Authn provider: %s", arg); - if (!provider->check_password) + if(!provider->check_password) return apr_psprintf(cmd->pool, "The '%s' Authn provider doesn't support password authentication", arg); dc.apcs = append<AuthnProviderConf>(dc.apcs, mklist<AuthnProviderConf>(AuthnProviderConf(arg, provider))); return NULL; @@ -458,6 +508,7 @@ void registerHooks(unused apr_pool_t *p) { ap_hook_check_authn(checkAuthn, NULL, NULL, APR_HOOK_MIDDLE, AP_AUTH_INTERNAL_PER_CONF); ap_hook_session_load(sessionCookieLoad, NULL, NULL, APR_HOOK_MIDDLE); ap_hook_session_save(sessionCookieSave, NULL, NULL, APR_HOOK_MIDDLE); + ap_hook_handler(logoutHandler, NULL, NULL, APR_HOOK_MIDDLE); } } diff --git a/sca-cpp/trunk/modules/http/mod-ssltunnel.cpp b/sca-cpp/trunk/modules/http/mod-ssltunnel.cpp index b66cd29959..0a9ebc1a80 100644 --- a/sca-cpp/trunk/modules/http/mod-ssltunnel.cpp +++ b/sca-cpp/trunk/modules/http/mod-ssltunnel.cpp @@ -53,17 +53,17 @@ namespace modssltunnel { */ class ServerConf { public: - ServerConf(apr_pool_t* p, server_rec* s) : p(p), server(s) { + ServerConf(apr_pool_t* const p, server_rec* const s) : p(p), server(s) { } const gc_pool p; - server_rec* server; - string pass; - string host; - string path; - string ca; - string cert; - string key; + server_rec* const server; + gc_mutable_ref<string> pass; + gc_mutable_ref<string> host; + gc_mutable_ref<string> path; + gc_mutable_ref<string> ca; + gc_mutable_ref<string> cert; + gc_mutable_ref<string> key; }; extern "C" { @@ -74,7 +74,7 @@ extern module AP_DECLARE_DATA core_module; * Process the module configuration. */ int M_SSLTUNNEL; -int postConfigMerge(ServerConf& mainsc, apr_pool_t* p, server_rec* s) { +int postConfigMerge(const ServerConf& mainsc, apr_pool_t* const p, server_rec* const s) { if (s == NULL) return OK; ServerConf& sc = httpd::serverConf<ServerConf>(s, &mod_tuscany_ssltunnel); @@ -102,10 +102,10 @@ int postConfigMerge(ServerConf& mainsc, apr_pool_t* p, server_rec* s) { return postConfigMerge(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); +int postConfig(apr_pool_t* const p, unused apr_pool_t* const plog, unused apr_pool_t* const ptemp, server_rec* const s) { + const gc_scoped_pool sp(p); - ServerConf& sc = httpd::serverConf<ServerConf>(s, &mod_tuscany_ssltunnel); + const ServerConf& sc = httpd::serverConf<ServerConf>(s, &mod_tuscany_ssltunnel); debug(httpd::serverName(s), "modssltunnel::postConfig::serverName"); // Register the SSLTUNNEL method @@ -118,7 +118,7 @@ int postConfig(apr_pool_t* p, unused apr_pool_t* plog, unused apr_pool_t* ptemp, /** * Close a connection. */ -const int close(conn_rec* conn, apr_socket_t* csock) { +const int close(conn_rec* const conn, apr_socket_t* const csock) { debug("modssltunnel::close"); apr_socket_close(csock); conn->aborted = 1; @@ -128,7 +128,7 @@ const int close(conn_rec* conn, apr_socket_t* csock) { /** * Abort a connection. */ -const int abort(conn_rec* conn, apr_socket_t* csock, const string& reason) { +const int abort(conn_rec* const conn, apr_socket_t* const csock, const string& reason) { debug("modssltunnel::abort"); apr_socket_close(csock); conn->aborted = 1; @@ -138,21 +138,21 @@ const int abort(conn_rec* conn, apr_socket_t* csock, const string& reason) { /** * Tunnel traffic from a client connection to a target URL. */ -int tunnel(conn_rec* conn, const string& ca, const string& cert, const string& key, const string& url, const string& preamble, const gc_pool& p, unused ap_filter_t* ifilter, ap_filter_t* ofilter) { +int tunnel(conn_rec* const conn, const string& ca, const string& cert, const string& key, const string& url, const string& preamble, const gc_pool& p, unused ap_filter_t* const ifilter, ap_filter_t* const ofilter) { // 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); + apr_bucket_brigade* const ib = apr_brigade_create(pool(p), conn->bucket_alloc); + apr_bucket_brigade* const ob = apr_brigade_create(pool(p), conn->bucket_alloc); // Get client connection socket - apr_socket_t* csock = (apr_socket_t*)ap_get_module_config(conn->conn_config, &core_module); + apr_socket_t* const csock = (apr_socket_t*)ap_get_module_config(conn->conn_config, &core_module); // Open connection to target - http::CURLSession cs(ca, cert, key, "", 0); + const http::CURLSession cs(ca, cert, key, emptyString, 0); const failable<bool> crc = http::connect(url, cs); if (!hasContent(crc)) return abort(conn, csock, reason(crc)); - apr_socket_t* tsock = http::sock(cs); + apr_socket_t* const tsock = http::sock(cs); // Send preamble if (length(preamble) != 0) { @@ -164,7 +164,7 @@ int tunnel(conn_rec* conn, const string& ca, const string& cert, const string& k // 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); + const apr_status_t cprc = apr_pollset_create(&pollset, 2, pool(p), 0); if (cprc != APR_SUCCESS) return abort(conn, csock, http::apreason(cprc)); const apr_pollfd_t* cpollfd = http::pollfd(csock, APR_POLLIN, p); @@ -241,7 +241,7 @@ int tunnel(conn_rec* conn, const string& ca, const string& cert, const string& k // Poll the client and target sockets debug("modssltunnel::tunnel::poll"); - apr_status_t pollrc = apr_pollset_poll(pollset, -1, &pollcount, &pollfds); + const apr_status_t pollrc = apr_pollset_poll(pollset, -1, &pollcount, &pollfds); if (pollrc != APR_SUCCESS) return abort(conn, csock, "Couldn't poll sockets"); debug(pollcount, "modssltunnel::tunnel::pollfds"); @@ -254,7 +254,7 @@ int tunnel(conn_rec* conn, const string& ca, const string& cert, const string& k /** * Return the first connection filter in a list of filters. */ -ap_filter_t* connectionFilter(ap_filter_t* f) { +ap_filter_t* const connectionFilter(ap_filter_t* const f) { if (f == NULL) return f; if (f->frec->ftype < AP_FTYPE_CONNECTION) @@ -265,14 +265,14 @@ ap_filter_t* connectionFilter(ap_filter_t* f) { /** * Process a client connection and relay it to a tunnel. */ -int processConnection(conn_rec *conn) { +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 pool(conn->pool); + const gc_scoped_pool sp(conn->pool); // Get the server configuration const ServerConf& sc = httpd::serverConf<ServerConf>(conn->base_server, &mod_tuscany_ssltunnel); @@ -297,41 +297,41 @@ int handler(request_rec* r) { if (strcmp(r->server->server_scheme, "https")) return DECLINED; - gc_scoped_pool pool(r->pool); + const gc_scoped_pool sp(r->pool); // 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); + const string url = string(cadr(path)) + ":" + (string)caddr(path); debug(url, "modssltunnel::handler::target"); // Run the tunnel - return tunnel(r->connection, "", "", "", url, "", gc_pool(r->pool), connectionFilter(r->proto_input_filters), connectionFilter(r->proto_output_filters)); + return tunnel(r->connection, emptyString, emptyString, emptyString, url, emptyString, 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); +char* confTunnelPass(cmd_parms *cmd, unused void *c, const char *arg) { + const gc_scoped_pool sp(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); +char* confCAFile(cmd_parms *cmd, unused void *c, const char *arg) { + const gc_scoped_pool sp(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); +char* confCertFile(cmd_parms *cmd, unused void *c, const char *arg) { + const gc_scoped_pool sp(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); +char* confCertKeyFile(cmd_parms *cmd, unused void *c, const char *arg) { + const gc_scoped_pool sp(cmd->pool); ServerConf& sc = httpd::serverConf<ServerConf>(cmd, &mod_tuscany_ssltunnel); sc.key = arg; return NULL; diff --git a/sca-cpp/trunk/modules/http/openauth.hpp b/sca-cpp/trunk/modules/http/openauth.hpp index 3ffa88d362..dcf405d487 100644 --- a/sca-cpp/trunk/modules/http/openauth.hpp +++ b/sca-cpp/trunk/modules/http/openauth.hpp @@ -42,11 +42,12 @@ namespace openauth { /** * Return the session id from a request. */ -const char* cookieName(const char* cs) { +const char* const cookieName(const char* const cs) { if (*cs != ' ') return cs; return cookieName(cs + 1); } + const maybe<string> sessionID(const list<string>& c, const string& key) { if (isNil(c)) return maybe<string>(); @@ -62,7 +63,7 @@ const maybe<string> sessionID(const list<string>& c, const string& key) { return sessionID(cdr(c), key); } -const maybe<string> sessionID(const request_rec* r, const string& key) { +const maybe<string> sessionID(const request_rec* const r, const string& key) { const string c = httpd::cookie(r); debug(c, "openauth::sessionid::cookies"); if (length(c) == 0) @@ -74,10 +75,15 @@ const maybe<string> sessionID(const request_rec* r, const string& key) { * Convert a session id to a cookie string. */ const string cookie(const string& key, const string& sid, const string& domain) { + if (length(sid) == 0) { + const string c = key + string("=") + "; max-age=0; domain=." + httpd::realm(domain) + "; path=/; secure; httponly"; + debug(c, "openauth::cookie"); + return c; + } const time_t t = time(NULL) + 86400; char exp[32]; strftime(exp, 32, "%a, %d-%b-%Y %H:%M:%S GMT", gmtime(&t)); - const string c = key + string("=") + sid + "; expires=" + string(exp) + "; domain=." + httpd::realm(domain) + "; path=/"; + const string c = key + string("=") + sid + "; expires=" + string(exp) + "; domain=." + httpd::realm(domain) + "; path=/; secure; httponly"; debug(c, "openauth::cookie"); return c; } @@ -85,7 +91,7 @@ const string cookie(const string& key, const string& sid, const string& domain) /** * Redirect to the configured login page. */ -const failable<int> login(const string& page, const value& ref, const value& attempt, request_rec* r) { +const failable<int> login(const string& page, const value& ref, const value& attempt, request_rec* const r) { const list<list<value> > rarg = ref == string("/")? list<list<value> >() : mklist<list<value> >(mklist<value>("openauth_referrer", httpd::escape(httpd::url(isNil(ref)? r->uri : ref, r)))); const list<list<value> > aarg = isNil(attempt)? list<list<value> >() : mklist<list<value> >(mklist<value>("openauth_attempt", attempt)); const list<list<value> > largs = append<list<value> >(rarg, aarg); @@ -94,6 +100,31 @@ const failable<int> login(const string& page, const value& ref, const value& att return httpd::externalRedirect(loc, r); } +/** + * Report a request auth status. + */ +const int reportStatus(const failable<int>& authrc, const string& page, const value& attempt, request_rec* const r) { + debug(authrc, "openauth::reportStatus::authrc"); + + // Redirect to the login page if not authorized + if (!hasContent(authrc) && rcode(authrc) == HTTP_UNAUTHORIZED) { + + // Clear any auth cookies + if(hasContent(sessionID(r, "TuscanyOpenAuth"))) + apr_table_set(r->err_headers_out, "Set-Cookie", c_str(cookie("TuscanyOpenAuth", emptyString, httpd::hostName(r)))); + if(hasContent(sessionID(r, "TuscanyOpenIDAuth"))) + apr_table_set(r->err_headers_out, "Set-Cookie", c_str(cookie("TuscanyOpenIDAuth", emptyString, httpd::hostName(r)))); + if(hasContent(sessionID(r, "TuscanyOAuth1"))) + apr_table_set(r->err_headers_out, "Set-Cookie", c_str(cookie("TuscanyOAuth1", emptyString, httpd::hostName(r)))); + if(hasContent(sessionID(r, "TuscanyOAuth2"))) + apr_table_set(r->err_headers_out, "Set-Cookie", c_str(cookie("TuscanyOAuth2", emptyString, httpd::hostName(r)))); + + return httpd::reportStatus(login(page, string("/"), attempt, r)); + } + + return httpd::reportStatus(authrc); +} + } } diff --git a/sca-cpp/trunk/modules/java/Makefile.am b/sca-cpp/trunk/modules/java/Makefile.am index 8b80276d15..a25576537c 100644 --- a/sca-cpp/trunk/modules/java/Makefile.am +++ b/sca-cpp/trunk/modules/java/Makefile.am @@ -36,7 +36,7 @@ EXTRA_DIST = domain-test.composite mod_LTLIBRARIES = libmod_tuscany_java.la libmod_tuscany_java_la_SOURCES = mod-java.cpp -libmod_tuscany_java_la_LDFLAGS = -lxml2 -lcurl -lmozjs ${JAVA_LDFLAGS} +libmod_tuscany_java_la_LDFLAGS = -lxml2 -lcurl -ljansson ${JAVA_LDFLAGS} noinst_DATA = libmod_tuscany_java${libsuffix} libmod_tuscany_java${libsuffix}: ln -s .libs/libmod_tuscany_java${libsuffix} @@ -55,12 +55,13 @@ jardir = ${prefix}/modules/java jarfile = libmod-tuscany-java-${PACKAGE_VERSION}.jar jar_DATA = ${jarfile} ${jarfile}: ${dist_mod_JAVA} + ${JAVAC} ${dist_mod_JAVA} ${JAR} cf $@ org/apache/tuscany/*.class CLEANFILES = *.stamp ${jarfile} org/apache/tuscany/*.class test/*.class client_test_SOURCES = client-test.cpp -client_test_LDFLAGS = -lxml2 -lcurl -lmozjs +client_test_LDFLAGS = -lxml2 -lcurl -ljansson dist_noinst_SCRIPTS = server-test wiring-test noinst_PROGRAMS = jni-test java-test client-test diff --git a/sca-cpp/trunk/modules/java/driver.hpp b/sca-cpp/trunk/modules/java/driver.hpp index ddfc057940..4ffc84f4db 100644 --- a/sca-cpp/trunk/modules/java/driver.hpp +++ b/sca-cpp/trunk/modules/java/driver.hpp @@ -37,7 +37,7 @@ namespace java { const value evalDriverLoop(const JavaRuntime& jr, const JavaClass jc, istream& in, ostream& out) { scheme::promptForInput(scheme::evalInputPrompt, out); - value input = scheme::readValue(in); + const value input = content(scheme::readValue(in)); if (isNil(input)) return input; const failable<value> output = evalClass(jr, input, jc); @@ -46,7 +46,7 @@ const value evalDriverLoop(const JavaRuntime& jr, const JavaClass jc, istream& i return evalDriverLoop(jr, jc, in, out); } -const bool evalDriverRun(const char* name, istream& in, ostream& out) { +const bool evalDriverRun(const char* const name, istream& in, ostream& out) { scheme::setupDisplay(out); JavaRuntime javaRuntime; const failable<JavaClass> jc = readClass(javaRuntime, ".", name); diff --git a/sca-cpp/trunk/modules/java/eval.hpp b/sca-cpp/trunk/modules/java/eval.hpp index 31fb09f741..2c76b764fa 100644 --- a/sca-cpp/trunk/modules/java/eval.hpp +++ b/sca-cpp/trunk/modules/java/eval.hpp @@ -50,12 +50,12 @@ jobject JNICALL nativeUUID(JNIEnv *env); class JavaRuntime { public: - JavaRuntime() { + JavaRuntime() : h(*(new (gc_new<handles>()) handles())) { debug("java::javaruntime"); // Get existing JVM jsize nvms = 0; - JNI_GetCreatedJavaVMs(&jvm, 1, &nvms); + JNI_GetCreatedJavaVMs(&h.jvm, 1, &nvms); if (nvms == 0) { // Create a new JVM @@ -67,7 +67,7 @@ public: args.nOptions = 0; // Configure classpath - const char* envcp = getenv("CLASSPATH"); + const char* const envcp = getenv("CLASSPATH"); const string cp = string("-Djava.class.path=") + (envcp == NULL? "." : envcp); options[args.nOptions].optionString = const_cast<char*>(c_str(cp)); options[args.nOptions++].extraInfo = NULL; @@ -78,12 +78,12 @@ public: #endif // Configure Java debugging - const char* jpdaopts = getenv("JPDA_OPTS"); + const char* const jpdaopts = getenv("JPDA_OPTS"); if (jpdaopts != NULL) { options[args.nOptions].optionString = const_cast<char*>(jpdaopts); options[args.nOptions++].extraInfo = NULL; } else { - const char* jpdaaddr = getenv("JPDA_ADDRESS"); + const char* const jpdaaddr = getenv("JPDA_ADDRESS"); if (jpdaaddr != NULL) { const string jpda = string("-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=") + jpdaaddr; options[args.nOptions].optionString = const_cast<char*>(c_str(jpda)); @@ -93,114 +93,131 @@ public: // Create the JVM #ifdef JAVA_HARMONY_VM - JNI_CreateJavaVM(&jvm, &env, &args); + JNI_CreateJavaVM(&h.jvm, &h.env, &args); #else - JNI_CreateJavaVM(&jvm, (void**)&env, &args); + JNI_CreateJavaVM(&h.jvm, (void**)&h.env, &args); #endif } else { // Just point to existing JVM - jvm->GetEnv((void**)&env, JNI_VERSION); + h.jvm->GetEnv((void**)&h.env, JNI_VERSION); } // Lookup System classes and methods - classClass = env->FindClass("java/lang/Class"); - methodClass = env->FindClass("java/lang/reflect/Method"); - objectClass = env->FindClass("java/lang/Object"); - doubleClass = env->FindClass("java/lang/Double"); - booleanClass = env->FindClass("java/lang/Boolean"); - stringClass = env->FindClass("java/lang/String"); - objectArrayClass = env->FindClass("[Ljava/lang/Object;"); - iterableClass = env->FindClass("java/lang/Iterable"); - classForName = env->GetStaticMethodID(classClass, "forName", "(Ljava/lang/String;ZLjava/lang/ClassLoader;)Ljava/lang/Class;"); - doubleValueOf = env->GetStaticMethodID(doubleClass, "valueOf", "(D)Ljava/lang/Double;"); - doubleValue = env->GetMethodID(doubleClass, "doubleValue", "()D"); - booleanValueOf = env->GetStaticMethodID(booleanClass, "valueOf", "(Z)Ljava/lang/Boolean;"); - booleanValue = env->GetMethodID(booleanClass, "booleanValue", "()Z"); - declaredMethods = env->GetMethodID(classClass, "getDeclaredMethods", "()[Ljava/lang/reflect/Method;"); - methodName = env->GetMethodID(methodClass, "getName", "()Ljava/lang/String;"); - parameterTypes = env->GetMethodID(methodClass, "getParameterTypes", "()[Ljava/lang/Class;"); + h.classClass = h.env->FindClass("java/lang/Class"); + h.methodClass = h.env->FindClass("java/lang/reflect/Method"); + h.objectClass = h.env->FindClass("java/lang/Object"); + h.doubleClass = h.env->FindClass("java/lang/Double"); + h.booleanClass = h.env->FindClass("java/lang/Boolean"); + h.stringClass = h.env->FindClass("java/lang/String"); + h.objectArrayClass = h.env->FindClass("[Ljava/lang/Object;"); + h.iterableClass = h.env->FindClass("java/lang/Iterable"); + h.classForName = h.env->GetStaticMethodID(h.classClass, "forName", "(Ljava/lang/String;ZLjava/lang/ClassLoader;)Ljava/lang/Class;"); + h.doubleValueOf = h.env->GetStaticMethodID(h.doubleClass, "valueOf", "(D)Ljava/lang/Double;"); + h.doubleValue = h.env->GetMethodID(h.doubleClass, "doubleValue", "()D"); + h.booleanValueOf = h.env->GetStaticMethodID(h.booleanClass, "valueOf", "(Z)Ljava/lang/Boolean;"); + h.booleanValue = h.env->GetMethodID(h.booleanClass, "booleanValue", "()Z"); + h.declaredMethods = h.env->GetMethodID(h.classClass, "getDeclaredMethods", "()[Ljava/lang/reflect/Method;"); + h.methodName = h.env->GetMethodID(h.methodClass, "getName", "()Ljava/lang/String;"); + h.parameterTypes = h.env->GetMethodID(h.methodClass, "getParameterTypes", "()[Ljava/lang/Class;"); // Lookup Tuscany classes and methods - loaderClass = env->FindClass("org/apache/tuscany/ClassLoader"); - loaderValueOf = env->GetStaticMethodID(loaderClass, "valueOf", "(Ljava/lang/String;)Ljava/lang/ClassLoader;"); - loaderForName = env->GetStaticMethodID(loaderClass, "forName", "(Ljava/lang/String;ZLjava/lang/ClassLoader;)Ljava/lang/Class;"); - invokerClass = env->FindClass("org/apache/tuscany/InvocationHandler"); - invokerValueOf = env->GetStaticMethodID(invokerClass, "valueOf", "(Ljava/lang/Class;J)Ljava/lang/Object;"); - invokerStackTrace = env->GetStaticMethodID(invokerClass, "stackTrace", "(Ljava/lang/Throwable;)Ljava/lang/String;"); - invokerLambda = env->GetFieldID(invokerClass, "lambda", "J"); - iterableUtilClass = env->FindClass("org/apache/tuscany/IterableUtil"); - iterableValueOf = env->GetStaticMethodID(iterableUtilClass, "list", "([Ljava/lang/Object;)Ljava/lang/Iterable;"); - iterableIsNil = env->GetStaticMethodID(iterableUtilClass, "isNil", "(Ljava/lang/Object;)Z"); - iterableCar = env->GetStaticMethodID(iterableUtilClass, "car", "(Ljava/lang/Object;)Ljava/lang/Object;"); - iterableCdr = env->GetStaticMethodID(iterableUtilClass, "cdr", "(Ljava/lang/Object;)Ljava/lang/Iterable;"); - uuidClass = env->FindClass("org/apache/tuscany/UUIDUtil"); + h.loaderClass = h.env->FindClass("org/apache/tuscany/ClassLoader"); + h.loaderValueOf = h.env->GetStaticMethodID(h.loaderClass, "valueOf", "(Ljava/lang/String;)Ljava/lang/ClassLoader;"); + h.loaderForName = h.env->GetStaticMethodID(h.loaderClass, "forName", "(Ljava/lang/String;ZLjava/lang/ClassLoader;)Ljava/lang/Class;"); + h.invokerClass = h.env->FindClass("org/apache/tuscany/InvocationHandler"); + h.invokerValueOf = h.env->GetStaticMethodID(h.invokerClass, "valueOf", "(Ljava/lang/Class;J)Ljava/lang/Object;"); + h.invokerStackTrace = h.env->GetStaticMethodID(h.invokerClass, "stackTrace", "(Ljava/lang/Throwable;)Ljava/lang/String;"); + h.invokerLambda = h.env->GetFieldID(h.invokerClass, "lambda", "J"); + h.iterableUtilClass = h.env->FindClass("org/apache/tuscany/IterableUtil"); + h.iterableValueOf = h.env->GetStaticMethodID(h.iterableUtilClass, "list", "([Ljava/lang/Object;)Ljava/lang/Iterable;"); + h.iterableIsNil = h.env->GetStaticMethodID(h.iterableUtilClass, "isNil", "(Ljava/lang/Object;)Z"); + h.iterableCar = h.env->GetStaticMethodID(h.iterableUtilClass, "car", "(Ljava/lang/Object;)Ljava/lang/Object;"); + h.iterableCdr = h.env->GetStaticMethodID(h.iterableUtilClass, "cdr", "(Ljava/lang/Object;)Ljava/lang/Iterable;"); + h.uuidClass = h.env->FindClass("org/apache/tuscany/UUIDUtil"); // Register our native invocation handler function JNINativeMethod invokenm; invokenm.name = const_cast<char*>("invoke"); invokenm.signature = const_cast<char*>("(Ljava/lang/Object;Ljava/lang/reflect/Method;[Ljava/lang/Object;)Ljava/lang/Object;"); invokenm.fnPtr = (void*)nativeInvoke; - env->RegisterNatives(invokerClass, &invokenm, 1); + h.env->RegisterNatives(h.invokerClass, &invokenm, 1); // Register our native UUID function JNINativeMethod uuidnm; uuidnm.name = const_cast<char*>("uuid"); uuidnm.signature = const_cast<char*>("()Ljava/lang/String;"); uuidnm.fnPtr = (void*)nativeUUID; - env->RegisterNatives(uuidClass, &uuidnm, 1); + h.env->RegisterNatives(h.uuidClass, &uuidnm, 1); } + JavaRuntime(const JavaRuntime& c) : h(c.h) { + } + + JavaRuntime& operator=(const JavaRuntime&) = delete; + ~JavaRuntime() { } - JavaVM* jvm; - JNIEnv* env; - - jclass classClass; - jclass methodClass; - jclass objectClass; - jclass doubleClass; - jclass booleanClass; - jclass stringClass; - jclass objectArrayClass; - jclass iterableClass; - jmethodID doubleValueOf; - jmethodID doubleValue; - jmethodID booleanValueOf; - jmethodID booleanValue; - jmethodID declaredMethods; - jmethodID methodName; - jmethodID parameterTypes; - jmethodID classForName; - jclass loaderClass; - jmethodID loaderValueOf; - jmethodID loaderForName; - jclass invokerClass; - jmethodID invokerValueOf; - jmethodID invokerStackTrace; - jfieldID invokerLambda; - jclass iterableUtilClass; - jmethodID iterableValueOf; - jmethodID iterableCar; - jmethodID iterableCdr; - jmethodID iterableIsNil; - jclass uuidClass; +public: + class handles { + public: + handles() { + } + + public: + friend class JavaRuntime; + + JavaVM* jvm; + JNIEnv* env; + + jclass classClass; + jclass methodClass; + jclass objectClass; + jclass doubleClass; + jclass booleanClass; + jclass stringClass; + jclass objectArrayClass; + jclass iterableClass; + jmethodID doubleValueOf; + jmethodID doubleValue; + jmethodID booleanValueOf; + jmethodID booleanValue; + jmethodID declaredMethods; + jmethodID methodName; + jmethodID parameterTypes; + jmethodID classForName; + jclass loaderClass; + jmethodID loaderValueOf; + jmethodID loaderForName; + jclass invokerClass; + jmethodID invokerValueOf; + jmethodID invokerStackTrace; + jfieldID invokerLambda; + jclass iterableUtilClass; + jmethodID iterableValueOf; + jmethodID iterableCar; + jmethodID iterableCdr; + jmethodID iterableIsNil; + jclass uuidClass; + }; + + handles& h; }; /** * Return the last exception that occurred in a JVM. */ -string lastException(const JavaRuntime& jr) { - if (!jr.env->ExceptionCheck()) +const string lastException(const JavaRuntime& jr) { + if (!jr.h.env->ExceptionCheck()) return "No Exception"; - const jthrowable ex = jr.env->ExceptionOccurred(); - const jstring trace = (jstring)jr.env->CallStaticObjectMethod(jr.invokerClass, jr.invokerStackTrace, ex); - const char* c = jr.env->GetStringUTFChars(trace, NULL); + const jthrowable ex = jr.h.env->ExceptionOccurred(); + const jstring trace = (jstring)jr.h.env->CallStaticObjectMethod(jr.h.invokerClass, jr.h.invokerStackTrace, ex); + const char* const c = jr.h.env->GetStringUTFChars(trace, NULL); const string msg(c); - jr.env->ReleaseStringUTFChars(trace, c); - jr.env->ExceptionClear(); + jr.h.env->ReleaseStringUTFChars(trace, c); + jr.h.env->ExceptionClear(); return msg; } @@ -216,7 +233,7 @@ const list<value> jiterableToValues(const JavaRuntime& jr, const jobject o); /** * Convert a Java class name to a JNI class name. */ -const bool jniClassNameHelper(char* to, const char* from) { +const bool jniClassNameHelper(char* const to, const char* const from) { if (*from == '\0') { *to = '\0'; return true; @@ -236,7 +253,7 @@ const string jniClassName(const string& from) { */ class javaLambda { public: - javaLambda(const JavaRuntime& jr, const value& iface, const lambda<value(const list<value>&)>& func) : jr(jr), iface(iface), func(func) { + javaLambda(const JavaRuntime& jr, const value& iface, const lvvlambda& func) : jr(jr), iface(iface), func(func) { } const value operator()(const list<value>& expr) const { @@ -255,9 +272,10 @@ public: return func(expr); } - const JavaRuntime& jr; +public: + const JavaRuntime jr; const value iface; - const lambda<value(const list<value>&)> func; + const lvvlambda func; }; /** @@ -267,12 +285,12 @@ public: jobject JNICALL nativeInvoke(JNIEnv* env, jobject self, unused jobject proxy, jobject method, jobjectArray args) { // Retrieve the lambda function from the invocation handler - jclass clazz = env->GetObjectClass(self); - jfieldID f = env->GetFieldID(clazz, "lambda", "J"); + const jclass clazz = env->GetObjectClass(self); + const jfieldID f = env->GetFieldID(clazz, "lambda", "J"); const javaLambda& jl = *(javaLambda*)(long)env->GetLongField(self, f); // Retrieve the function name - const jstring s = (jstring)env->CallObjectMethod(method, jl.jr.methodName); + const jstring s = (jstring)env->CallObjectMethod(method, jl.jr.h.methodName); const char* c = env->GetStringUTFChars(s, NULL); const value func(c); env->ReleaseStringUTFChars(s, c); @@ -287,7 +305,7 @@ jobject JNICALL nativeInvoke(JNIEnv* env, jobject self, unused jobject proxy, jo debug(result, "java::nativeInvoke::result"); // Convert result to a jobject - return valueToJobject(jl.jr, value(), result); + return valueToJobject(jl.jr, nilValue, result); } /** @@ -302,10 +320,10 @@ jobject JNICALL nativeUUID(JNIEnv* env) { /** * Convert a lambda function to Java proxy. */ -const jobject mkJavaLambda(const JavaRuntime& jr, unused const value& iface, const lambda<value(const list<value>&)>& l) { +const jobject mkJavaLambda(const JavaRuntime& jr, unused const value& iface, const lvvlambda& l) { const gc_ptr<javaLambda> jl = new (gc_new<javaLambda>()) javaLambda(jr, iface, l); jclass jc = (jclass)(long)(double)iface; - const jobject obj = jr.env->CallStaticObjectMethod(jr.invokerClass, jr.invokerValueOf, jc, (long)(javaLambda*)jl); + const jobject obj = jr.h.env->CallStaticObjectMethod(jr.h.invokerClass, jr.h.invokerValueOf, jc, (long)(javaLambda*)jl); return obj; } @@ -315,20 +333,20 @@ const jobject mkJavaLambda(const JavaRuntime& jr, unused const value& iface, con const jobjectArray valuesToJarrayHelper(const JavaRuntime& jr, jobjectArray a, const list<value>& v, const int i) { if (isNil(v)) return a; - jr.env->SetObjectArrayElement(a, i, valueToJobject(jr, value(), car(v))); + jr.h.env->SetObjectArrayElement(a, i, valueToJobject(jr, nilValue, car(v))); return valuesToJarrayHelper(jr, a, cdr(v), i + 1); } const jobjectArray valuesToJarray(const JavaRuntime& jr, const list<value>& v) { - jobjectArray a = jr.env->NewObjectArray((jsize)length(v), jr.objectClass, NULL); + jobjectArray a = jr.h.env->NewObjectArray((jsize)length(v), jr.h.objectClass, NULL); return valuesToJarrayHelper(jr, a, v, 0); } /** * Convert a Java jobjectArray to a Java iterable. */ -const jobject jarrayToJiterable(const JavaRuntime& jr, jobjectArray a) { - return jr.env->CallStaticObjectMethod(jr.iterableClass, jr.iterableValueOf, a); +const jobject jarrayToJiterable(const JavaRuntime& jr, const jobjectArray a) { + return jr.h.env->CallStaticObjectMethod(jr.h.iterableClass, jr.h.iterableValueOf, a); } /** @@ -341,13 +359,13 @@ const jobject valueToJobject(const JavaRuntime& jr, const value& jtype, const va case value::Lambda: return mkJavaLambda(jr, jtype, v); case value::Symbol: - return jr.env->NewStringUTF(c_str(string("'") + v)); + return jr.h.env->NewStringUTF(c_str(string("'") + (string)v)); case value::String: - return jr.env->NewStringUTF(c_str(v)); + return jr.h.env->NewStringUTF(c_str(v)); case value::Number: - return jr.env->CallStaticObjectMethod(jr.doubleClass, jr.doubleValueOf, (double)v); + return jr.h.env->CallStaticObjectMethod(jr.h.doubleClass, jr.h.doubleValueOf, (double)v); case value::Bool: - return jr.env->CallStaticObjectMethod(jr.booleanClass, jr.booleanValueOf, (bool)v); + return jr.h.env->CallStaticObjectMethod(jr.h.booleanClass, jr.h.booleanValueOf, (bool)v); default: return NULL; } @@ -356,7 +374,7 @@ const jobject valueToJobject(const JavaRuntime& jr, const value& jtype, const va /** * Convert a list of values to an array of jvalues. */ -const jvalue* valuesToJvaluesHelper(const JavaRuntime& jr, jvalue* a, const list<value>& types, const list<value>& v) { +const jvalue* valuesToJvaluesHelper(const JavaRuntime& jr, jvalue* const a, const list<value>& types, const list<value>& v) { if (isNil(v)) return a; a->l = valueToJobject(jr, car(types), car(v)); @@ -365,7 +383,7 @@ const jvalue* valuesToJvaluesHelper(const JavaRuntime& jr, jvalue* a, const list const jvalue* valuesToJvalues(const JavaRuntime& jr, const list<value>& types, const list<value>& v) { const size_t n = length(v); - jvalue* a = new (gc_anew<jvalue>(n)) jvalue[n]; + jvalue* const a = new (gc_anew<jvalue>(n)) jvalue[n]; valuesToJvaluesHelper(jr, a, types, v); return a; } @@ -373,79 +391,67 @@ const jvalue* valuesToJvalues(const JavaRuntime& jr, const list<value>& types, c /** * Convert a Java jobjectArray to a list of values. */ -const list<value> jarrayToValuesHelper(const JavaRuntime& jr, jobjectArray a, const int i, const int size) { +const list<value> jarrayToValuesHelper(const JavaRuntime& jr, const jobjectArray a, const int i, const int size) { if (i == size) - return list<value>(); - return cons(jobjectToValue(jr, jr.env->GetObjectArrayElement(a, i)), jarrayToValuesHelper(jr, a, i + 1, size)); + return nilListValue; + return cons(jobjectToValue(jr, jr.h.env->GetObjectArrayElement(a, i)), jarrayToValuesHelper(jr, a, i + 1, size)); } -const list<value> jarrayToValues(const JavaRuntime& jr, jobjectArray o) { +const list<value> jarrayToValues(const JavaRuntime& jr, const jobjectArray o) { if (o == NULL) - return list<value>(); - return jarrayToValuesHelper(jr, o, 0, jr.env->GetArrayLength(o)); + return nilListValue; + return jarrayToValuesHelper(jr, o, 0, jr.h.env->GetArrayLength(o)); } /** * Convert a Java Iterable to a list of values. */ -const list<value> jiterableToValuesHelper(const JavaRuntime& jr, jobject o) { - if ((bool)jr.env->CallStaticBooleanMethod(jr.iterableUtilClass, jr.iterableIsNil, o)) - return list<value>(); - jobject car = jr.env->CallStaticObjectMethod(jr.iterableUtilClass, jr.iterableCar, o); - jobject cdr = jr.env->CallStaticObjectMethod(jr.iterableUtilClass, jr.iterableCdr, o); +const list<value> jiterableToValuesHelper(const JavaRuntime& jr, const jobject o) { + if ((bool)jr.h.env->CallStaticBooleanMethod(jr.h.iterableUtilClass, jr.h.iterableIsNil, o)) + return nilListValue; + const jobject car = jr.h.env->CallStaticObjectMethod(jr.h.iterableUtilClass, jr.h.iterableCar, o); + const jobject cdr = jr.h.env->CallStaticObjectMethod(jr.h.iterableUtilClass, jr.h.iterableCdr, o); return cons(jobjectToValue(jr, car), jiterableToValuesHelper(jr, cdr)); } -const list<value> jiterableToValues(const JavaRuntime& jr, jobject o) { +const list<value> jiterableToValues(const JavaRuntime& jr, const jobject o) { if (o == NULL) - return list<value>(); + return nilListValue; return jiterableToValuesHelper(jr, o); } /** - * Lambda function used to represent a Java callable object. - */ -struct javaCallable { - const JavaRuntime& jr; - const jobject obj; - - javaCallable(const JavaRuntime& jr, const jobject obj) : jr(jr), obj(obj) { - } - - const value operator()(const list<value>& args) const { - jobjectArray jargs = valuesToJarray(jr, args); - jobject result = jargs; //CallObject(func, jargs); - return jobjectToValue(jr, result); - } -}; - -/** * Convert a Java jobject to a value. */ const value jobjectToValue(const JavaRuntime& jr, const jobject o) { if (o == NULL) - return value(); - const jclass clazz = jr.env->GetObjectClass(o); - if ((jr.env->IsSameObject(clazz, jr.stringClass))) { - const char* s = jr.env->GetStringUTFChars((jstring)o, NULL); + return nilValue; + const jclass clazz = jr.h.env->GetObjectClass(o); + if ((jr.h.env->IsSameObject(clazz, jr.h.stringClass))) { + const char* const s = jr.h.env->GetStringUTFChars((jstring)o, NULL); if (*s == '\'') { const value v(s + 1); - jr.env->ReleaseStringUTFChars((jstring)o, s); + jr.h.env->ReleaseStringUTFChars((jstring)o, s); return v; } const value v = string(s); - jr.env->ReleaseStringUTFChars((jstring)o, s); + jr.h.env->ReleaseStringUTFChars((jstring)o, s); return v; } - if (jr.env->IsSameObject(clazz, jr.booleanClass)) - return value((bool)jr.env->CallBooleanMethod(o, jr.booleanValue)); - if (jr.env->IsSameObject(clazz, jr.doubleClass)) - return value((double)jr.env->CallDoubleMethod(o, jr.doubleValue)); - if (jr.env->IsAssignableFrom(clazz, jr.iterableClass)) + if (jr.h.env->IsSameObject(clazz, jr.h.booleanClass)) + return value((bool)jr.h.env->CallBooleanMethod(o, jr.h.booleanValue)); + if (jr.h.env->IsSameObject(clazz, jr.h.doubleClass)) + return value((double)jr.h.env->CallDoubleMethod(o, jr.h.doubleValue)); + if (jr.h.env->IsAssignableFrom(clazz, jr.h.iterableClass)) return jiterableToValues(jr, o); - if (jr.env->IsAssignableFrom(clazz, jr.objectArrayClass)) + if (jr.h.env->IsAssignableFrom(clazz, jr.h.objectArrayClass)) return jarrayToValues(jr, (jobjectArray)o); - return lambda<value(const list<value>&)>(javaCallable(jr, o)); + const lvvlambda javaCallable = [jr](const list<value>& params) -> const value { + jobjectArray jargs = valuesToJarray(jr, params); + jobject result = jargs; //CallObject(func, jargs); + return jobjectToValue(jr, result); + }; + return value(javaCallable); } /** @@ -457,33 +463,33 @@ const value parameterTypeToValue(const jobject t) { const list<value> parameterTypesToValues(const JavaRuntime& jr, const jobjectArray t, const int i) { if (i == 0) - return list<value>(); - return cons<value>(parameterTypeToValue(jr.env->GetObjectArrayElement(t, i - 1)), parameterTypesToValues(jr, t, i - 1)); + return nilListValue; + return cons<value>(parameterTypeToValue(jr.h.env->GetObjectArrayElement(t, i - 1)), parameterTypesToValues(jr, t, i - 1)); } const value methodToValue(const JavaRuntime& jr, const jobject m) { - const jobject s = jr.env->CallObjectMethod(m, jr.methodName); - const char* c = jr.env->GetStringUTFChars((jstring)s, NULL); + const jobject s = jr.h.env->CallObjectMethod(m, jr.h.methodName); + const char* const c = jr.h.env->GetStringUTFChars((jstring)s, NULL); const string& name = string(c); - jr.env->ReleaseStringUTFChars((jstring)s, c); + jr.h.env->ReleaseStringUTFChars((jstring)s, c); - const jmethodID mid = jr.env->FromReflectedMethod(m); + const jmethodID mid = jr.h.env->FromReflectedMethod(m); - const jobjectArray t = (jobjectArray)jr.env->CallObjectMethod(m, jr.parameterTypes); - const list<value> types = reverse(parameterTypesToValues(jr, t, jr.env->GetArrayLength(t))); + const jobjectArray t = (jobjectArray)jr.h.env->CallObjectMethod(m, jr.h.parameterTypes); + const list<value> types = reverse(parameterTypesToValues(jr, t, jr.h.env->GetArrayLength(t))); return cons<value>(c_str(name), cons<value>((double)(long)mid, types)); } const list<value> methodsToValues(const JavaRuntime& jr, const jobjectArray m, const int i) { if (i == 0) - return list<value>(); - return cons<value>(methodToValue(jr, jr.env->GetObjectArrayElement(m, i - 1)), methodsToValues(jr, m, i - 1)); + return nilListValue; + return cons<value>(methodToValue(jr, jr.h.env->GetObjectArrayElement(m, i - 1)), methodsToValues(jr, m, i - 1)); } const list<value> methodsToValues(const JavaRuntime& jr, const jclass clazz) { - const jobjectArray m = (jobjectArray)jr.env->CallObjectMethod(clazz, jr.declaredMethods); - return methodsToValues(jr, m, jr.env->GetArrayLength(m)); + const jobjectArray m = (jobjectArray)jr.h.env->CallObjectMethod(clazz, jr.h.declaredMethods); + return methodsToValues(jr, m, jr.h.env->GetArrayLength(m)); } /** @@ -508,20 +514,20 @@ public: const failable<JavaClass> readClass(const JavaRuntime& jr, const string& path, const string& name) { // Create a class loader from the given path - const jobject jpath = jr.env->NewStringUTF(c_str(path)); - jobject loader = jr.env->CallStaticObjectMethod(jr.loaderClass, jr.loaderValueOf, jpath); + const jobject jpath = jr.h.env->NewStringUTF(c_str(path)); + const jobject loader = jr.h.env->CallStaticObjectMethod(jr.h.loaderClass, jr.h.loaderValueOf, jpath); // Load the class - const jobject jname = jr.env->NewStringUTF(c_str(name)); - const jclass clazz = (jclass)jr.env->CallStaticObjectMethod(jr.loaderClass, jr.loaderForName, jname, JNI_TRUE, loader); + const jobject jname = jr.h.env->NewStringUTF(c_str(name)); + const jclass clazz = (jclass)jr.h.env->CallStaticObjectMethod(jr.h.loaderClass, jr.h.loaderForName, jname, JNI_TRUE, loader); if (clazz == NULL) return mkfailure<JavaClass>(string("Couldn't load class: ") + name + " : " + lastException(jr)); // Create an instance - const jmethodID constr = jr.env->GetMethodID(clazz, "<init>", "()V"); + const jmethodID constr = jr.h.env->GetMethodID(clazz, "<init>", "()V"); if (constr == NULL) return mkfailure<JavaClass>(string("Couldn't find constructor: ") + name + " : " + lastException(jr)); - const jobject obj = jr.env->NewObject(clazz, constr); + const jobject obj = jr.h.env->NewObject(clazz, constr); if (obj == NULL) return mkfailure<JavaClass>(string("Couldn't construct object: ") + name + " : " + lastException(jr)); @@ -541,19 +547,19 @@ const failable<value> evalClass(const JavaRuntime& jr, const value& expr, const // The start, stop, and restart functions are optional const value fn = car<value>(expr); if (fn == "start" || fn == "stop") - return value(lambda<value(const list<value>&)>()); + return value(lvvlambda()); - return mkfailure<value>(string("Couldn't find function: ") + car<value>(expr) + " : " + lastException(jr)); + return mkfailure<value>(string("Couldn't find function: ") + (string)car<value>(expr) + " : " + lastException(jr)); } const jmethodID fid = (jmethodID)(long)(double)cadr(func); // Convert args to Java jvalues - const jvalue* args = valuesToJvalues(jr, cddr(func), cdr<value>(expr)); + const jvalue* const args = valuesToJvalues(jr, cddr(func), cdr<value>(expr)); // Call the Java function - const jobject result = jr.env->CallObjectMethodA(jc.obj, fid, const_cast<jvalue*>(args)); + const jobject result = jr.h.env->CallObjectMethodA(jc.obj, fid, const_cast<jvalue*>(args)); if (result == NULL) - return mkfailure<value>(string("Function call failed: ") + car<value>(expr) + " : " + lastException(jr)); + return mkfailure<value>(string("Function call failed: ") + (string)car<value>(expr) + " : " + lastException(jr)); // Convert Java result to a value const value v = jobjectToValue(jr, result); diff --git a/sca-cpp/trunk/modules/java/java-shell.cpp b/sca-cpp/trunk/modules/java/java-shell.cpp index 51df513990..d76fa8b45b 100644 --- a/sca-cpp/trunk/modules/java/java-shell.cpp +++ b/sca-cpp/trunk/modules/java/java-shell.cpp @@ -29,8 +29,8 @@ #include "string.hpp" #include "driver.hpp" -int main(const int argc, char** argv) { - tuscany::gc_scoped_pool pool; +int main(const int argc, const char** const argv) { + const tuscany::gc_scoped_pool pool; if (argc != 2) { tuscany::cerr << "Usage: java-shell <class name>" << tuscany::endl; return 1; diff --git a/sca-cpp/trunk/modules/java/java-test.cpp b/sca-cpp/trunk/modules/java/java-test.cpp index f811a4f58d..7ae170d03f 100644 --- a/sca-cpp/trunk/modules/java/java-test.cpp +++ b/sca-cpp/trunk/modules/java/java-test.cpp @@ -32,8 +32,8 @@ namespace tuscany { namespace java { bool testEvalExpr() { - gc_scoped_pool pool; - JavaRuntime javaRuntime; + const gc_scoped_pool pool; + const JavaRuntime javaRuntime; { const failable<JavaClass> obj = readClass(javaRuntime, ".", "test.CalcImpl"); assert(hasContent(obj)); @@ -48,7 +48,7 @@ bool testEvalExpr() { const value exp = mklist<value>("even", 2); const failable<value> r = evalClass(javaRuntime, exp, content(obj)); assert(hasContent(r)); - assert(content(r) == value(true)); + assert(content(r) == trueValue); } { const failable<JavaClass> obj = readClass(javaRuntime, ".", "test.AdderImpl"); @@ -77,12 +77,12 @@ const value add(const list<value>& args) { } bool testEvalLambda() { - gc_scoped_pool pool; - JavaRuntime javaRuntime; + const gc_scoped_pool pool; + const JavaRuntime javaRuntime; { const failable<JavaClass> obj = readClass(javaRuntime, ".", "test.CalcImpl"); assert(hasContent(obj)); - const value tcel = mklist<value>("add", 3, 4, lambda<value(const list<value>&)>(add)); + const value tcel = mklist<value>("add", 3, 4, lvvlambda(add)); const failable<value> r = evalClass(javaRuntime, tcel, content(obj)); assert(hasContent(r)); assert(content(r) == value(7)); @@ -90,7 +90,7 @@ bool testEvalLambda() { { const failable<JavaClass> obj = readClass(javaRuntime, ".", "test.CalcImpl"); assert(hasContent(obj)); - const value tcel = mklist<value>("addEval", 3, 4, lambda<value(const list<value>&)>(add)); + const value tcel = mklist<value>("addEval", 3, 4, lvvlambda(add)); const failable<value> r = evalClass(javaRuntime, tcel, content(obj)); assert(hasContent(r)); assert(content(r) == value(7)); @@ -99,26 +99,26 @@ bool testEvalLambda() { } bool testClassLoader() { - gc_scoped_pool pool; - JavaRuntime javaRuntime; + const gc_scoped_pool pool; + const JavaRuntime javaRuntime; const failable<JavaClass> obj = readClass(javaRuntime, ".", "org.apache.tuscany.ClassLoader$Test"); assert(hasContent(obj)); const value exp = mklist<value>("testClassLoader"); const failable<value> r = evalClass(javaRuntime, exp, content(obj)); assert(hasContent(r)); - assert(content(r) == value(true)); + assert(content(r) == trueValue); return true; } bool testIterableUtil() { - gc_scoped_pool pool; - JavaRuntime javaRuntime; + const gc_scoped_pool pool; + const JavaRuntime javaRuntime; const failable<JavaClass> obj = readClass(javaRuntime, ".", "org.apache.tuscany.IterableUtil$Test"); assert(hasContent(obj)); const value exp = mklist<value>("testList"); const failable<value> r = evalClass(javaRuntime, exp, content(obj)); assert(hasContent(r)); - assert(content(r) == value(true)); + assert(content(r) == trueValue); return true; } diff --git a/sca-cpp/trunk/modules/java/jni-test.cpp b/sca-cpp/trunk/modules/java/jni-test.cpp index 727af13dc6..f69460f235 100644 --- a/sca-cpp/trunk/modules/java/jni-test.cpp +++ b/sca-cpp/trunk/modules/java/jni-test.cpp @@ -40,7 +40,7 @@ namespace java { #endif bool testJNI() { - gc_scoped_pool pool; + const gc_scoped_pool pool; JavaVM* jvm; JNIEnv* env; @@ -50,7 +50,7 @@ bool testJNI() { JavaVMOption options[3]; args.options = options; args.nOptions = 0; - const char* envcp = getenv("CLASSPATH"); + const char* const envcp = getenv("CLASSPATH"); const string cp = string("-Djava.class.path=") + (envcp == NULL? "." : envcp); options[args.nOptions].optionString = const_cast<char*>(c_str(cp)); options[args.nOptions++].extraInfo = NULL; @@ -60,9 +60,9 @@ bool testJNI() { JNI_CreateJavaVM(&jvm, (void**)&env, &args); #endif - jclass classClass = env->FindClass("java/lang/Class"); + const jclass classClass = env->FindClass("java/lang/Class"); assert(classClass != NULL); - jclass loaderClass = env->FindClass("org/apache/tuscany/ClassLoader"); + const jclass loaderClass = env->FindClass("org/apache/tuscany/ClassLoader"); assert(loaderClass != NULL); return true; } diff --git a/sca-cpp/trunk/modules/java/mod-java.cpp b/sca-cpp/trunk/modules/java/mod-java.cpp index d96861cc6d..61711db9f4 100644 --- a/sca-cpp/trunk/modules/java/mod-java.cpp +++ b/sca-cpp/trunk/modules/java/mod-java.cpp @@ -40,32 +40,25 @@ namespace modeval { /** * Apply a lifecycle start or restart event. */ -struct javaLifecycle { - javaLifecycle(java::JavaRuntime& jr) : jr(jr) { - } - const value operator()(const list<value>& params) const { - const value func = car(params); - if (func == "javaRuntime") - return (gc_ptr<value>)(value*)(void*)&jr; - return lambda<value(const list<value>&)>(); - } - java::JavaRuntime& jr; -}; - const value applyLifecycle(unused const list<value>& params) { // Create a Java runtime - java::JavaRuntime& jr = *(new (gc_new<java::JavaRuntime>()) java::JavaRuntime()); + const java::JavaRuntime& jr = *(new (gc_new<java::JavaRuntime>()) java::JavaRuntime()); // Return the function to invoke on subsequent events - return failable<value>(lambda<value(const list<value>&)>(javaLifecycle(jr))); + return failable<value>(lvvlambda([&jr](const list<value>& params) -> const value { + const value func = car(params); + if (func == "javaRuntime") + return (gc_ptr<value>)(value*)(void*)&jr; + return lvvlambda(); + })); } /** * Evaluate a Java component implementation and convert it to an applicable * lambda function. */ -const failable<lambda<value(const list<value>&)> > evalImplementation(const string& path, const value& impl, const list<value>& px, const lambda<value(const list<value>&)>& lifecycle) { +const failable<lvvlambda > evalImplementation(const string& path, const value& impl, const list<value>& px, const lvvlambda& lifecycle) { const string itype(elementName(impl)); if (contains(itype, ".java")) { const void* p = (gc_ptr<value>)lifecycle(mklist<value>("javaRuntime")); @@ -74,8 +67,8 @@ const failable<lambda<value(const list<value>&)> > evalImplementation(const stri if (contains(itype, ".cpp")) return modcpp::evalImplementation(path, impl, px); if (contains(itype, ".widget")) - return mkfailure<lambda<value(const list<value>&)> >(string("Unsupported implementation type: ") + itype, -1, false); - return mkfailure<lambda<value(const list<value>&)> >(string("Unsupported implementation type: ") + itype); + return mkfailure<lvvlambda >(string("Unsupported implementation type: ") + itype, -1, false); + return mkfailure<lvvlambda >(string("Unsupported implementation type: ") + itype); } } diff --git a/sca-cpp/trunk/modules/java/mod-java.hpp b/sca-cpp/trunk/modules/java/mod-java.hpp index b68f17aa3f..4dd2fe33a2 100644 --- a/sca-cpp/trunk/modules/java/mod-java.hpp +++ b/sca-cpp/trunk/modules/java/mod-java.hpp @@ -40,34 +40,26 @@ namespace server { namespace modjava { /** - * Apply a Java component implementation function. - */ -struct applyImplementation { - java::JavaClass impl; - const list<value> px; - java::JavaRuntime& jr; - applyImplementation(const java::JavaClass& impl, const list<value>& px, java::JavaRuntime& jr) : impl(impl), px(px), jr(jr) { - } - const value operator()(const list<value>& params) const { - const value expr = append<value>(params, px); - debug(expr, "modeval::java::applyImplementation::input"); - const failable<value> res = java::evalClass(jr, expr, impl); - const value val = !hasContent(res)? mklist<value>(value(), reason(res), rcode(res)) : mklist<value>(content(res)); - debug(val, "modeval::java::applyImplementation::result"); - return val; - } -}; - -/** * Evaluate a Java component implementation and convert it to an applicable * lambda function. */ -const failable<lambda<value(const list<value>&)> > evalImplementation(const string& path, const value& impl, const list<value>& px, java::JavaRuntime& jr) { +const failable<lvvlambda > evalImplementation(const string& path, const value& impl, const list<value>& px, const java::JavaRuntime& jr) { const string cn(attributeValue("class", impl)); - const failable<java::JavaClass> jc = java::readClass(jr, path, cn); - if (!hasContent(jc)) - return mkfailure<lambda<value(const list<value>&)> >(jc); - return lambda<value(const list<value>&)>(applyImplementation(content(jc), px, jr)); + const failable<java::JavaClass> fjc = java::readClass(jr, path, cn); + if (!hasContent(fjc)) + return mkfailure<lvvlambda >(fjc); + + // Return Java component implementation lambda function + const java::JavaClass jc = content(fjc); + const lvvlambda applyImplementation = [jc, px, jr](const list<value>& params) -> const value { + const value expr = append<value>(params, px); + debug(expr, "modeval::java::applyImplementation::expr"); + const failable<value> res = java::evalClass(jr, expr, jc); + const value val = !hasContent(res)? mklist<value>(nilValue, reason(res), rcode(res)) : mklist<value>(content(res)); + debug(val, "modeval::java::applyImplementation::result"); + return val; + }; + return applyImplementation; } } diff --git a/sca-cpp/trunk/modules/oauth/Makefile.am b/sca-cpp/trunk/modules/oauth/Makefile.am index 9e8eb5a0dd..d72a584f49 100644 --- a/sca-cpp/trunk/modules/oauth/Makefile.am +++ b/sca-cpp/trunk/modules/oauth/Makefile.am @@ -26,12 +26,12 @@ mod_LTLIBRARIES = libmod_tuscany_oauth1.la libmod_tuscany_oauth2.la noinst_DATA = libmod_tuscany_oauth1${libsuffix} libmod_tuscany_oauth2${libsuffix} libmod_tuscany_oauth1_la_SOURCES = mod-oauth1.cpp -libmod_tuscany_oauth1_la_LDFLAGS = -L${LIBOAUTH_LIB} -R${LIBOAUTH_LIB} -loauth -lxml2 -lcurl -lmozjs +libmod_tuscany_oauth1_la_LDFLAGS = -L${LIBOAUTH_LIB} -R${LIBOAUTH_LIB} -loauth -lxml2 -lcurl -ljansson libmod_tuscany_oauth1${libsuffix}: ln -s .libs/libmod_tuscany_oauth1${libsuffix} libmod_tuscany_oauth2_la_SOURCES = mod-oauth2.cpp -libmod_tuscany_oauth2_la_LDFLAGS = -lxml2 -lcurl -lmozjs +libmod_tuscany_oauth2_la_LDFLAGS = -lxml2 -lcurl -ljansson libmod_tuscany_oauth2${libsuffix}: ln -s .libs/libmod_tuscany_oauth2${libsuffix} diff --git a/sca-cpp/trunk/modules/oauth/mod-oauth1.cpp b/sca-cpp/trunk/modules/oauth/mod-oauth1.cpp index d2c7cf7ddd..c9d8607144 100644 --- a/sca-cpp/trunk/modules/oauth/mod-oauth1.cpp +++ b/sca-cpp/trunk/modules/oauth/mod-oauth1.cpp @@ -56,18 +56,18 @@ namespace oauth1 { */ class ServerConf { public: - ServerConf(apr_pool_t* p, server_rec* s) : p(p), server(s) { + ServerConf(apr_pool_t* const p, server_rec* const s) : p(p), server(s) { } const gc_pool p; - server_rec* server; - string ca; - string cert; - string key; - list<list<value> > appkeys; - list<string> mcaddrs; - memcache::MemCached mc; - perthread_ptr<http::CURLSession> cs; + server_rec* const server; + gc_mutable_ref<string> ca; + gc_mutable_ref<string> cert; + gc_mutable_ref<string> key; + gc_mutable_ref<list<list<value> > > appkeys; + gc_mutable_ref<list<string> > mcaddrs; + gc_mutable_ref<memcache::MemCached> mc; + gc_mutable_ref<perthread_ptr<http::CURLSession> > cs; }; /** @@ -80,7 +80,7 @@ public: AuthnProviderConf(const string name, const authn_provider* provider) : name(name), provider(provider) { } - string name; + const string name; const authn_provider* provider; }; @@ -89,21 +89,21 @@ public: */ class DirConf { public: - DirConf(apr_pool_t* p, char* d) : p(p), dir(d), enabled(false), login("") { + DirConf(apr_pool_t* const p, const char* const d) : p(p), dir(d), enabled(false), login(emptyString) { } const gc_pool p; - const char* dir; + const char* const dir; bool enabled; - string login; - list<list<value> > scopeattrs; - list<AuthnProviderConf> apcs; + gc_mutable_ref<string> login; + gc_mutable_ref<list<list<value> > > scopeattrs; + gc_mutable_ref<list<AuthnProviderConf> > apcs; }; /** * Run the authnz hooks to authenticate a request. */ -const failable<int> checkAuthnzProviders(const string& user, request_rec* r, const list<AuthnProviderConf>& apcs) { +const failable<int> checkAuthnzProviders(const string& user, request_rec* const r, const list<AuthnProviderConf>& apcs) { if (isNil(apcs)) return mkfailure<int>("Authentication failure for: " + user, HTTP_UNAUTHORIZED); const AuthnProviderConf apc = car<AuthnProviderConf>(apcs); @@ -118,7 +118,7 @@ const failable<int> checkAuthnzProviders(const string& user, request_rec* r, con return OK; } -const failable<int> checkAuthnz(const string& user, request_rec* r, const list<AuthnProviderConf>& apcs) { +const failable<int> checkAuthnz(const string& user, request_rec* const r, const list<AuthnProviderConf>& apcs) { if (substr(user, 0, 1) == "/") return mkfailure<int>(string("Encountered FakeBasicAuth spoof: ") + user, HTTP_UNAUTHORIZED); @@ -139,7 +139,7 @@ const failable<value> userInfo(const value& sid, const memcache::MemCached& mc) /** * Handle an authenticated request. */ -const failable<int> authenticated(const list<list<value> >& userinfo, const bool check, request_rec* r, const list<list<value> >& scopeattrs, const list<AuthnProviderConf>& apcs) { +const failable<int> authenticated(const list<list<value> >& userinfo, const bool check, request_rec* const r, const list<list<value> >& scopeattrs, const list<AuthnProviderConf>& apcs) { debug(userinfo, "modoauth2::authenticated::userinfo"); if (isNil(scopeattrs)) { @@ -147,7 +147,7 @@ const failable<int> authenticated(const list<list<value> >& userinfo, const bool // Store user id in an environment variable const list<value> id = assoc<value>("id", userinfo); if (isNil(id) || isNil(cdr(id))) - return mkfailure<int>("Couldn't retrieve user id"); + return mkfailure<int>("Couldn't retrieve user id", HTTP_UNAUTHORIZED); apr_table_set(r->subprocess_env, "OAUTH2_ID", apr_pstrdup(r->pool, c_str(cadr(id)))); // If the request user field has not been mapped to another attribute, map the @@ -157,7 +157,7 @@ const failable<int> authenticated(const list<list<value> >& userinfo, const bool // Run the authnz hooks to check the authenticated user if (check) - return checkAuthnz(r->user == NULL? "" : r->user, r, apcs); + return checkAuthnz(r->user == NULL? emptyString : r->user, r, apcs); return OK; } @@ -210,7 +210,7 @@ const string header(const string& qs, const string& redir, const string& verif) */ const list<string> sign(const string& verb, const string& uri, const list<value> appkey, const string& tok, const string& sec) { char* qs = NULL; - char* suri = oauth_sign_url2(c_str(uri), &qs, OA_HMAC, c_str(verb), c_str(car(appkey)), c_str(cadr(appkey)), length(tok) != 0? c_str(tok) : NULL, length(sec) != 0? c_str(sec) : NULL); + char* const suri = oauth_sign_url2(c_str(uri), &qs, OA_HMAC, c_str(verb), c_str(car(appkey)), c_str(cadr(appkey)), length(tok) != 0? c_str(tok) : NULL, length(sec) != 0? c_str(sec) : NULL); const list<string> res = mklist<string>(suri, qs); free(suri); free(qs); @@ -220,7 +220,7 @@ const list<string> sign(const string& verb, const string& uri, const list<value> /** * Handle an authorize request. */ -const failable<int> authorize(const list<list<value> >& args, request_rec* r, const list<list<value> >& appkeys, const memcache::MemCached& mc) { +const failable<int> authorize(const list<list<value> >& args, request_rec* const r, const list<list<value> >& appkeys, const memcache::MemCached& mc) { // Extract authorize, access_token, client ID and info URIs const list<value> ref = assoc<value>("openauth_referrer", args); if (isNil(ref) || isNil(cdr(ref))) @@ -249,19 +249,19 @@ const failable<int> authorize(const list<list<value> >& args, request_rec* r, co // Lookup client app configuration const list<value> app = assoc<value>(cadr(cid), appkeys); if (isNil(app) || isNil(cdr(app))) - return mkfailure<int>(string("client id not found: ") + cadr(cid)); + return mkfailure<int>(string("client id not found: ") + (string)cadr(cid)); list<value> appkey = cadr(app); // Build and sign the request token URI const string requri = httpd::unescape(cadr(req)) + string("&") + http::queryString(mklist<list<value> >(mklist<value>("oauth_callback", httpd::escape(redir)))); - const list<string> srequri = sign("POST", requri, appkey, "", ""); + const list<string> srequri = sign("POST", requri, appkey, emptyString, emptyString); debug(srequri, "modoauth1::authorize::srequri"); // Put the args into an oauth header - const string reqhdr = header(cadr(srequri), redir, ""); + const string reqhdr = header(cadr(srequri), redir, emptyString); // Send the request token request - char* pres = oauth_http_post2(c_str(car(srequri)), "", c_str(reqhdr)); + char* const pres = oauth_http_post2(c_str(car(srequri)), "", c_str(reqhdr)); if (pres == NULL) return mkfailure<int>("Couldn't send request token request"); const string res(pres); @@ -297,11 +297,10 @@ const failable<int> authorize(const list<list<value> >& args, request_rec* r, co * User profile parsing needs to be made configurable. */ const failable<list<value> > profileUserInfo(const value& cid, const string& info) { - string b = substr(info, 0, 1); + const string b = substr(info, 0, 1); if (b == "[") { // Twitter JSON profile - js::JSContext cx; - const list<value> infov(json::jsonValues(content(json::readJSON(mklist<string>(info), cx)))); + const list<value> infov(content(json::readValue(mklist<string>(info)))); if (isNil(infov)) return mkfailure<list<value> >("Couldn't retrieve user info"); debug(infov, "modoauth1::access_token::info"); @@ -314,8 +313,7 @@ const failable<list<value> > profileUserInfo(const value& cid, const string& inf } if (b == "{") { // Foursquare JSON profile - js::JSContext cx; - const list<value> infov(json::jsonValues(content(json::readJSON(mklist<string>(info), cx)))); + const list<value> infov(content(json::readValue(mklist<string>(info)))); if (isNil(infov)) return mkfailure<list<value> >("Couldn't retrieve user info"); debug(infov, "modoauth1::access_token::info"); @@ -328,7 +326,7 @@ const failable<list<value> > profileUserInfo(const value& cid, const string& inf } if (b == "<") { // XML profile - const list<value> infov = elementsToValues(readXML(mklist<string>(info))); + const list<value> infov = elementsToValues(content(xml::readElements(mklist<string>(info)))); if (isNil(infov)) return mkfailure<list<value> >("Couldn't retrieve user info"); debug(infov, "modoauth1::access_token::info"); @@ -370,8 +368,8 @@ const failable<int> accessToken(const list<list<value> >& args, request_rec* r, // Lookup client app configuration const list<value> app = assoc<value>(cadr(cid), appkeys); if (isNil(app) || isNil(cdr(app))) - return mkfailure<int>(string("client id not found: ") + cadr(cid)); - list<value> appkey = cadr(app); + return mkfailure<int>(string("client id not found: ") + (string)cadr(cid)); + const list<value> appkey = cadr(app); // Retrieve the request token from memcached const failable<value> sv = memcache::get(mklist<value>("tuscanyOAuth1Token", cadr(tv)), mc); @@ -384,10 +382,10 @@ const failable<int> accessToken(const list<list<value> >& args, request_rec* r, debug(stokuri, "modoauth1::access_token::stokuri"); // Put the args into an oauth header - string tokhdr = header(cadr(stokuri), "", cadr(vv)); + string tokhdr = header(cadr(stokuri), emptyString, cadr(vv)); // Send the access token request - char* ptokres = oauth_http_post2(c_str(car(stokuri)), "", c_str(tokhdr)); + char* const ptokres = oauth_http_post2(c_str(car(stokuri)), "", c_str(tokhdr)); if (ptokres == NULL) return mkfailure<int>("Couldn't post access_token request"); const string tokres(ptokres); @@ -410,10 +408,10 @@ const failable<int> accessToken(const list<list<value> >& args, request_rec* r, debug(sprofuri, "modoauth1::access_token::sprofuri"); // Put the args into an oauth header - string profhdr = header(cadr(sprofuri), "", ""); + const string profhdr = header(cadr(sprofuri), emptyString, emptyString); // Send the user profile request - char* pprofres = oauth_http_get2(c_str(car(sprofuri)), NULL, c_str(profhdr)); + char* const pprofres = oauth_http_get2(c_str(car(sprofuri)), NULL, c_str(profhdr)); if (pprofres == NULL) return mkfailure<int>("Couldn't get user info"); const string profres(pprofres); @@ -431,7 +429,7 @@ const failable<int> accessToken(const list<list<value> >& args, request_rec* r, return authrc; // Store user info in memcached keyed by session ID - const value sid = string("OAuth1_") + mkrand(); + const value sid = string("OAuth1_") + (string)mkrand(); const failable<bool> prc = memcache::put(mklist<value>("tuscanyOAuth1", sid), content(userinfo), mc); if (!hasContent(prc)) return mkfailure<int>(prc); @@ -446,17 +444,17 @@ const failable<int> accessToken(const list<list<value> >& args, request_rec* r, * Check user authentication. */ static int checkAuthn(request_rec *r) { - gc_scoped_pool pool(r->pool); + const gc_scoped_pool sp(r->pool); // Decline if we're not enabled or AuthType is not set to Open const DirConf& dc = httpd::dirConf<DirConf>(r, &mod_tuscany_oauth1); if (!dc.enabled) return DECLINED; - const char* atype = ap_auth_type(r); + const char* const atype = ap_auth_type(r); if (atype == NULL || strcasecmp(atype, "Open")) return DECLINED; debug_httpdRequest(r, "modoauth1::checkAuthn::input"); - debug(atype, "modopenauth::checkAuthn::auth_type"); + debug(atype, "modoauth1::checkAuthn::auth_type"); // Get the server configuration const ServerConf& sc = httpd::serverConf<ServerConf>(r, &mod_tuscany_oauth1); @@ -471,9 +469,9 @@ static int checkAuthn(request_rec *r) { // Extract the user info from the auth session const failable<value> userinfo = userInfo(content(sid), sc.mc); if (!hasContent(userinfo)) - return httpd::reportStatus(mkfailure<int>(userinfo)); + return openauth::reportStatus(mkfailure<int>(reason(userinfo), HTTP_UNAUTHORIZED), dc.login, nilValue, r); r->ap_auth_type = const_cast<char*>(atype); - return httpd::reportStatus(authenticated(content(userinfo), false, r, dc.scopeattrs, dc.apcs)); + return openauth::reportStatus(authenticated(content(userinfo), false, r, dc.scopeattrs, dc.apcs), dc.login, nilValue, r); } // Get the request args @@ -482,19 +480,14 @@ static int checkAuthn(request_rec *r) { // Handle OAuth authorize request step if (string(r->uri) == "/oauth1/authorize/") { r->ap_auth_type = const_cast<char*>(atype); - return httpd::reportStatus(authorize(args, r, sc.appkeys, sc.mc)); + return openauth::reportStatus(authorize(args, r, sc.appkeys, sc.mc), dc.login, 1, r); } // Handle OAuth access_token request step if (string(r->uri) == "/oauth1/access_token/") { r->ap_auth_type = const_cast<char*>(atype); const failable<int> authrc = accessToken(args, r, sc.appkeys, dc.scopeattrs, dc.apcs, sc.mc); - - // Redirect to the login page if user is not authorized - if (!hasContent(authrc) && rcode(authrc) == HTTP_UNAUTHORIZED) - return httpd::reportStatus(openauth::login(dc.login, string("/"), 1, r)); - - return httpd::reportStatus(authrc); + return openauth::reportStatus(authrc, dc.login, 1, r); } // Redirect to the login page, unless we have a session id or an authorization @@ -509,22 +502,22 @@ static int checkAuthn(request_rec *r) { return DECLINED; r->ap_auth_type = const_cast<char*>(atype); - return httpd::reportStatus(openauth::login(dc.login, value(), value(), r)); + return httpd::reportStatus(openauth::login(dc.login, nilValue, nilValue, r)); } /** * Process the module configuration. */ -int postConfigMerge(ServerConf& mainsc, server_rec* s) { +int postConfigMerge(const ServerConf& mainsc, server_rec* const s) { if (s == NULL) return OK; ServerConf& sc = httpd::serverConf<ServerConf>(s, &mod_tuscany_oauth1); debug(httpd::serverName(s), "modoauth1::postConfigMerge::serverName"); // Merge configuration from main server - if (isNil(sc.appkeys)) + if (isNil((list<list<value> >)sc.appkeys)) sc.appkeys = mainsc.appkeys; - if (isNil(sc.mcaddrs)) + if (isNil((list<string>)sc.mcaddrs)) sc.mcaddrs = mainsc.mcaddrs; sc.mc = mainsc.mc; sc.cs = mainsc.cs; @@ -532,10 +525,10 @@ int postConfigMerge(ServerConf& mainsc, server_rec* s) { return postConfigMerge(mainsc, 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); +int postConfig(apr_pool_t* const p, unused apr_pool_t* const plog, unused apr_pool_t* const ptemp, server_rec* const s) { + const gc_scoped_pool sp(p); - ServerConf& sc = httpd::serverConf<ServerConf>(s, &mod_tuscany_oauth1); + const ServerConf& sc = httpd::serverConf<ServerConf>(s, &mod_tuscany_oauth1); debug(httpd::serverName(s), "modoauth1::postConfig::serverName"); // Merge server configurations @@ -543,30 +536,12 @@ int postConfig(apr_pool_t* p, unused apr_pool_t* plog, unused apr_pool_t* ptemp, } /** - * Lambda function that creates a new CURL session. - */ -class newsession { -public: - newsession(const string& ca, const string& cert, const string& key) : ca(ca), cert(cert), key(key) { - } - - const gc_ptr<http::CURLSession> operator()() const { - return new (gc_new<http::CURLSession>()) http::CURLSession(ca, cert, key, "", 0); - } - -private: - const string ca; - const string cert; - const string key; -}; - -/** * Child process initialization. */ -void childInit(apr_pool_t* p, server_rec* s) { - gc_scoped_pool pool(p); +void childInit(apr_pool_t* const p, server_rec* const s) { + const gc_scoped_pool sp(p); - ServerConf* psc = (ServerConf*)ap_get_module_config(s->module_config, &mod_tuscany_oauth1); + ServerConf* const psc = (ServerConf*)ap_get_module_config(s->module_config, &mod_tuscany_oauth1); if(psc == NULL) { cfailure << "[Tuscany] Due to one or more errors mod_tuscany_oauth1 loading failed. Causing apache to stop loading." << endl; exit(APEXIT_CHILDFATAL); @@ -574,13 +549,21 @@ void childInit(apr_pool_t* p, server_rec* s) { ServerConf& sc = *psc; // Connect to Memcached - if (isNil(sc.mcaddrs)) + if (isNil((list<string>)sc.mcaddrs)) sc.mc = *(new (gc_new<memcache::MemCached>()) memcache::MemCached("localhost", 11211)); else sc.mc = *(new (gc_new<memcache::MemCached>()) memcache::MemCached(sc.mcaddrs)); // Setup a CURL session - sc.cs = perthread_ptr<http::CURLSession>(lambda<gc_ptr<http::CURLSession>()>(newsession(sc.ca, sc.cert, sc.key))); + const string ca(sc.ca); + const string cert(sc.cert); + const string key(sc.key); + const gc_pool cp(gc_current_pool()); + const lambda<const gc_ptr<http::CURLSession>()> newsession = [ca, cert, key, cp]() -> const gc_ptr<http::CURLSession> { + const gc_scoped_pool sp(pool(cp)); + return new (gc_new<http::CURLSession>()) http::CURLSession(ca, cert, key, emptyString, 0); + }; + sc.cs = *(new (gc_new<perthread_ptr<http::CURLSession> >()) perthread_ptr<http::CURLSession>(newsession)); // Merge the updated configuration into the virtual hosts postConfigMerge(sc, s->next); @@ -589,56 +572,56 @@ void childInit(apr_pool_t* p, server_rec* s) { /** * Configuration commands. */ -const char* confAppKey(cmd_parms *cmd, unused void *c, const char *arg1, const char* arg2, const char* arg3) { - gc_scoped_pool pool(cmd->pool); +char* const confAppKey(cmd_parms* cmd, unused void *c, char *arg1, char* arg2, char* arg3) { + const gc_scoped_pool sp(cmd->pool); ServerConf& sc = httpd::serverConf<ServerConf>(cmd, &mod_tuscany_oauth1); - sc.appkeys = cons<list<value> >(mklist<value>(arg1, mklist<value>(arg2, arg3)), sc.appkeys); + sc.appkeys = cons<list<value> >(mklist<value>(arg1, mklist<value>(arg2, arg3)), (list<list<value> >)sc.appkeys); return NULL; } -const char* confMemcached(cmd_parms *cmd, unused void *c, const char *arg) { - gc_scoped_pool pool(cmd->pool); +char* confMemcached(cmd_parms *cmd, unused void *c, char *arg) { + const gc_scoped_pool sp(cmd->pool); ServerConf& sc = httpd::serverConf<ServerConf>(cmd, &mod_tuscany_oauth1); - sc.mcaddrs = cons<string>(arg, sc.mcaddrs); + sc.mcaddrs = cons<string>(arg, (list<string>)sc.mcaddrs); return NULL; } -const char* confEnabled(cmd_parms *cmd, void *c, const int arg) { - gc_scoped_pool pool(cmd->pool); +char* confEnabled(cmd_parms *cmd, void *c, int arg) { + const gc_scoped_pool sp(cmd->pool); DirConf& dc = httpd::dirConf<DirConf>(c); dc.enabled = (bool)arg; return NULL; } -const char* confLogin(cmd_parms *cmd, void *c, const char* arg) { - gc_scoped_pool pool(cmd->pool); +char* confLogin(cmd_parms *cmd, void *c, char* arg) { + const gc_scoped_pool sp(cmd->pool); DirConf& dc = httpd::dirConf<DirConf>(c); dc.login = arg; return NULL; } -const char* confCAFile(cmd_parms *cmd, unused void *c, const char *arg) { - gc_scoped_pool pool(cmd->pool); +char* confCAFile(cmd_parms *cmd, unused void *c, char *arg) { + const gc_scoped_pool sp(cmd->pool); ServerConf& sc = httpd::serverConf<ServerConf>(cmd, &mod_tuscany_oauth1); sc.ca = arg; return NULL; } -const char* confCertFile(cmd_parms *cmd, unused void *c, const char *arg) { - gc_scoped_pool pool(cmd->pool); +char* confCertFile(cmd_parms *cmd, unused void *c, char *arg) { + const gc_scoped_pool sp(cmd->pool); ServerConf& sc = httpd::serverConf<ServerConf>(cmd, &mod_tuscany_oauth1); sc.cert = arg; return NULL; } -const char* confCertKeyFile(cmd_parms *cmd, unused void *c, const char *arg) { - gc_scoped_pool pool(cmd->pool); +char* confCertKeyFile(cmd_parms *cmd, unused void *c, char *arg) { + const gc_scoped_pool sp(cmd->pool); ServerConf& sc = httpd::serverConf<ServerConf>(cmd, &mod_tuscany_oauth1); sc.key = arg; return NULL; } -const char* confScopeAttr(cmd_parms *cmd, void* c, const char* arg1, const char* arg2) { - gc_scoped_pool pool(cmd->pool); +char* confScopeAttr(cmd_parms *cmd, void* c, char* arg1, char* arg2) { + const gc_scoped_pool sp(cmd->pool); DirConf& dc = httpd::dirConf<DirConf>(c); - dc.scopeattrs = cons<list<value> >(mklist<value>(arg1, arg2), dc.scopeattrs); + dc.scopeattrs = cons<list<value> >(mklist<value>(arg1, arg2), (list<list<value> >)dc.scopeattrs); return NULL; } -const char* confAuthnProvider(cmd_parms *cmd, void *c, const char* arg) { - gc_scoped_pool pool(cmd->pool); +char* confAuthnProvider(cmd_parms *cmd, void *c, char* arg) { + const gc_scoped_pool sp(cmd->pool); DirConf& dc = httpd::dirConf<DirConf>(c); // Lookup and cache the Authn provider diff --git a/sca-cpp/trunk/modules/oauth/mod-oauth2.cpp b/sca-cpp/trunk/modules/oauth/mod-oauth2.cpp index e384a0e742..bedf83325f 100644 --- a/sca-cpp/trunk/modules/oauth/mod-oauth2.cpp +++ b/sca-cpp/trunk/modules/oauth/mod-oauth2.cpp @@ -50,18 +50,18 @@ namespace oauth2 { */ class ServerConf { public: - ServerConf(apr_pool_t* p, server_rec* s) : p(p), server(s) { + ServerConf(apr_pool_t* const p, server_rec* const s) : p(p), server(s) { } const gc_pool p; - server_rec* server; - string ca; - string cert; - string key; - list<list<value> > appkeys; - list<string> mcaddrs; - memcache::MemCached mc; - perthread_ptr<http::CURLSession> cs; + server_rec* const server; + gc_mutable_ref<string> ca; + gc_mutable_ref<string> cert; + gc_mutable_ref<string> key; + gc_mutable_ref<list<list<value> > > appkeys; + gc_mutable_ref<list<string> > mcaddrs; + gc_mutable_ref<memcache::MemCached> mc; + gc_mutable_ref<perthread_ptr<http::CURLSession> > cs; }; /** @@ -74,7 +74,7 @@ public: AuthnProviderConf(const string name, const authn_provider* provider) : name(name), provider(provider) { } - string name; + const string name; const authn_provider* provider; }; @@ -83,21 +83,21 @@ public: */ class DirConf { public: - DirConf(apr_pool_t* p, char* d) : p(p), dir(d), enabled(false), login("") { + DirConf(apr_pool_t* const p, const char* const d) : p(p), dir(d), enabled(false), login(emptyString) { } const gc_pool p; - const char* dir; + const char* const dir; bool enabled; - string login; - list<list<value> > scopeattrs; - list<AuthnProviderConf> apcs; + gc_mutable_ref<string> login; + gc_mutable_ref<list<list<value> > > scopeattrs; + gc_mutable_ref<list<AuthnProviderConf> > apcs; }; /** * Run the authnz hooks to authenticate a request. */ -const failable<int> checkAuthnzProviders(const string& user, request_rec* r, const list<AuthnProviderConf>& apcs) { +const failable<int> checkAuthnzProviders(const string& user, request_rec* const r, const list<AuthnProviderConf>& apcs) { if (isNil(apcs)) return mkfailure<int>("Authentication failure for: " + user, HTTP_UNAUTHORIZED); const AuthnProviderConf apc = car<AuthnProviderConf>(apcs); @@ -112,7 +112,7 @@ const failable<int> checkAuthnzProviders(const string& user, request_rec* r, con return OK; } -const failable<int> checkAuthnz(const string& user, request_rec* r, const list<AuthnProviderConf>& apcs) { +const failable<int> checkAuthnz(const string& user, request_rec* const r, const list<AuthnProviderConf>& apcs) { if (substr(user, 0, 1) == "/") return mkfailure<int>(string("Encountered FakeBasicAuth spoof: ") + user, HTTP_UNAUTHORIZED); @@ -133,7 +133,7 @@ const failable<value> userInfo(const value& sid, const memcache::MemCached& mc) /** * Handle an authenticated request. */ -const failable<int> authenticated(const list<list<value> >& userinfo, const bool check, request_rec* r, const list<list<value> >& scopeattrs, const list<AuthnProviderConf>& apcs) { +const failable<int> authenticated(const list<list<value> >& userinfo, const bool check, request_rec* const r, const list<list<value> >& scopeattrs, const list<AuthnProviderConf>& apcs) { debug(userinfo, "modoauth2::authenticated::userinfo"); if (isNil(scopeattrs)) { @@ -141,7 +141,7 @@ const failable<int> authenticated(const list<list<value> >& userinfo, const bool // Store user id in an environment variable const list<value> id = assoc<value>("id", userinfo); if (isNil(id) || isNil(cdr(id))) - return mkfailure<int>("Couldn't retrieve user id"); + return mkfailure<int>("Couldn't retrieve user id", HTTP_UNAUTHORIZED); apr_table_set(r->subprocess_env, "OAUTH2_ID", apr_pstrdup(r->pool, c_str(cadr(id)))); // If the request user field has not been mapped to another attribute, map the @@ -151,7 +151,7 @@ const failable<int> authenticated(const list<list<value> >& userinfo, const bool // Run the authnz hooks to check the authenticated user if (check) - return checkAuthnz(r->user == NULL? "" : r->user, r, apcs); + return checkAuthnz(r->user == NULL? emptyString : r->user, r, apcs); return OK; } @@ -172,7 +172,7 @@ const failable<int> authenticated(const list<list<value> >& userinfo, const bool /** * Handle an authorize request. */ -const failable<int> authorize(const list<list<value> >& args, request_rec* r, const list<list<value> >& appkeys) { +const failable<int> authorize(const list<list<value> >& args, request_rec* const r, const list<list<value> >& appkeys) { // Extract authorize, access_token, client ID and info URIs const list<value> ref = assoc<value>("openauth_referrer", args); if (isNil(ref) || isNil(cdr(ref))) @@ -206,11 +206,11 @@ const failable<int> authorize(const list<list<value> >& args, request_rec* r, co // Lookup client app configuration const list<value> app = assoc<value>(cadr(cid), appkeys); if (isNil(app) || isNil(cdr(app))) - return mkfailure<int>(string("client id not found: ") + cadr(cid)); + return mkfailure<int>(string("client id not found: ") + (string)cadr(cid)); list<value> appkey = cadr(app); // Redirect to the authorize URI - const list<value> adisplay = (isNil(display) || isNil(cdr(display)))? list<value>() : mklist<value>("display", cadr(display)); + const list<value> adisplay = (isNil(display) || isNil(cdr(display)))? nilListValue : mklist<value>("display", cadr(display)); const list<list<value> > aargs = mklist<list<value> >(mklist<value>("response_type", "code"), mklist<value>("client_id", car(appkey)), mklist<value>("scope", cadr(scope)), adisplay, mklist<value>("redirect_uri", httpd::escape(redir)), mklist<value>("state", httpd::escape(state))); const string uri = httpd::unescape(cadr(auth)) + string("?") + http::queryString(aargs); debug(uri, "modoauth2::authorize::uri"); @@ -229,7 +229,7 @@ const failable<list<value> > profileUserInfo(const value& cid, const list<value> /** * Handle an access_token request. */ -const failable<int> accessToken(const list<list<value> >& args, request_rec* r, const list<list<value> >& appkeys, const perthread_ptr<http::CURLSession>& cs, const list<list<value> >& scopeattrs, const list<AuthnProviderConf>& apcs, const memcache::MemCached& mc) { +const failable<int> accessToken(const list<list<value> >& args, request_rec* r, const list<list<value> >& appkeys, const http::CURLSession& cs, const list<list<value> >& scopeattrs, const list<AuthnProviderConf>& apcs, const memcache::MemCached& mc) { // Extract access_token URI, client ID and authorization code parameters const list<value> state = assoc<value>("state", args); @@ -255,7 +255,7 @@ const failable<int> accessToken(const list<list<value> >& args, request_rec* r, // Lookup client app configuration const list<value> app = assoc<value>(cadr(cid), appkeys); if (isNil(app) || isNil(cdr(app))) - return mkfailure<int>(string("client id not found: ") + cadr(cid)); + return mkfailure<int>(string("client id not found: ") + (string)cadr(cid)); list<value> appkey = cadr(app); // Build the redirect URI @@ -269,7 +269,7 @@ const failable<int> accessToken(const list<list<value> >& args, request_rec* r, const string turi = httpd::unescape(cadr(tok)); debug(turi, "modoauth2::access_token::tokenuri"); const value tval = mklist<value>(string("application/x-www-form-urlencoded;charset=UTF-8"), mklist<value>(tqs)); - const failable<value> ftr = http::post(tval, turi, *(cs)); + const failable<value> ftr = http::post(tval, turi, cs); if (!hasContent(ftr)) return mkfailure<int>(ftr); const value tr = content(ftr); @@ -288,7 +288,7 @@ const failable<int> accessToken(const list<list<value> >& args, request_rec* r, const list<list<value> > iargs = mklist<list<value> >(tv); const string iuri = httpd::unescape(cadr(info)) + string("?") + http::queryString(iargs); debug(iuri, "modoauth2::access_token::infouri"); - const failable<value> profres = http::get(iuri, *(cs)); + const failable<value> profres = http::get(iuri, cs); if (!hasContent(profres)) return mkfailure<int>("Couldn't retrieve user info"); debug(content(profres), "modoauth2::access_token::info"); @@ -304,7 +304,7 @@ const failable<int> accessToken(const list<list<value> >& args, request_rec* r, return authrc; // Store user info in memcached keyed by a session ID - const value sid = string("OAuth2_") + mkrand(); + const value sid = string("OAuth2_") + (string)mkrand(); const failable<bool> prc = memcache::put(mklist<value>("tuscanyOAuth2", sid), content(userinfo), mc); if (!hasContent(prc)) return mkfailure<int>(prc); @@ -319,7 +319,7 @@ const failable<int> accessToken(const list<list<value> >& args, request_rec* r, * Check user authentication. */ static int checkAuthn(request_rec *r) { - gc_scoped_pool pool(r->pool); + const gc_scoped_pool sp(r->pool); // Decline if we're not enabled or AuthType is not set to Open const DirConf& dc = httpd::dirConf<DirConf>(r, &mod_tuscany_oauth2); @@ -329,7 +329,7 @@ static int checkAuthn(request_rec *r) { if (atype == NULL || strcasecmp(atype, "Open")) return DECLINED; debug_httpdRequest(r, "modoauth2::checkAuthn::input"); - debug(atype, "modopenauth::checkAuthn::auth_type"); + debug(atype, "modoauth2::checkAuthn::auth_type"); // Get the server configuration const ServerConf& sc = httpd::serverConf<ServerConf>(r, &mod_tuscany_oauth2); @@ -344,9 +344,9 @@ static int checkAuthn(request_rec *r) { // Extract the user info from the auth session const failable<value> userinfo = userInfo(content(sid), sc.mc); if (!hasContent(userinfo)) - return httpd::reportStatus(mkfailure<int>(userinfo)); + return openauth::reportStatus(mkfailure<int>(reason(userinfo), HTTP_UNAUTHORIZED), dc.login, nilValue, r); r->ap_auth_type = const_cast<char*>(atype); - return httpd::reportStatus(authenticated(content(userinfo), false, r, dc.scopeattrs, dc.apcs)); + return openauth::reportStatus(authenticated(content(userinfo), false, r, dc.scopeattrs, dc.apcs), dc.login, nilValue, r); } // Get the request args @@ -355,19 +355,14 @@ static int checkAuthn(request_rec *r) { // Handle OAuth authorize request step if (string(r->uri) == "/oauth2/authorize/") { r->ap_auth_type = const_cast<char*>(atype); - return httpd::reportStatus(authorize(args, r, sc.appkeys)); + return openauth::reportStatus(authorize(args, r, sc.appkeys), dc.login, 1, r); } // Handle OAuth access_token request step if (string(r->uri) == "/oauth2/access_token/") { r->ap_auth_type = const_cast<char*>(atype); - const failable<int> authrc = accessToken(args, r, sc.appkeys, sc.cs, dc.scopeattrs, dc.apcs, sc.mc); - - // Redirect to the login page if user is not authorized - if (!hasContent(authrc) && rcode(authrc) == HTTP_UNAUTHORIZED) - return httpd::reportStatus(openauth::login(dc.login, string("/"), 1, r)); - - return httpd::reportStatus(authrc); + const failable<int> authrc = accessToken(args, r, sc.appkeys, *(*(perthread_ptr<http::CURLSession>*)sc.cs), dc.scopeattrs, dc.apcs, sc.mc); + return openauth::reportStatus(authrc, dc.login, 1, r); } // Redirect to the login page, unless we have a session id or an authorization @@ -382,22 +377,22 @@ static int checkAuthn(request_rec *r) { return DECLINED; r->ap_auth_type = const_cast<char*>(atype); - return httpd::reportStatus(openauth::login(dc.login, value(), value(), r)); + return httpd::reportStatus(openauth::login(dc.login, nilValue, nilValue, r)); } /** * Process the module configuration. */ -int postConfigMerge(ServerConf& mainsc, server_rec* s) { +int postConfigMerge(const ServerConf& mainsc, server_rec* const s) { if (s == NULL) return OK; ServerConf& sc = httpd::serverConf<ServerConf>(s, &mod_tuscany_oauth2); debug(httpd::serverName(s), "modoauth2::postConfigMerge::serverName"); // Merge configuration from main server - if (isNil(sc.appkeys)) + if (isNil((list<list<value> >)sc.appkeys)) sc.appkeys = mainsc.appkeys; - if (isNil(sc.mcaddrs)) + if (isNil((list<string>)sc.mcaddrs)) sc.mcaddrs = mainsc.mcaddrs; sc.mc = mainsc.mc; sc.cs = mainsc.cs; @@ -405,10 +400,10 @@ int postConfigMerge(ServerConf& mainsc, server_rec* s) { return postConfigMerge(mainsc, 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); +int postConfig(apr_pool_t* const p, unused apr_pool_t* const plog, unused apr_pool_t* const ptemp, server_rec* const s) { + const gc_scoped_pool sp(p); - ServerConf& sc = httpd::serverConf<ServerConf>(s, &mod_tuscany_oauth2); + const ServerConf& sc = httpd::serverConf<ServerConf>(s, &mod_tuscany_oauth2); debug(httpd::serverName(s), "modoauth2::postConfig::serverName"); // Merge server configurations @@ -416,30 +411,12 @@ int postConfig(apr_pool_t* p, unused apr_pool_t* plog, unused apr_pool_t* ptemp, } /** - * Lambda function that creates a new CURL session. - */ -class newsession { -public: - newsession(const string& ca, const string& cert, const string& key) : ca(ca), cert(cert), key(key) { - } - - const gc_ptr<http::CURLSession> operator()() const { - return new (gc_new<http::CURLSession>()) http::CURLSession(ca, cert, key, "", 0); - } - -private: - const string ca; - const string cert; - const string key; -}; - -/** * Child process initialization. */ -void childInit(apr_pool_t* p, server_rec* s) { - gc_scoped_pool pool(p); +void childInit(apr_pool_t* const p, server_rec* const s) { + const gc_scoped_pool sp(p); - ServerConf* psc = (ServerConf*)ap_get_module_config(s->module_config, &mod_tuscany_oauth2); + ServerConf* const psc = (ServerConf*)ap_get_module_config(s->module_config, &mod_tuscany_oauth2); if(psc == NULL) { cfailure << "[Tuscany] Due to one or more errors mod_tuscany_oauth2 loading failed. Causing apache to stop loading." << endl; exit(APEXIT_CHILDFATAL); @@ -447,13 +424,21 @@ void childInit(apr_pool_t* p, server_rec* s) { ServerConf& sc = *psc; // Connect to Memcached - if (isNil(sc.mcaddrs)) + if (isNil((list<string>)sc.mcaddrs)) sc.mc = *(new (gc_new<memcache::MemCached>()) memcache::MemCached("localhost", 11211)); else sc.mc = *(new (gc_new<memcache::MemCached>()) memcache::MemCached(sc.mcaddrs)); // Setup a CURL session - sc.cs = perthread_ptr<http::CURLSession>(lambda<gc_ptr<http::CURLSession>()>(newsession(sc.ca, sc.cert, sc.key))); + const string ca = sc.ca; + const string cert = sc.cert; + const string key = sc.key; + const gc_pool cp = gc_current_pool(); + const lambda<const gc_ptr<http::CURLSession>()> newsession = [ca, cert, key, cp]() -> const gc_ptr<http::CURLSession> { + const gc_scoped_pool sp(pool(cp)); + return new (gc_new<http::CURLSession>()) http::CURLSession(ca, cert, key, emptyString, 0); + }; + sc.cs = *(new (gc_new<perthread_ptr<http::CURLSession> >()) perthread_ptr<http::CURLSession>(newsession)); // Merge the updated configuration into the virtual hosts postConfigMerge(sc, s->next); @@ -462,56 +447,56 @@ void childInit(apr_pool_t* p, server_rec* s) { /** * Configuration commands. */ -const char* confAppKey(cmd_parms *cmd, unused void *c, const char *arg1, const char* arg2, const char* arg3) { - gc_scoped_pool pool(cmd->pool); +char* confAppKey(cmd_parms *cmd, unused void *c, char *arg1, char* arg2, char* arg3) { + const gc_scoped_pool sp(cmd->pool); ServerConf& sc = httpd::serverConf<ServerConf>(cmd, &mod_tuscany_oauth2); - sc.appkeys = cons<list<value> >(mklist<value>(arg1, mklist<value>(arg2, arg3)), sc.appkeys); + sc.appkeys = cons<list<value> >(mklist<value>(arg1, mklist<value>(arg2, arg3)), (list<list<value> >)sc.appkeys); return NULL; } -const char* confMemcached(cmd_parms *cmd, unused void *c, const char *arg) { - gc_scoped_pool pool(cmd->pool); +char* confMemcached(cmd_parms *cmd, unused void *c, char *arg) { + const gc_scoped_pool sp(cmd->pool); ServerConf& sc = httpd::serverConf<ServerConf>(cmd, &mod_tuscany_oauth2); - sc.mcaddrs = cons<string>(arg, sc.mcaddrs); + sc.mcaddrs = cons<string>(arg, (list<string>)sc.mcaddrs); return NULL; } -const char* confEnabled(cmd_parms *cmd, void *c, const int arg) { - gc_scoped_pool pool(cmd->pool); +char* confEnabled(cmd_parms *cmd, void *c, int arg) { + const gc_scoped_pool sp(cmd->pool); DirConf& dc = httpd::dirConf<DirConf>(c); dc.enabled = (bool)arg; return NULL; } -const char* confLogin(cmd_parms *cmd, void *c, const char* arg) { - gc_scoped_pool pool(cmd->pool); +char* confLogin(cmd_parms *cmd, void *c, char* arg) { + const gc_scoped_pool sp(cmd->pool); DirConf& dc = httpd::dirConf<DirConf>(c); dc.login = arg; return NULL; } -const char* confCAFile(cmd_parms *cmd, unused void *c, const char *arg) { - gc_scoped_pool pool(cmd->pool); +char* confCAFile(cmd_parms *cmd, unused void *c, char *arg) { + const gc_scoped_pool sp(cmd->pool); ServerConf& sc = httpd::serverConf<ServerConf>(cmd, &mod_tuscany_oauth2); sc.ca = arg; return NULL; } -const char* confCertFile(cmd_parms *cmd, unused void *c, const char *arg) { - gc_scoped_pool pool(cmd->pool); +char* confCertFile(cmd_parms *cmd, unused void *c, char *arg) { + const gc_scoped_pool sp(cmd->pool); ServerConf& sc = httpd::serverConf<ServerConf>(cmd, &mod_tuscany_oauth2); sc.cert = arg; return NULL; } -const char* confCertKeyFile(cmd_parms *cmd, unused void *c, const char *arg) { - gc_scoped_pool pool(cmd->pool); +char* confCertKeyFile(cmd_parms *cmd, unused void *c, char *arg) { + const gc_scoped_pool sp(cmd->pool); ServerConf& sc = httpd::serverConf<ServerConf>(cmd, &mod_tuscany_oauth2); sc.key = arg; return NULL; } -const char* confScopeAttr(cmd_parms *cmd, void* c, const char* arg1, const char* arg2) { - gc_scoped_pool pool(cmd->pool); +char* confScopeAttr(cmd_parms *cmd, void* c, char* arg1, char* arg2) { + const gc_scoped_pool sp(cmd->pool); DirConf& dc = httpd::dirConf<DirConf>(c); - dc.scopeattrs = cons<list<value> >(mklist<value>(arg1, arg2), dc.scopeattrs); + dc.scopeattrs = cons<list<value> >(mklist<value>(arg1, arg2), (list<list<value> >)dc.scopeattrs); return NULL; } -const char* confAuthnProvider(cmd_parms *cmd, void *c, const char* arg) { - gc_scoped_pool pool(cmd->pool); +char* confAuthnProvider(cmd_parms *cmd, void *c, char* arg) { + const gc_scoped_pool sp(cmd->pool); DirConf& dc = httpd::dirConf<DirConf>(c); // Lookup and cache the Authn provider diff --git a/sca-cpp/trunk/modules/opencl/Makefile.am b/sca-cpp/trunk/modules/opencl/Makefile.am index 3e76a435c8..92da55b307 100644 --- a/sca-cpp/trunk/modules/opencl/Makefile.am +++ b/sca-cpp/trunk/modules/opencl/Makefile.am @@ -36,7 +36,7 @@ endif #mod_LTLIBRARIES = libmod_tuscany_opencl.la #libmod_tuscany_opencl_la_SOURCES = mod-opencl.cpp -#libmod_tuscany_opencl_la_LDFLAGS = -lxml2 -lcurl -lmozjs -framework OpenCL +#libmod_tuscany_opencl_la_LDFLAGS = -lxml2 -lcurl -ljansson -framework OpenCL #noinst_DATA = libmod_tuscany_opencl${libsuffix} #libmod_tuscany_opencl${libsuffix}: # ln -s .libs/libmod_tuscany_opencl${libsuffix} @@ -48,7 +48,7 @@ opencl_shell_SOURCES = opencl-shell.cpp opencl_shell_LDFLAGS = ${OPENCL_FLAGS} client_test_SOURCES = client-test.cpp -client_test_LDFLAGS = -lxml2 -lcurl -lmozjs +client_test_LDFLAGS = -lxml2 -lcurl -ljansson dist_noinst_SCRIPTS = server-test noinst_PROGRAMS = opencl-test client-test diff --git a/sca-cpp/trunk/modules/opencl/driver.hpp b/sca-cpp/trunk/modules/opencl/driver.hpp index b4b6c2845b..c45bcf6ee4 100644 --- a/sca-cpp/trunk/modules/opencl/driver.hpp +++ b/sca-cpp/trunk/modules/opencl/driver.hpp @@ -37,7 +37,7 @@ namespace opencl { const value evalDriverLoop(const OpenCLProgram& clprog, istream& in, ostream& out, const OpenCLContext& cl) { scheme::promptForInput(scheme::evalInputPrompt, out); - value input = scheme::readValue(in); + const value input = content(scheme::readValue(in)); if (isNil(input)) return input; const failable<value> output = evalKernel(createKernel(input, clprog), input, 1, value::String, 512, cl); diff --git a/sca-cpp/trunk/modules/opencl/eval.hpp b/sca-cpp/trunk/modules/opencl/eval.hpp index 5606b2f57a..f842ba783d 100644 --- a/sca-cpp/trunk/modules/opencl/eval.hpp +++ b/sca-cpp/trunk/modules/opencl/eval.hpp @@ -61,7 +61,7 @@ cl_ulong evaltime = 0; /** * Reset the OpenCL profiling counters. */ -bool resetOpenCLCounters() { +const bool resetOpenCLCounters() { memtime = kernelqtime = kerneltime = preptime = evaltime = 0; return true; } @@ -69,7 +69,7 @@ bool resetOpenCLCounters() { /** * Print the OpenCL profiling counters. */ -bool printOpenCLCounters(const long n) { +const bool printOpenCLCounters(const long n) { cout << " kernelq " << ((double)kernelqtime / 1000000.0) / (double)n << " ms kernel " << ((double)kerneltime / 1000000.0) / (double)n << " ms memory " << ((double)memtime / 1000000.0) / (double)n << " ms prep " << ((double)preptime / 1000000.0) / (double)n << " ms eval " << ((double)evaltime / 1000000.0) / (double)n << " ms"; return true; } @@ -77,7 +77,7 @@ bool printOpenCLCounters(const long n) { /** * Profile a memory event. */ -failable<cl_ulong> profileMemEvent(const cl_event evt) { +const failable<cl_ulong> profileMemEvent(const cl_event evt) { cl_ulong start = 0; const cl_int serr = clGetEventProfilingInfo(evt, CL_PROFILING_COMMAND_START, sizeof(cl_ulong), &start, NULL); if (serr != CL_SUCCESS) @@ -94,7 +94,7 @@ failable<cl_ulong> profileMemEvent(const cl_event evt) { /** * Profile a kernel event. */ -failable<cl_ulong> profileKernelEvent(const cl_event evt) { +const failable<cl_ulong> profileKernelEvent(const cl_event evt) { cl_ulong queued = 0; const cl_int qerr = clGetEventProfilingInfo(evt, CL_PROFILING_COMMAND_QUEUED, sizeof(cl_ulong), &queued, NULL); if (qerr != CL_SUCCESS) @@ -117,7 +117,7 @@ failable<cl_ulong> profileKernelEvent(const cl_event evt) { /** * Profile an array of memory events. */ -failable<cl_ulong> profileMemEvents(const cl_uint n, const cl_event* evt) { +const failable<cl_ulong> profileMemEvents(const cl_uint n, const cl_event* const evt) { if (n == 0) return 0; const failable<cl_ulong> t = profileMemEvent(*evt); @@ -221,6 +221,21 @@ public: } } + OpenCLContext(const OpenCLContext& c) : dev(c.dev), ndevs(c.ndevs), ctx(c.ctx) { + for (cl_uint i = 0; i < ndevs; i++) { + devid[i] = c.devid[i]; + cq[i] = c.cq[i]; + if (cq[i] != 0) { + const cl_int rcqerr = clRetainCommandQueue(cq[i]); + if (rcqerr != CL_SUCCESS) + mkfailure<bool>(string("Couldn't retain OpenCL command queue: ") + clError(rcqerr)); + } + } + const cl_int rcerr = clRetainContext(ctx); + if (rcerr != CL_SUCCESS) + mkfailure<bool>(string("Couldn't retain OpenCL context: ") + clError(rcerr)); + } + ~OpenCLContext() { for (cl_uint i = 0; i < ndevs; i++) { if (cq[i] != 0) @@ -372,7 +387,7 @@ private: /** * Return a read-only memory buffer. */ -const failable<OpenCLBuffer> readOnlyBuffer(const size_t size, const void* p, const OpenCLContext& cl, const cl_command_queue cq) { +const failable<OpenCLBuffer> readOnlyBuffer(const size_t size, const void* const p, const OpenCLContext& cl, const cl_command_queue cq) { if (cl.dev == OpenCLContext::CPU) { cl_int err; const cl_mem buf = clCreateBuffer(cl.ctx, CL_MEM_READ_ONLY | CL_MEM_USE_HOST_PTR, size, const_cast<void*>(p), &err); @@ -396,7 +411,7 @@ const failable<OpenCLBuffer> readOnlyBuffer(const size_t size, const void* p, co /** * Fill an array of write events for a given list of buffers. */ -const cl_uint writeBufferEvents(const list<OpenCLBuffer>& buf, cl_event* evt) { +const cl_uint writeBufferEvents(const list<OpenCLBuffer>& buf, cl_event* const evt) { if (isNil(buf)) return 0; const cl_event e = car(buf).evt; @@ -427,7 +442,7 @@ const failable<OpenCLBuffer> writeOnlyBuffer(const size_t size, const OpenCLCont /** * Convert a value to a kernel arg. */ -const failable<OpenCLBuffer> valueToKernelArg(const cl_uint i, const size_t size, const void* p, const failable<OpenCLBuffer>& buf, const OpenCLKernel& kernel) { +const failable<OpenCLBuffer> valueToKernelArg(const cl_uint i, const size_t size, const void* const p, const failable<OpenCLBuffer>& buf, const OpenCLKernel& kernel) { if (!hasContent(buf)) return buf; if (p != NULL) { @@ -446,7 +461,7 @@ const failable<OpenCLBuffer> valueToKernelArg(const cl_uint i, const size_t size const failable<OpenCLBuffer> valueToKernelArg(const value& v, const cl_uint i, const OpenCLKernel& kernel, const OpenCLContext& cl, const cl_command_queue cq) { switch (type(v)) { case value::Symbol: { - const string s = string("'") + v; + const string s = string("'") + (string)v; return valueToKernelArg(i, 0, NULL, readOnlyBuffer(length(s) + 1, c_str(s), cl, cq), kernel); } case value::String: { @@ -489,28 +504,28 @@ const failable<list<OpenCLBuffer>> valuesToKernelArgs(const list<value>& v, cons /** * Convert a kernel result to a value. */ -const value kernelResultToValue(const void* p, const value::ValueType type) { +const value kernelResultToValue(const void* const p, const value::ValueType type) { switch(type) { case value::Symbol: { - const char* s = static_cast<const char*>(p); + const char* const s = (const char*)p; const size_t l = strlen(s); if (l != 0 && *s == '\'') return value(s + 1); return value(s); } case value::String: { - const char* s = static_cast<const char*>(p); + const char* const s = (const char*)p; const size_t l = strlen(s); if (l != 0 && *s == '\'') return value(s + 1); return value(string(s, l)); } case value::Number: - return (double)(*(static_cast<const cl_float*>(p))); + return (double)(*(const cl_float*)p); case value::Bool: - return (bool)(*(static_cast<const cl_int*>(p))); + return (bool)(*(const cl_int*)p); default: - return *(static_cast<const value*>(p)); + return *(const value*)p; } } @@ -582,9 +597,9 @@ const failable<OpenCLKernel> createKernel(const value& expr, const OpenCLProgram // The start, stop, and restart functions are optional //if (fn == "start" || fn == "stop") - //return value(lambda<value(const list<value>&)>()); + //return value(lvvlambda()); - return mkfailure<OpenCLKernel>(string("Couldn't find function: ") + car<value>(expr) + " : " + clError(ckerr)); + return mkfailure<OpenCLKernel>(string("Couldn't find function: ") + (string)car<value>(expr) + " : " + clError(ckerr)); } return OpenCLKernel(k); } diff --git a/sca-cpp/trunk/modules/opencl/opencl-shell.cpp b/sca-cpp/trunk/modules/opencl/opencl-shell.cpp index 1dfeaeea1d..a0598c9d32 100644 --- a/sca-cpp/trunk/modules/opencl/opencl-shell.cpp +++ b/sca-cpp/trunk/modules/opencl/opencl-shell.cpp @@ -29,8 +29,8 @@ #include "string.hpp" #include "driver.hpp" -int main(const int argc, char** argv) { - tuscany::gc_scoped_pool pool; +int main(const int argc, char** const argv) { + const tuscany::gc_scoped_pool pool; if (argc != 2) { tuscany::cerr << "Usage: opencl-shell <kernel.cl>" << tuscany::endl; return 1; diff --git a/sca-cpp/trunk/modules/opencl/opencl-test.cpp b/sca-cpp/trunk/modules/opencl/opencl-test.cpp index 17bc5ccfa6..4c7f3fa86b 100644 --- a/sca-cpp/trunk/modules/opencl/opencl-test.cpp +++ b/sca-cpp/trunk/modules/opencl/opencl-test.cpp @@ -159,8 +159,8 @@ const string testCharsParallelGPU = " r[i] = i < ixl? x[i] : i < ixl + iyl? y[i - ixl] : '\\0';\n" "}\n"; -bool testTaskParallel(const OpenCLContext::DeviceType dev) { - gc_scoped_pool pool; +const bool testTaskParallel(const OpenCLContext::DeviceType dev) { + const gc_scoped_pool pool; OpenCLContext cl(dev); if (!devices(cl) != 0) return true; @@ -192,12 +192,12 @@ bool testTaskParallel(const OpenCLContext::DeviceType dev) { const value exp = mklist<value>("int_or", true, false); const failable<value> r = evalKernel(createKernel(exp, content(clprog)), exp, cl); assert(hasContent(r)); - assert(content(r) == value(true)); + assert(content(r) == trueValue); const value exp2 = mklist<value>("int_or", false, false); const failable<value> r2 = evalKernel(createKernel(exp2, content(clprog)), exp2, cl); assert(hasContent(r2)); - assert(content(r2) == value(false)); + assert(content(r2) == falseValue); } { istringstream is(dev == OpenCLContext::CPU? testCharsCPU : testCharsGPU); @@ -223,41 +223,33 @@ bool testTaskParallel(const OpenCLContext::DeviceType dev) { return true; } -struct evalTaskParallelLoop { - evalTaskParallelLoop(const OpenCLContext& cl, const OpenCLProgram& clprog) : cl(cl), clprog(clprog), exp(mklist<value>("add", 60, string("Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello "), 60, string("World World World World World World World World World World "))) { - } - const bool operator()() const { - const failable<value> r = evalKernel(createKernel(exp, clprog), exp, 1, value::String, 128, cl); - assert(hasContent(r)); - assert(content(r) == value(string("Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello World World World World World World World World World World "))); - return true; - } - - const OpenCLContext& cl; - const OpenCLProgram& clprog; - const value exp; -}; - const bool testTaskParallelPerf(const OpenCLContext::DeviceType dev, const bool copy) { - gc_scoped_pool pool; + const gc_scoped_pool pool; OpenCLContext cl(dev); if (!devices(cl) != 0) return true; istringstream is(dev == OpenCLContext::CPU? testCharsCPU : copy? testCharsCopyGPU : testCharsGPU); - failable<OpenCLProgram> clprog = readProgram("kernel.cl", is, cl); - assert(hasContent(clprog)); + failable<OpenCLProgram> fclprog = readProgram("kernel.cl", is, cl); + assert(hasContent(fclprog)); resetOpenCLCounters(); - const lambda<bool()> el = evalTaskParallelLoop(cl, content(clprog)); + OpenCLProgram clprog = content(fclprog); + const value exp = mklist<value>("add", 60, string("Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello "), 60, string("World World World World World World World World World World ")); + const blambda el = [cl, clprog, exp]() -> const bool { + const failable<value> r = evalKernel(createKernel(exp, clprog), exp, 1, value::String, 128, cl); + assert(hasContent(r)); + assert(content(r) == value(string("Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello World World World World World World World World World World "))); + return true; + }; cout << "OpenCL task-parallel eval " << (dev == OpenCLContext::CPU? "CPU" : "GPU") << (copy? " copy" : "") << " test " << time(el, 5, 500) << " ms"; printOpenCLCounters(500); cout << endl; return true; } -bool testDataParallel(const OpenCLContext::DeviceType dev) { - gc_scoped_pool pool; +const bool testDataParallel(const OpenCLContext::DeviceType dev) { + const gc_scoped_pool pool; OpenCLContext cl(dev); if (!devices(cl) != 0) return true; @@ -276,33 +268,25 @@ bool testDataParallel(const OpenCLContext::DeviceType dev) { return true; } -struct evalDataParallelLoop { - evalDataParallelLoop(const OpenCLContext& cl, const OpenCLProgram& clprog) : cl(cl), clprog(clprog), exp(mklist<value>("add", 60, string("Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello "), 60, string("World World World World World World World World World World "))) { - } - const bool operator()() const { - const failable<value> r = evalKernel(createKernel(exp, clprog), exp, 121, value::String, 128, cl); - assert(hasContent(r)); - assert(content(r) == value(string("Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello World World World World World World World World World World "))); - return true; - } - - const OpenCLContext& cl; - const OpenCLProgram& clprog; - const value exp; -}; - const bool testDataParallelPerf(const OpenCLContext::DeviceType dev, const bool copy) { - gc_scoped_pool pool; + const gc_scoped_pool pool; OpenCLContext cl(dev); if (!devices(cl) != 0) return true; istringstream is(dev == OpenCLContext::CPU? testCharsParallelCPU : copy? testCharsParallelCopyGPU : testCharsParallelGPU); - failable<OpenCLProgram> clprog = readProgram("kernel.cl", is, cl); - assert(hasContent(clprog)); + failable<OpenCLProgram> fclprog = readProgram("kernel.cl", is, cl); + assert(hasContent(fclprog)); resetOpenCLCounters(); - const lambda<bool()> el = evalDataParallelLoop(cl, content(clprog)); + OpenCLProgram clprog = content(fclprog); + const value exp = mklist<value>("add", 60, string("Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello "), 60, string("World World World World World World World World World World ")); + const blambda el = [cl, clprog, exp]() -> const bool { + const failable<value> r = evalKernel(createKernel(exp, clprog), exp, 121, value::String, 128, cl); + assert(hasContent(r)); + assert(content(r) == value(string("Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello World World World World World World World World World World "))); + return true; + }; cout << "OpenCL data-parallel eval " << (dev == OpenCLContext::CPU? "CPU" : "GPU") << (copy? " copy" : "") << " test " << time(el, 5, 500) << " ms"; printOpenCLCounters(500); cout << endl; diff --git a/sca-cpp/trunk/modules/python/Makefile.am b/sca-cpp/trunk/modules/python/Makefile.am index 80c3097b48..92548de6d0 100644 --- a/sca-cpp/trunk/modules/python/Makefile.am +++ b/sca-cpp/trunk/modules/python/Makefile.am @@ -35,7 +35,7 @@ EXTRA_DIST = domain-test.composite client-test.py server-test.py mod_LTLIBRARIES = libmod_tuscany_python.la libmod_tuscany_python_la_SOURCES = mod-python.cpp -libmod_tuscany_python_la_LDFLAGS = -lxml2 -lcurl -lmozjs -L${PYTHON_LIB} -R${PYTHON_LIB} -lpython${PYTHON_VERSION} +libmod_tuscany_python_la_LDFLAGS = -lxml2 -lcurl -ljansson -L${PYTHON_LIB} -R${PYTHON_LIB} -lpython${PYTHON_VERSION} noinst_DATA = libmod_tuscany_python${libsuffix} libmod_tuscany_python${libsuffix}: ln -s .libs/libmod_tuscany_python${libsuffix} @@ -47,7 +47,7 @@ python_shell_SOURCES = python-shell.cpp python_shell_LDFLAGS = -L${PYTHON_LIB} -R${PYTHON_LIB} -lpython${PYTHON_VERSION} client_test_SOURCES = client-test.cpp -client_test_LDFLAGS = -lxml2 -lcurl -lmozjs +client_test_LDFLAGS = -lxml2 -lcurl -ljansson dist_noinst_SCRIPTS = server-test wiring-test noinst_PROGRAMS = python-test client-test diff --git a/sca-cpp/trunk/modules/python/driver.hpp b/sca-cpp/trunk/modules/python/driver.hpp index a5d554172b..41daed32c3 100644 --- a/sca-cpp/trunk/modules/python/driver.hpp +++ b/sca-cpp/trunk/modules/python/driver.hpp @@ -35,9 +35,9 @@ namespace tuscany { namespace python { -const value evalDriverLoop(PyObject* script, istream& in, ostream& out, PythonRuntime& py) { +const value evalDriverLoop(PyObject* const script, istream& in, ostream& out, PythonRuntime& py) { scheme::promptForInput(scheme::evalInputPrompt, out); - value input = scheme::readValue(in); + const value input = content(scheme::readValue(in)); if (isNil(input)) return input; const failable<value> output = evalScript(input, script, py); @@ -46,11 +46,11 @@ const value evalDriverLoop(PyObject* script, istream& in, ostream& out, PythonRu return evalDriverLoop(script, in, out, py); } -const bool evalDriverRun(const char* path, istream& in, ostream& out) { +const bool evalDriverRun(const char* const path, istream& in, ostream& out) { PythonRuntime py; scheme::setupDisplay(out); ifstream is(path); - failable<PyObject*> script = readScript(moduleName(path), path, is, py); + const failable<PyObject*> script = readScript(moduleName(path), path, is, py); if (!hasContent(script)) return true; evalDriverLoop(content(script), in, out, py); diff --git a/sca-cpp/trunk/modules/python/eval.hpp b/sca-cpp/trunk/modules/python/eval.hpp index 5c0be7d261..3f9c6c20a2 100644 --- a/sca-cpp/trunk/modules/python/eval.hpp +++ b/sca-cpp/trunk/modules/python/eval.hpp @@ -53,8 +53,8 @@ class PythonRuntime; /** * Maintain a garbage collected reference to a Python object. */ -const bool pyIncRef(PyObject* o); -const bool pyDecRef(PyObject* o, PythonRuntime* py); +const bool pyIncRef(PyObject* const o); +const bool pyDecRef(PyObject* const o, PythonRuntime* const py); /** * Write to debug log from Python. @@ -70,7 +70,7 @@ const value pyDebug(const list<value>& args) { class PythonRuntime { public: - PythonRuntime() { + PythonRuntime() : owner(true) { debug("python::pythonruntime"); // Save current process id @@ -115,7 +115,7 @@ public: PySys_SetArgv(0, const_cast<char**>(&arg0)); // Install debug log function - PyObject* mkPyLambda(const lambda<value(const list<value>&)>& l, PythonRuntime* py); + PyObject* mkPyLambda(const lvvlambda& l, PythonRuntime* py); PyObject* pyd= mkPyLambda(pyDebug, this); PyObject* sys = PyImport_ImportModule("sys"); PyObject_SetAttrString(sys, "debug", pyd); @@ -127,10 +127,21 @@ public: #endif } +#ifdef WANT_THREADS + PythonRuntime(const PythonRuntime& py) : owner(false), mutex(py.mutex), pidmutex(py.pidmutex), pid(py.pid) { + } +#else + PythonRuntime(const PythonRuntime& py) : owner(false), pid(py.pid) { + } +#endif + + PythonRuntime& operator=(const PythonRuntime& py) = delete; + ~PythonRuntime() { } private: + const bool owner; #ifdef WANT_THREADS pthread_mutex_t mutex; pthread_mutex_t pidmutex; @@ -145,9 +156,9 @@ private: /** * Return the last python error. */ -const string lastErrorTrace(PyObject *trace) { +const string lastErrorTrace(PyObject* const trace) { if (trace == NULL) - return ""; + return emptyString; PyTracebackObject* tb = (PyTracebackObject*)trace; const int limit = 16; int depth = 0; @@ -167,16 +178,16 @@ const string lastErrorTrace(PyObject *trace) { return str(os); } -const string lastError(PythonRuntime* py) { +const string lastError(PythonRuntime* const py) { if(PyErr_Occurred()) { PyObject* type = NULL; PyObject* val = NULL; PyObject* trace = NULL; PyErr_Fetch(&type, &val, &trace); if (type != NULL && val != NULL) { - PyObject* stype = PyObject_Repr(type); - PyObject* sval = PyObject_Repr(val); - string msg = string() + PyString_AsString(stype) + " : " + PyString_AsString(sval) + lastErrorTrace(trace); + PyObject* const stype = PyObject_Repr(type); + PyObject* const sval = PyObject_Repr(val); + const string msg = string() + PyString_AsString(stype) + " : " + PyString_AsString(sval) + lastErrorTrace(trace); pyDecRef(stype, py); pyDecRef(sval, py); PyErr_Restore(type, val, trace); @@ -187,7 +198,7 @@ const string lastError(PythonRuntime* py) { PyErr_Clear(); return "Unknown Python error"; } - return ""; + return emptyString; } /** @@ -195,7 +206,7 @@ const string lastError(PythonRuntime* py) { */ class PythonRuntimeLock { public: - PythonRuntimeLock(PythonRuntime* py) : py(py) { + PythonRuntimeLock(PythonRuntime* const py) : py(py) { #ifdef WANT_THREADS pthread_mutex_lock(&py->mutex); #endif @@ -208,7 +219,7 @@ public: } private: - PythonRuntime* py; + PythonRuntime* const py; }; /** @@ -216,7 +227,7 @@ private: */ class PythonThreadIn { public: - PythonThreadIn(PythonRuntime* py) : py(py) { + PythonThreadIn(PythonRuntime* const py) : py(py) { // Reinitialize Python thread support after a fork const unsigned long pid = processId(); @@ -261,7 +272,7 @@ public: } private: - PythonRuntime* py; + PythonRuntime* const py; #ifdef WANT_THREADS PyGILState_STATE gstate; #endif @@ -272,7 +283,7 @@ private: */ class PythonThreadOut { public: - PythonThreadOut(PythonRuntime* py) : py(py) { + PythonThreadOut(PythonRuntime* const py) : py(py) { #ifdef WANT_THREADS //debug("python::gil::save"); tstate = PyEval_SaveThread(); @@ -289,7 +300,7 @@ public: } private: - PythonRuntime* py; + PythonRuntime* const py; #ifdef WANT_THREADS PyThreadState* tstate; #endif @@ -300,7 +311,7 @@ private: */ class PyGCRef { public: - PyGCRef(PyObject* o, PythonRuntime* py) : o(o), py(py) { + PyGCRef(PyObject* const o, PythonRuntime* const py) : o(o), py(py) { } ~PyGCRef() { @@ -311,21 +322,21 @@ public: } private: - PyObject* o; - PythonRuntime* py; + PyObject* const o; + PythonRuntime* const py; }; /** * Maintain a garbage collected reference to a Python object. */ -const bool pyIncRef(PyObject* o) { +const bool pyIncRef(PyObject* const o) { if (o == NULL) return true; Py_INCREF(o); return true; } -const bool pyDecRef(unused PyObject* o, unused PythonRuntime* py) { +const bool pyDecRef(unused PyObject* const o, unused PythonRuntime* const py) { if (o == NULL) return true; //new (gc_new<PyGCRef>()) PyGCRef(o, py); @@ -336,40 +347,40 @@ const bool pyDecRef(unused PyObject* o, unused PythonRuntime* py) { /** * Declare conversion functions. */ -PyObject* valueToPyObject(const value& v, PythonRuntime* py); -const value pyObjectToValue(PyObject *o, PythonRuntime* py); -PyObject* valuesToPyTuple(const list<value>& v, PythonRuntime* py); -const list<value> pyTupleToValues(PyObject* o, PythonRuntime* py); +PyObject* const valueToPyObject(const value& v, PythonRuntime* const py); +const value pyObjectToValue(PyObject* const o, PythonRuntime* const py); +PyObject* const valuesToPyTuple(const list<value>& v, PythonRuntime* const py); +const list<value> pyTupleToValues(PyObject* const o, PythonRuntime* const py); /** * Callable python type used to represent a lambda expression. */ typedef struct { PyObject_HEAD - lambda<value(const list<value>&)>* func; + lvvlambda* func; PythonRuntime* py; } pyLambda; -PyObject *mkPyLambda(const lambda<value(const list<value>&)>& l, PythonRuntime* py); +PyObject* const mkPyLambda(const lvvlambda& l, PythonRuntime* const py); -void pyLambda_dealloc(PyObject* self) { +void pyLambda_dealloc(PyObject* const self) { //debug(self, "python::pylambda_dealloc"); PyObject_Del(self); } -const string pyRepr(PyObject* o, PythonRuntime* py) { - PyObject* r = PyObject_Repr(o); +const string pyRepr(PyObject* const o, PythonRuntime* const py) { + PyObject* const r = PyObject_Repr(o); const string s = PyString_AsString(r); pyDecRef(r, py); return s; } -const value pyLambda_callout(const pyLambda* pyl, const list<value>& args, PythonRuntime* py) { +const value pyLambda_callout(const pyLambda* const pyl, const list<value>& args, PythonRuntime* const py) { PythonThreadOut pyout(py); return (*(pyl->func))(args); } -PyObject* pyLambda_call(PyObject* self, PyObject* args, unused PyObject* kwds) { +PyObject* const pyLambda_call(PyObject* const self, PyObject* const args, unused PyObject* const kwds) { debug("python::call"); const pyLambda* pyl = (const pyLambda*)self; const value result = pyLambda_callout(pyl, pyTupleToValues(args, pyl->py), pyl->py); @@ -378,22 +389,7 @@ PyObject* pyLambda_call(PyObject* self, PyObject* args, unused PyObject* kwds) { return pyr; } -struct pyProxy { - const value name; - const lambda<value(const list<value>&)> func; - - pyProxy(const value& name, const lambda<value(const list<value>&)>& func) : name(name), func(func) { - } - - const value operator()(const list<value>& args) const { - debug(name, "python::proxy::name"); - const value result = func(cons<value>(name, args)); - debug(result, "python::proxy::result"); - return result; - } -}; - -PyObject* pyLambda_getattr(PyObject *self, PyObject *attrname) { +PyObject* const pyLambda_getattr(PyObject* const self, PyObject* const attrname) { const string name = PyString_AsString(attrname); if (substr(name, 0, 1) == "_") return PyObject_GenericGetAttr(self, attrname); @@ -403,9 +399,18 @@ PyObject* pyLambda_getattr(PyObject *self, PyObject *attrname) { return self; } - const pyLambda* pyl = (pyLambda*)self; + const pyLambda* const pyl = (const pyLambda* const)self; debug(name, "python::getattr::name"); - PyObject* pyr = mkPyLambda(pyProxy(name, *(pyl->func)), pyl->py); + + const lvvlambda func = *(pyl->func); + const lvvlambda pyProxy = [name, func](const list<value>& args) -> const value { + debug(name, "python::proxy::name"); + const value result = func(cons<value>(name, args)); + debug(result, "python::proxy::result"); + return result; + }; + + PyObject* const pyr = mkPyLambda(pyProxy, pyl->py); return pyr; } @@ -464,10 +469,10 @@ PyObject* pyLambda_getattr(PyObject *self, PyObject *attrname) { /** * Create a new python object representing a lambda expression. */ -PyObject *mkPyLambda(const lambda<value(const list<value>&)>& l, PythonRuntime* py) { - pyLambda* pyl = PyObject_New(pyLambda, &pyLambda_type); +PyObject* const mkPyLambda(const lvvlambda& l, PythonRuntime* const py) { + pyLambda* const pyl = PyObject_New(pyLambda, &pyLambda_type); if (pyl != NULL) { - pyl->func = new (gc_new<lambda<value(const list<value>&)> >()) lambda<value(const list<value>&)>(l); + pyl->func = new (gc_new<lvvlambda >()) lvvlambda(l); pyl->py = py; } //debug(pyl, "python::mkpylambda"); @@ -477,18 +482,18 @@ PyObject *mkPyLambda(const lambda<value(const list<value>&)>& l, PythonRuntime* /** * Convert a list of values to a python list. */ -PyObject* valuesToPyListHelper(PyObject* l, const list<value>& v, PythonRuntime* py) { +PyObject* const valuesToPyListHelper(PyObject* const l, const list<value>& v, PythonRuntime* const py) { if (isNil(v)) return l; - PyObject* pyv = valueToPyObject(car(v), py); + PyObject* const pyv = valueToPyObject(car(v), py); PyList_Append(l, pyv); pyDecRef(pyv, py); return valuesToPyListHelper(l, cdr(v), py); } -PyObject* valuesToPyTuple(const list<value>& v, PythonRuntime* py) { - PyObject* pyl = valuesToPyListHelper(PyList_New(0), v, py); - PyObject* pyt = PyList_AsTuple(pyl); +PyObject* const valuesToPyTuple(const list<value>& v, PythonRuntime* const py) { + PyObject* const pyl = valuesToPyListHelper(PyList_New(0), v, py); + PyObject* const pyt = PyList_AsTuple(pyl); pyDecRef(pyl, py); return pyt; } @@ -496,14 +501,14 @@ PyObject* valuesToPyTuple(const list<value>& v, PythonRuntime* py) { /** * Convert a value to a python object. */ -PyObject* valueToPyObject(const value& v, PythonRuntime* py) { +PyObject* const valueToPyObject(const value& v, PythonRuntime* const py) { switch (type(v)) { case value::List: return valuesToPyTuple(v, py); case value::Lambda: return mkPyLambda(v, py); case value::Symbol: - return PyString_FromString(c_str(string("'") + v)); + return PyString_FromString(c_str(string("'") + (string)v)); case value::String: { const string s = (string)v; return PyString_FromStringAndSize(c_str(s), length(s)); @@ -511,12 +516,12 @@ PyObject* valueToPyObject(const value& v, PythonRuntime* py) { case value::Number: return PyFloat_FromDouble((double)v); case value::Bool: { - PyObject* b = (bool)v? Py_True : Py_False; + PyObject* const b = (bool)v? Py_True : Py_False; pyIncRef(b); return b; } default: { - PyObject* n = Py_None; + PyObject* const n = Py_None; pyIncRef(n); return n; } @@ -526,39 +531,29 @@ PyObject* valueToPyObject(const value& v, PythonRuntime* py) { /** * Convert a python tuple to a list of values. */ -const list<value> pyTupleToValuesHelper(PyObject* o, const size_t i, const size_t size, PythonRuntime* py) { +const list<value> pyTupleToValuesHelper(PyObject* const o, const size_t i, const size_t size, PythonRuntime* const py) { if (i == size) - return list<value>(); + return nilListValue; return cons(pyObjectToValue(PyTuple_GetItem(o, i), py), pyTupleToValuesHelper(o, i + 1, size, py)); } -const list<value> pyTupleToValues(PyObject* o, PythonRuntime* py) { +const list<value> pyTupleToValues(PyObject* const o, PythonRuntime* const py) { return pyTupleToValuesHelper(o, 0, PyTuple_Size(o), py); } /** * Lambda function used to represent a python callable object. */ -struct pyCallable { - PyObject* func; - PythonRuntime* py; - bool owner; - - pyCallable(PyObject* func, PythonRuntime* py) : func(func), py(py), owner(true) { +class pyCallable { +public: + pyCallable(PyObject* const func, PythonRuntime* const py) : func(func), py(py), owner(true) { pyIncRef(func); } pyCallable(const pyCallable& c) : func(c.func), py(c.py), owner(false) { } - const pyCallable& operator=(const pyCallable& c) { - if(this == &c) - return *this; - func = c.func; - py = c.py; - owner = false; - return *this; - } + pyCallable& operator=(const pyCallable& c) = delete; ~pyCallable() { if (!owner) @@ -569,16 +564,16 @@ struct pyCallable { const value operator()(const list<value>& args) const { PythonThreadIn pyin(py); if (debug_islogging()) { - PyObject* rfunc = PyObject_Repr(func); + PyObject* const rfunc = PyObject_Repr(func); char* s = NULL; Py_ssize_t l = 0; PyString_AsStringAndSize(rfunc, &s, &l); debug(string(s, l), "python::operator()::func"); pyDecRef(rfunc, py); } - PyObject* pyargs = valuesToPyTuple(args, py); + PyObject* const pyargs = valuesToPyTuple(args, py); if (debug_islogging()) { - PyObject* rargs = PyObject_Repr(pyargs); + PyObject* const rargs = PyObject_Repr(pyargs); char* s = NULL; Py_ssize_t l = 0; PyString_AsStringAndSize(rargs, &s, &l); @@ -586,21 +581,26 @@ struct pyCallable { pyDecRef(rargs, py); } - PyObject* result = PyObject_CallObject(func, pyargs); + PyObject* const result = PyObject_CallObject(func, pyargs); pyDecRef(pyargs, py); const value v = pyObjectToValue(result, py); pyDecRef(result, py); return v; } + +private: + PyObject* const func; + PythonRuntime* const py; + const bool owner; }; /** * Convert a python object to a value. */ -const value pyObjectToValue(PyObject *o, PythonRuntime* py) { +const value pyObjectToValue(PyObject* const o, PythonRuntime* const py) { if (o == NULL) - return value(); + return nilValue; if (PyString_Check(o)) { char* s = NULL; Py_ssize_t l = 0; @@ -622,8 +622,8 @@ const value pyObjectToValue(PyObject *o, PythonRuntime* py) { if (PyObject_TypeCheck(o, &pyLambda_type)) return *(((pyLambda*)o)->func); if (PyCallable_Check(o)) - return lambda<value(const list<value>&)>(pyCallable(o, py)); - return value(); + return lvvlambda(pyCallable(o, py)); + return nilValue; } /** @@ -636,37 +636,37 @@ const string moduleName(const string& path) { /** * Evaluate an expression against a script provided as a python object. */ -const failable<value> evalScript(const value& expr, PyObject* script, PythonRuntime& py) { +const failable<value> evalScript(const value& expr, PyObject* const script, PythonRuntime& py) { PythonThreadIn pyin(&py); // Get the requested function - PyObject* func = PyObject_GetAttrString(script, c_str(car<value>(expr))); + PyObject* const func = PyObject_GetAttrString(script, c_str(car<value>(expr))); if (func == NULL) { // The start, stop, and restart functions are optional const value fn = car<value>(expr); if (fn == "start" || fn == "stop") { PyErr_Clear(); - return value(lambda<value(const list<value>&)>()); + return value(lvvlambda()); } - return mkfailure<value>(string("Couldn't find function: ") + car<value>(expr) + " : " + lastError(&py)); + return mkfailure<value>(string("Couldn't find function: ") + (string)car<value>(expr) + " : " + lastError(&py)); } if (!PyCallable_Check(func)) { pyDecRef(func, &py); - return mkfailure<value>(string("Couldn't find callable function: ") + car<value>(expr)); + return mkfailure<value>(string("Couldn't find callable function: ") + (string)car<value>(expr)); } // Convert args to python objects - PyObject* args = valuesToPyTuple(cdr<value>(expr), &py); + PyObject* const args = valuesToPyTuple(cdr<value>(expr), &py); // Call the function - PyObject* result = PyObject_CallObject(func, args); + PyObject* const result = PyObject_CallObject(func, args); if (result == NULL) { const string msg = lastError(&py); pyDecRef(func, &py); pyDecRef(args, &py); - return mkfailure<value>(string("Function call failed: ") + car<value>(expr) + " : " + msg); + return mkfailure<value>(string("Function call failed: ") + (string)car<value>(expr) + " : " + msg); } pyDecRef(func, &py); pyDecRef(args, &py); @@ -684,8 +684,8 @@ const failable<PyObject*> readScript(const string& name, const string& path, ist PythonThreadIn pyin(&py); // Lookup already loaded module - PyObject *mods = PyImport_GetModuleDict(); - PyObject *emod = PyDict_GetItemString(mods, const_cast<char*>(c_str(name))); + PyObject* const mods = PyImport_GetModuleDict(); + PyObject* const emod = PyDict_GetItemString(mods, const_cast<char*>(c_str(name))); if (emod != NULL) return emod; @@ -695,10 +695,10 @@ const failable<PyObject*> readScript(const string& name, const string& path, ist const list<string> ls = streamList(is); ostringstream os; write(ls, os); - PyObject* code = Py_CompileStringFlags(c_str(str(os)), c_str(path), Py_file_input, NULL); + PyObject* const code = Py_CompileStringFlags(c_str(str(os)), c_str(path), Py_file_input, NULL); if (code == NULL) return mkfailure<PyObject*>(string("Couldn't compile script: ") + path + " : " + lastError(&py)); - PyObject* mod = PyImport_ExecCodeModuleEx(const_cast<char*>(c_str(name)), code, const_cast<char*>(c_str(path))); + PyObject* const mod = PyImport_ExecCodeModuleEx(const_cast<char*>(c_str(name)), code, const_cast<char*>(c_str(path))); if (mod == NULL) { const string msg = lastError(&py); pyDecRef(code, &py); @@ -708,7 +708,7 @@ const failable<PyObject*> readScript(const string& name, const string& path, ist pyDecRef(mod, &py); // Lookup the loaded module - PyObject *lmod = PyDict_GetItemString(mods, const_cast<char*>(c_str(name))); + PyObject* const lmod = PyDict_GetItemString(mods, const_cast<char*>(c_str(name))); if (lmod != NULL) return lmod; @@ -718,7 +718,7 @@ const failable<PyObject*> readScript(const string& name, const string& path, ist /** * Release a python script. */ -const failable<bool> releaseScript(unused PyObject* script, PythonRuntime& py) { +const failable<bool> releaseScript(unused PyObject* const script, PythonRuntime& py) { PythonThreadIn pyin(&py); // No need to decref the script here, as it's referenced only once from sys.modules return true; diff --git a/sca-cpp/trunk/modules/python/mod-python.cpp b/sca-cpp/trunk/modules/python/mod-python.cpp index 956edf1059..eaaeeb8e3e 100644 --- a/sca-cpp/trunk/modules/python/mod-python.cpp +++ b/sca-cpp/trunk/modules/python/mod-python.cpp @@ -40,42 +40,35 @@ namespace modeval { /** * Apply a lifecycle start or restart event. */ -struct pythonLifecycle { - python::PythonRuntime& py; - pythonLifecycle(python::PythonRuntime& py) : py(py) { - } - const value operator()(const list<value>& params) const { - const value func = car(params); - if (func == "pythonRuntime") - return (gc_ptr<value>)(value*)&py; - return lambda<value(const list<value>&)>(); - } -}; - const value applyLifecycle(unused const list<value>& params) { // Create a Python runtime python::PythonRuntime& py = *(new (gc_new<python::PythonRuntime>()) python::PythonRuntime()); // Return the function to invoke on subsequent events - return failable<value>(lambda<value(const list<value>&)>(pythonLifecycle(py))); + return failable<value>(lvvlambda([&py](const list<value>& params) -> const value { + const value func = car(params); + if (func == "pythonRuntime") + return (gc_ptr<value>)(value*)&py; + return lvvlambda(); + })); } /** * Evaluate a Python component implementation and convert it to an applicable * lambda function. */ -const failable<lambda<value(const list<value>&)> > evalImplementation(const string& path, const value& impl, const list<value>& px, const lambda<value(const list<value>&)>& lifecycle) { +const failable<lvvlambda > evalImplementation(const string& path, const value& impl, const list<value>& px, const lvvlambda& lifecycle) { const string itype(elementName(impl)); if (contains(itype, ".python")) { - const value* p = (gc_ptr<value>)lifecycle(mklist<value>("pythonRuntime")); + const value* const p = (gc_ptr<value>)lifecycle(mklist<value>("pythonRuntime")); return modpython::evalImplementation(path, impl, px, *(python::PythonRuntime*)p); } if (contains(itype, ".cpp")) return modcpp::evalImplementation(path, impl, px); if (contains(itype, ".widget")) - return mkfailure<lambda<value(const list<value>&)> >(string("Unsupported implementation type: ") + itype, -1, false); - return mkfailure<lambda<value(const list<value>&)> >(string("Unsupported implementation type: ") + itype); + return mkfailure<lvvlambda >(string("Unsupported implementation type: ") + itype, -1, false); + return mkfailure<lvvlambda >(string("Unsupported implementation type: ") + itype); } } diff --git a/sca-cpp/trunk/modules/python/mod-python.hpp b/sca-cpp/trunk/modules/python/mod-python.hpp index e6effb985b..00f2e4ab4e 100644 --- a/sca-cpp/trunk/modules/python/mod-python.hpp +++ b/sca-cpp/trunk/modules/python/mod-python.hpp @@ -40,38 +40,30 @@ namespace server { namespace modpython { /** - * Apply a Python component implementation function. - */ -struct applyImplementation { - PyObject* impl; - const list<value> px; - python::PythonRuntime& py; - applyImplementation(PyObject* impl, const list<value>& px, python::PythonRuntime& py) : impl(impl), px(px), py(py) { - } - const value operator()(const list<value>& params) const { - const value expr = append<value>(params, px); - debug(expr, "modeval::python::applyImplementation::input"); - const failable<value> res = python::evalScript(expr, impl, py); - const value val = !hasContent(res)? mklist<value>(value(), reason(res), rcode(res)) : mklist<value>(content(res)); - debug(val, "modeval::python::applyImplementation::result"); - return val; - } -}; - -/** * Evaluate a Python component implementation and convert it to an applicable * lambda function. */ -const failable<lambda<value(const list<value>&)> > evalImplementation(const string& path, const value& impl, const list<value>& px, python::PythonRuntime& py) { +const failable<lvvlambda > evalImplementation(const string& path, const value& impl, const list<value>& px, python::PythonRuntime& py) { const string spath(attributeValue("script", impl)); const string fpath(path + spath); ifstream is(fpath); if (fail(is)) - return mkfailure<lambda<value(const list<value>&)> >(string("Could not read implementation: ") + fpath); - const failable<PyObject*> script = python::readScript(python::moduleName(spath), fpath, is, py); - if (!hasContent(script)) - return mkfailure<lambda<value(const list<value>&)> >(script); - return lambda<value(const list<value>&)>(applyImplementation(content(script), px, py)); + return mkfailure<lvvlambda >(string("Could not read implementation: ") + fpath); + const failable<PyObject*> fscript = python::readScript(python::moduleName(spath), fpath, is, py); + if (!hasContent(fscript)) + return mkfailure<lvvlambda >(fscript); + PyObject* const script = content(fscript); + + const lvvlambda applyImplementation = [script, px, &py](const list<value>& params) -> const value { + // Apply a Python component implementation function + const value expr = append<value>(params, px); + debug(expr, "modeval::python::applyImplementation::input"); + const failable<value> res = python::evalScript(expr, script, py); + const value val = !hasContent(res)? mklist<value>(nilValue, reason(res), rcode(res)) : mklist<value>(content(res)); + debug(val, "modeval::python::applyImplementation::result"); + return val; + }; + return applyImplementation; } } diff --git a/sca-cpp/trunk/modules/python/python-shell.cpp b/sca-cpp/trunk/modules/python/python-shell.cpp index 89b47b8d44..7575ffa077 100644 --- a/sca-cpp/trunk/modules/python/python-shell.cpp +++ b/sca-cpp/trunk/modules/python/python-shell.cpp @@ -29,8 +29,8 @@ #include "string.hpp" #include "driver.hpp" -int main(const int argc, char** argv) { - tuscany::gc_scoped_pool pool; +int main(const int argc, const char** const argv) { + const tuscany::gc_scoped_pool pool; if (argc != 2) { tuscany::cerr << "Usage: python-shell <script.py>" << tuscany::endl; return 1; diff --git a/sca-cpp/trunk/modules/python/python-test.cpp b/sca-cpp/trunk/modules/python/python-test.cpp index 29a66cc2e7..44a72f8f88 100644 --- a/sca-cpp/trunk/modules/python/python-test.cpp +++ b/sca-cpp/trunk/modules/python/python-test.cpp @@ -37,12 +37,12 @@ const string testPythonAdd = "def add(x, y):\n" " return x + y\n"; -bool testEvalExpr() { - gc_scoped_pool pool; +const bool testEvalExpr() { + const gc_scoped_pool pool; PythonRuntime py; istringstream is(testPythonAdd); - failable<PyObject*> script = readScript("script1", "script1.py", is, py); + const failable<PyObject*> script = readScript("script1", "script1.py", is, py); assert(hasContent(script)); const value exp = mklist<value>("add", 2, 3); @@ -58,12 +58,12 @@ const string testPythonMap = "def addmap(x, y):\n" " return tuple(map(lambda i: i + y, x))\n"; -bool testEvalList() { - gc_scoped_pool pool; +const bool testEvalList() { + const gc_scoped_pool pool; PythonRuntime py; istringstream is(testPythonMap); - failable<PyObject*> script = readScript("script2", "script2.py", is, py); + const failable<PyObject*> script = readScript("script2", "script2.py", is, py); assert(hasContent(script)); const value exp = mklist<value>("addmap", mklist<value>(1, 2, 3), 1); @@ -94,8 +94,8 @@ const string testCallLambda( "def testCallLambda(l, x, y):\n" " return l(x, y)\n"); -bool testEvalLambda() { - gc_scoped_pool pool; +const bool testEvalLambda() { + const gc_scoped_pool pool; PythonRuntime py; const value trl = mklist<value>("testReturnLambda"); @@ -104,7 +104,7 @@ bool testEvalLambda() { assert(hasContent(trlv)); assert(isLambda(content(trlv))); - const lambda<value(const list<value>&)> trll(content(trlv)); + const lvvlambda trll(content(trlv)); assert(trll(mklist<value>(2, 3)) == value(6)); istringstream tclis(testCallLambda); @@ -114,20 +114,20 @@ bool testEvalLambda() { assert(content(tclv) == value(6)); istringstream tcelis(testCallLambda); - const value tcel = mklist<value>("testCallLambda", lambda<value(const list<value>&)>(mult), 3, 4); + const value tcel = mklist<value>("testCallLambda", lvvlambda(mult), 3, 4); const failable<value> tcelv = evalScript(tcel, tcelis, py); assert(hasContent(tcelv)); assert(content(tcelv) == value(12)); return true; } -struct testEvalReadAdd { - PythonRuntime& py; - testEvalReadAdd(PythonRuntime& py) : py(py) { - } - const bool operator()() const { +const bool testEvalPerf() { + const gc_scoped_pool pool; + PythonRuntime py; + + const blambda erl = [&py]() -> const bool { istringstream is(testPythonAdd); - failable<PyObject*> script = readScript("script3", "script3.py", is, py); + const failable<PyObject*> script = readScript("script3", "script3.py", is, py); assert(hasContent(script)); const value exp = mklist<value>("add", 2, 3); @@ -137,51 +137,36 @@ struct testEvalReadAdd { releaseScript(content(script), py); return true; - } -}; - -struct testEvalAdd { - PyObject* script; - PythonRuntime& py; - testEvalAdd(PyObject* script, PythonRuntime& py) : script(script), py(py) { - } - const bool operator()() const { + }; + cout << "Python read + eval test " << time(erl, 5, 10000) << " ms" << endl; + + istringstream is(testPythonAdd); + const failable<PyObject*> fscript = readScript("script4", "script4.py", is, py); + assert(hasContent(fscript)); + + PyObject* const script = content(fscript); + const blambda el = [script, &py]() -> const bool { const value exp = mklist<value>("add", 2, 3); const failable<value> r = evalScript(exp, script, py); assert(hasContent(r)); assert(content(r) == value(5)); return true; - } -}; - -bool testEvalPerf() { - gc_scoped_pool pool; - PythonRuntime py; - - const lambda<bool()> erl = lambda<bool()>(testEvalReadAdd(py)); - cout << "Python read + eval test " << time(erl, 5, 10000) << " ms" << endl; - - istringstream is(testPythonAdd); - failable<PyObject*> script = readScript("script4", "script4.py", is, py); - assert(hasContent(script)); - - const lambda<bool()> el = lambda<bool()>(testEvalAdd(content(script), py)); + }; cout << "Python eval test " << time(el, 5, 10000) << " ms" << endl; - releaseScript(content(script), py); + releaseScript(script, py); return true; } #ifdef WANT_THREADS -struct testReadEvalAddLoop { - PythonRuntime& py; - testReadEvalAddLoop(PythonRuntime& py) : py(py) { - } - const bool operator()() const { +const list<future<bool> > submitReadEvals(worker& w, const int max, const int i, PythonRuntime& py) { + if (i == max) + return list<future<bool> >(); + const blambda func = [&py]() -> const bool { for (int i = 0; i < 100; i++) { istringstream is(testPythonAdd); - failable<PyObject*> script = readScript("script6", "script6.py", is, py); + const failable<PyObject*> script = readScript("script6", "script6.py", is, py); assert(hasContent(script)); const value exp = mklist<value>("add", 2, 3); @@ -192,15 +177,14 @@ struct testReadEvalAddLoop { releaseScript(content(script), py); } return true; - } -}; - -struct testEvalAddLoop { - PyObject* script; - PythonRuntime& py; - testEvalAddLoop(PyObject* script, PythonRuntime& py) : script(script), py(py) { - } - const bool operator()() const { + }; + return cons(submit(w, func), submitReadEvals(w, max, i + 1, py)); +} + +const list<future<bool> > submitEvals(worker& w, const int max, const int i, PyObject* const script, PythonRuntime& py) { + if (i == max) + return list<future<bool> >(); + const blambda func = [script, &py]() -> const bool { for (int i = 0; i < 100; i++) { const value exp = mklist<value>("add", 2, 3); const failable<value> r = evalScript(exp, script, py); @@ -208,75 +192,44 @@ struct testEvalAddLoop { assert(content(r) == value(5)); } return true; - } -}; - -const list<future<bool> > submitReadEvals(worker& w, const int max, const int i, PythonRuntime& py) { - if (i == max) - return list<future<bool> >(); - const lambda<bool()> func = lambda<bool()>(testReadEvalAddLoop(py)); - return cons(submit(w, func), submitReadEvals(w, max, i + 1, py)); -} - -const list<future<bool> > submitEvals(worker& w, const int max, const int i, PyObject* script, PythonRuntime& py) { - if (i == max) - return list<future<bool> >(); - const lambda<bool()> func = lambda<bool()>(testEvalAddLoop(script, py)); + }; return cons(submit(w, func), submitEvals(w, max, i + 1, script, py)); } -bool checkEvalResults(const list<future<bool> > r) { +const bool checkEvalResults(const list<future<bool> > r) { if (isNil(r)) return true; assert(car(r) == true); return checkEvalResults(cdr(r)); } -struct testReadEvalThreads { - worker& w; - const int max; - PythonRuntime& py; - testReadEvalThreads(worker& w, const int max, PythonRuntime& py) : w(w), max(max), py(py) { - } - const bool operator()() const { - const list<future<bool> > r(submitReadEvals(w, max, 0, py)); - checkEvalResults(r); - return true; - } -}; - -struct testEvalThreads { - worker& w; - const int max; - PyObject* script; - PythonRuntime& py; - testEvalThreads(worker& w, const int max, PyObject* script, PythonRuntime& py) : w(w), max(max), script(script), py(py) { - } - const bool operator()() const { - const list<future<bool> > r(submitEvals(w, max, 0, script, py)); - checkEvalResults(r); - return true; - } -}; - -bool testThreads() { - gc_scoped_pool pool; +const bool testThreads() { + const gc_scoped_pool pool; PythonRuntime py; const int max = 100; worker w(max); - const lambda<bool()> elr = lambda<bool()>(testReadEvalThreads(w, max, py)); + const blambda elr = [&w, max, &py]() -> const bool { + const list<future<bool> > r(submitReadEvals(w, max, 0, py)); + checkEvalResults(r); + return true; + }; cout << "Python eval + read thread test " << time(elr, 1, 1) / 10000.0 << " ms" << endl; istringstream is(testPythonAdd); - failable<PyObject*> script = readScript("script7", "script7.py", is, py); - assert(hasContent(script)); + const failable<PyObject*> fscript = readScript("script7", "script7.py", is, py); + assert(hasContent(fscript)); - const lambda<bool()> el = lambda<bool()>(testEvalThreads(w, max, content(script), py)); + PyObject* const script = content(fscript); + const blambda el = [&w, max, script, &py]() -> const bool { + const list<future<bool> > r(submitEvals(w, max, 0, script, py)); + checkEvalResults(r); + return true; + }; cout << "Python eval thread test " << time(el, 1, 1) / 10000.0 << " ms" << endl; - releaseScript(content(script), py); + releaseScript(script, py); return true; } @@ -286,7 +239,7 @@ bool testThreads() { } int main() { - tuscany::gc_scoped_pool p; + const tuscany::gc_scoped_pool p; tuscany::cout << "Testing..." << tuscany::endl; tuscany::python::testEvalExpr(); diff --git a/sca-cpp/trunk/modules/server/Makefile.am b/sca-cpp/trunk/modules/server/Makefile.am index e2fd67d9b8..c5c19a5ba7 100644 --- a/sca-cpp/trunk/modules/server/Makefile.am +++ b/sca-cpp/trunk/modules/server/Makefile.am @@ -29,7 +29,7 @@ mod_LTLIBRARIES = libmod_tuscany_eval.la noinst_DATA = libmod_tuscany_eval${libsuffix} libmod_tuscany_eval_la_SOURCES = mod-eval.cpp -libmod_tuscany_eval_la_LDFLAGS = -lxml2 -lcurl -lmozjs +libmod_tuscany_eval_la_LDFLAGS = -lxml2 -lcurl -ljansson libmod_tuscany_eval${libsuffix}: ln -s .libs/libmod_tuscany_eval${libsuffix} @@ -42,7 +42,7 @@ libimpl-test${libsuffix}: ln -s .libs/libimpl-test${libsuffix} client_test_SOURCES = client-test.cpp -client_test_LDFLAGS = -lxml2 -lcurl -lmozjs +client_test_LDFLAGS = -lxml2 -lcurl -ljansson dist_noinst_SCRIPTS = httpd-test server-test wiring-test noinst_PROGRAMS = client-test diff --git a/sca-cpp/trunk/modules/server/client-test.hpp b/sca-cpp/trunk/modules/server/client-test.hpp index 1c7b26da39..dc9ca299ad 100644 --- a/sca-cpp/trunk/modules/server/client-test.hpp +++ b/sca-cpp/trunk/modules/server/client-test.hpp @@ -36,7 +36,8 @@ namespace tuscany { namespace server { -string testURI = "http://localhost:8090/scheme"; +gc_mutable_ref<string> testURI = string("http://localhost:8090/scheme"); + bool testBlobs = true; ostream* curlWriter(const string& s, ostream* os) { @@ -45,8 +46,8 @@ ostream* curlWriter(const string& s, ostream* os) { } const bool testGet() { - gc_scoped_pool pool; - http::CURLSession ch("", "", "", "", 0); + const gc_scoped_pool pool; + const http::CURLSession ch("", "", "", "", 0); { ostringstream os; const failable<list<ostream*> > r = http::get<ostream*>(curlWriter, &os, "http://localhost:8090/index.html", ch); @@ -62,160 +63,127 @@ const bool testGet() { return true; } -struct getLoop { - http::CURLSession& ch; - getLoop(http::CURLSession& ch) : ch(ch) { - } - const bool operator()() const { +const bool testGetPerf() { + const gc_scoped_pool pool; + const http::CURLSession ch("", "", "", "", 0); + const blambda gl = [ch]() -> const bool { const failable<value> r = http::getcontent("http://localhost:8090/index.html", ch); assert(hasContent(r)); assert(contains(car(reverse(list<value>(content(r)))), "It works")); return true; - } -}; - -const bool testGetPerf() { - gc_scoped_pool pool; - http::CURLSession ch("", "", "", "", 0); - const lambda<bool()> gl = getLoop(ch); + }; cout << "Static GET test " << time(gl, 5, 200) << " ms" << endl; return true; } const bool testEval() { - gc_scoped_pool pool; - http::CURLSession ch("", "", "", "", 0); + const gc_scoped_pool pool; + const http::CURLSession ch("", "", "", "", 0); const failable<value> r = http::evalExpr(mklist<value>(string("echo"), string("Hello")), testURI, ch); assert(hasContent(r)); assert(content(r) == string("Hello")); return true; } -struct evalLoop { - const string uri; - http::CURLSession& ch; - evalLoop(const string& uri, http::CURLSession& ch) : uri(uri), ch(ch) { - } - const bool operator()() const { - const failable<value> r = http::evalExpr(mklist<value>(string("echo"), string("Hello")), uri, ch); - assert(hasContent(r)); - assert(content(r) == string("Hello")); - return true; - } -}; - const value blob(string(2048, 'A')); const list<value> blobs = mklist(blob, blob); -struct blobEvalLoop { - const string uri; - http::CURLSession& ch; - blobEvalLoop(const string& uri, http::CURLSession& ch) : uri(uri), ch(ch) { - } - const bool operator()() const { - const failable<value> r = content(http::evalExpr(mklist<value>(string("echo"), blobs), uri, ch)); +const bool testEvalPerf() { + const gc_scoped_pool pool; + const http::CURLSession ch("", "", "", "", 0); + const blambda el = [ch]() -> const bool { + const failable<value> r = http::evalExpr(mklist<value>(string("echo"), string("Hello")), testURI, ch); assert(hasContent(r)); - assert(content(r) == blobs); + assert(content(r) == string("Hello")); return true; - } -}; - -const bool testEvalPerf() { - gc_scoped_pool pool; - http::CURLSession ch("", "", "", "", 0); - const lambda<bool()> el = evalLoop(testURI, ch); + }; cout << "JSON-RPC eval echo test " << time(el, 5, 200) << " ms" << endl; if (testBlobs) { - const lambda<bool()> bel = blobEvalLoop(testURI, ch); + const blambda bel = [ch]() -> const bool { + const failable<value> r = content(http::evalExpr(mklist<value>(string("echo"), blobs), testURI, ch)); + assert(hasContent(r)); + assert(content(r) == blobs); + return true; + }; cout << "JSON-RPC eval blob test " << time(bel, 5, 200) << " ms" << endl; } return true; } -bool testPost() { - gc_scoped_pool pool; - const list<value> i = list<value>() + "content" + (list<value>() + "item" - + (list<value>() + "name" + string("Apple")) - + (list<value>() + "price" + string("$2.99"))); - const list<value> a = list<value>() + (list<value>() + "entry" - + (list<value>() + "title" + string("item")) - + (list<value>() + "id" + string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b")) +const bool testPost() { + const gc_scoped_pool pool; + const list<value> i = nilListValue + "content" + (nilListValue + "item" + + (nilListValue + "name" + string("Apple")) + + (nilListValue + "price" + string("$2.99"))); + const list<value> a = nilListValue + (nilListValue + "entry" + + (nilListValue + "title" + string("item")) + + (nilListValue + "id" + string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b")) + i); - http::CURLSession ch("", "", "", "", 0); + const http::CURLSession ch("", "", "", "", 0); const failable<value> id = http::post(a, testURI, ch); assert(hasContent(id)); return true; } -struct postLoop { - const string uri; - const value val; - http::CURLSession& ch; - postLoop(const string& uri, const value& val, http::CURLSession& ch) : uri(uri), val(val), ch(ch) { - } - const bool operator()() const { - const failable<value> id = http::post(val, uri, ch); - assert(hasContent(id)); - return true; - } -}; - -struct postBlobLoop { - const string uri; - const value val; - http::CURLSession& ch; - postBlobLoop(const string& uri, const value& val, http::CURLSession& ch) : uri(uri), val(val), ch(ch) { - } - const bool operator()() const { - gc_scoped_pool pool; - const failable<value> id = http::post(val, uri, ch); - assert(hasContent(id)); - return true; - } -}; - const bool testPostPerf() { - gc_scoped_pool pool; - http::CURLSession ch("", "", "", "", 0); + const gc_scoped_pool pool; + const http::CURLSession ch("", "", "", "", 0); { - const list<value> i = list<value>() + "content" + (list<value>() + "item" - + (list<value>() + "name" + string("Apple")) - + (list<value>() + "price" + string("$2.99"))); - const list<value> val = list<value>() + (list<value>() + "entry" - + (list<value>() + "title" + string("item")) - + (list<value>() + "id" + string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b")) + const list<value> i = nilListValue + "content" + (nilListValue + "item" + + (nilListValue + "name" + string("Apple")) + + (nilListValue + "price" + string("$2.99"))); + const list<value> val = nilListValue + (nilListValue + "entry" + + (nilListValue + "title" + string("item")) + + (nilListValue + "id" + string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b")) + i); - const lambda<bool()> pl = postLoop(testURI, val, ch); + const blambda pl = [val, ch]() -> const bool { + const failable<value> id = http::post(val, testURI, ch); + assert(hasContent(id)); + return true; + }; cout << "ATOMPub POST small test " << time(pl, 5, 200) << " ms" << endl; } if (testBlobs) { - const list<value> i = list<value>() + "content" + (list<value>() + "item" - + (list<value>() + "name" + string("Apple")) - + (list<value>() + "blob1" + blob) - + (list<value>() + "blob2" + blob) - + (list<value>() + "price" + string("$2.99"))); - const list<value> val = list<value>() + (list<value>() + "entry" - + (list<value>() + "title" + string("item")) - + (list<value>() + "id" + string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b")) + const list<value> i = nilListValue + "content" + (nilListValue + "item" + + (nilListValue + "name" + string("Apple")) + + (nilListValue + "blob1" + blob) + + (nilListValue + "blob2" + blob) + + (nilListValue + "price" + string("$2.99"))); + const list<value> val = nilListValue + (nilListValue + "entry" + + (nilListValue + "title" + string("item")) + + (nilListValue + "id" + string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b")) + i); - const lambda<bool()> pl = postBlobLoop(testURI, val, ch); + const blambda pl = [val, ch]() -> const bool { + const gc_scoped_pool pool; + const failable<value> id = http::post(val, testURI, ch); + assert(hasContent(id)); + return true; + }; cout << "ATOMPub POST blob test " << time(pl, 5, 200) << " ms" << endl; } return true; } +const blambda mkpostLoop(const string& uri, const value& val, const http::CURLSession& ch) { + return [uri, val, ch]() -> const bool { + const failable<value> id = http::post(val, uri, ch); + assert(hasContent(id)); + return true; + }; +} + #ifdef WANT_THREADS const bool postThread(const string& uri, const int count, const value& val) { - gc_scoped_pool pool; - http::CURLSession ch("", "", "", "", 0); - const lambda<bool()> pl = postLoop(uri, val, ch); + const gc_scoped_pool pool; + const http::CURLSession ch("", "", "", "", 0); + const blambda pl = mkpostLoop(uri, val, ch); time(pl, 0, count); return true; } -const list<future<bool> > startPost(worker& w, const int threads, const lambda<bool()>& l) { +const list<future<bool> > startPost(worker& w, const int threads, const blambda& l) { if (threads == 0) return list<future<bool> >(); return cons(submit(w, l), startPost(w, threads - 1, l)); @@ -228,36 +196,27 @@ const bool checkPost(const list<future<bool> >& r) { return checkPost(cdr(r)); } -struct postThreadLoop { - const lambda<bool()> l; - worker& w; - const int threads; - postThreadLoop(const lambda<bool()>& l, worker& w, const int threads) : l(l), w(w), threads(threads) { - } - const bool operator()() const { - list<future<bool> > r = startPost(w, threads, l); - checkPost(r); - return true; - } -}; - const bool testPostThreadPerf() { - gc_scoped_pool pool; + const gc_scoped_pool pool; const int count = 50; const int threads = 10; worker w(threads); - const list<value> i = list<value>() + "content" + (list<value>() + "item" - + (list<value>() + "name" + string("Apple")) - + (list<value>() + "price" + string("$2.99"))); - const value val = list<value>() + (list<value>() + "entry" - + (list<value>() + "title" + string("item")) - + (list<value>() + "id" + string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b")) + const list<value> i = nilListValue + "content" + (nilListValue + "item" + + (nilListValue + "name" + string("Apple")) + + (nilListValue + "price" + string("$2.99"))); + const value val = nilListValue + (nilListValue + "entry" + + (nilListValue + "title" + string("item")) + + (nilListValue + "id" + string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b")) + i); - const lambda<bool()> pl= curry(lambda<bool(const string, const int, const value)>(postThread), testURI, count, val); - const lambda<bool()> ptl = postThreadLoop(pl, w, threads); - double t = time(ptl, 0, 1) / (threads * count); + const blambda pl= curry(lambda<const bool(const string, const int, const value)>(postThread), (const string)testURI, count, val); + const blambda ptl = [pl, &w, threads]() -> const bool { + list<future<bool> > r = startPost(w, threads, pl); + checkPost(r); + return true; + }; + const double t = time(ptl, 0, 1) / (threads * count); cout << "ATOMPub POST thread test " << t << " ms" << endl; return true; @@ -266,17 +225,17 @@ const bool testPostThreadPerf() { #else const bool postProc(const string& uri, const int count, const value& val) { - gc_scoped_pool pool; - http::CURLSession ch("", "", "", "", 0); - const lambda<bool()> pl = postLoop(uri, val, ch); + const gc_scoped_pool pool; + const http::CURLSession ch("", "", "", "", 0); + const blambda pl = mkpostLoop(uri, val, ch); time(pl, 0, count); return true; } -const list<pid_t> startPost(const int procs, const lambda<bool()>& l) { +const list<pid_t> startPost(const int procs, const blambda& l) { if (procs == 0) return list<pid_t>(); - pid_t pid = fork(); + const pid_t pid = fork(); if (pid == 0) { assert(l() == true); exit(0); @@ -293,34 +252,26 @@ const bool checkPost(const list<pid_t>& r) { return checkPost(cdr(r)); } -struct postForkLoop { - const lambda<bool()> l; - const int procs; - postForkLoop(const lambda<bool()>& l, const int procs) : l(l), procs(procs) { - } - const bool operator()() const { - list<pid_t> r = startPost(procs, l); - checkPost(r); - return true; - } -}; - const bool testPostForkPerf() { - gc_scoped_pool pool; + const gc_scoped_pool pool; const int count = 50; const int procs = 10; - const list<value> i = list<value>() + "content" + (list<value>() + "item" - + (list<value>() + "name" + string("Apple")) - + (list<value>() + "price" + string("$2.99"))); - const value val = list<value>() + (list<value>() + "entry" - + (list<value>() + "title" + string("item")) - + (list<value>() + "id" + string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b")) + const list<value> i = nilListValue + "content" + (nilListValue + "item" + + (nilListValue + "name" + string("Apple")) + + (nilListValue + "price" + string("$2.99"))); + const value val = nilListValue + (nilListValue + "entry" + + (nilListValue + "title" + string("item")) + + (nilListValue + "id" + string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b")) + i); - const lambda<bool()> pl= curry(lambda<bool(const string, const int, const value)>(postProc), testURI, count, val); - const lambda<bool()> ptl = postForkLoop(pl, procs); - double t = time(ptl, 0, 1) / (procs * count); + const blambda pl= curry(lambda<const bool(const string, const int, const value)>(postProc), testURI, count, val); + const blambda ptl = [pl, procs]() -> const bool { + list<pid_t> r = startPost(procs, l); + checkPost(r); + return true; + }; + const double t = time(ptl, 0, 1) / (procs * count); cout << "ATOMPub POST fork test " << t << " ms" << endl; return true; @@ -329,25 +280,25 @@ const bool testPostForkPerf() { #endif const bool testPut() { - gc_scoped_pool pool; - const list<value> i = list<value>() + "content" + (list<value>() + "item" - + (list<value>() + "name" + string("Apple")) - + (list<value>() + "price" + string("$2.99"))); - const list<value> a = list<value>() + (list<value>() + "entry" - + (list<value>() + "title" + string("item")) - + (list<value>() + "id" + string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b")) + const gc_scoped_pool pool; + const list<value> i = nilListValue + "content" + (nilListValue + "item" + + (nilListValue + "name" + string("Apple")) + + (nilListValue + "price" + string("$2.99"))); + const list<value> a = nilListValue + (nilListValue + "entry" + + (nilListValue + "title" + string("item")) + + (nilListValue + "id" + string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b")) + i); - http::CURLSession ch("", "", "", "", 0); - value rc = content(http::put(a, testURI + "/111", ch)); - assert(rc == value(true)); + const http::CURLSession ch("", "", "", "", 0); + const value rc = content(http::put(a, testURI + "/111", ch)); + assert(rc == trueValue); return true; } const bool testDel() { - gc_scoped_pool pool; - http::CURLSession ch("", "", "", "", 0); - value rc = content(http::del(testURI + "/111", ch)); - assert(rc == value(true)); + const gc_scoped_pool pool; + const http::CURLSession ch("", "", "", "", 0); + const value rc = content(http::del(testURI + "/111", ch)); + assert(rc == trueValue); return true; } diff --git a/sca-cpp/trunk/modules/server/htdocs/test/entry.xml b/sca-cpp/trunk/modules/server/htdocs/test/entry.xml index 46053c3138..6528c793e3 100644 --- a/sca-cpp/trunk/modules/server/htdocs/test/entry.xml +++ b/sca-cpp/trunk/modules/server/htdocs/test/entry.xml @@ -1,14 +1,2 @@ <?xml version="1.0" encoding="UTF-8"?> -<entry xmlns="http://www.w3.org/2005/Atom"> - <title type="text">Item</title> - <id>111</id> - <content type="application/xml"> - <item> - <name>Apple</name> - <currencyCode>USD</currencyCode> - <currencySymbol>$</currencySymbol> - <price>2.99</price> - </item> - </content> - <link href="111"/> -</entry> +<entry xmlns="http://www.w3.org/2005/Atom"><title type="text">Item</title><id>111</id><content type="application/xml"><item><name>Apple</name><currencyCode>USD</currencyCode><currencySymbol>$</currencySymbol><price>2.99</price></item></content><link href="111"/></entry> diff --git a/sca-cpp/trunk/modules/server/htdocs/test/feed.xml b/sca-cpp/trunk/modules/server/htdocs/test/feed.xml index 337320e4c5..bcb304f9c2 100644 --- a/sca-cpp/trunk/modules/server/htdocs/test/feed.xml +++ b/sca-cpp/trunk/modules/server/htdocs/test/feed.xml @@ -1,44 +1,2 @@ <?xml version="1.0" encoding="UTF-8"?> -<feed xmlns="http://www.w3.org/2005/Atom"> - <title type="text">Sample Feed</title> - <id>123456789</id> - <entry xmlns="http://www.w3.org/2005/Atom"> - <title type="text">Item</title> - <id>111</id> - <content type="application/xml"> - <item> - <name>Apple</name> - <currencyCode>USD</currencyCode> - <currencySymbol>$</currencySymbol> - <price>2.99</price> - </item> - </content> - <link href="111"/> - </entry> - <entry xmlns="http://www.w3.org/2005/Atom"> - <title type="text">Item</title> - <id>222</id> - <content type="application/xml"> - <item> - <name>Orange</name> - <currencyCode>USD</currencyCode> - <currencySymbol>$</currencySymbol> - <price>3.55</price> - </item> - </content> - <link href="222"/> - </entry> - <entry xmlns="http://www.w3.org/2005/Atom"> - <title type="text">Item</title> - <id>333</id> - <content type="application/xml"> - <item> - <name>Pear</name> - <currencyCode>USD</currencyCode> - <currencySymbol>$</currencySymbol> - <price>1.55</price> - </item> - </content> - <link href="333"/> - </entry> -</feed> +<feed xmlns="http://www.w3.org/2005/Atom"><title type="text">Sample Feed</title><id>123456789</id><entry xmlns="http://www.w3.org/2005/Atom"><title type="text">Item</title><id>111</id><content type="application/xml"><item><name>Apple</name><currencyCode>USD</currencyCode><currencySymbol>$</currencySymbol><price>2.99</price></item></content><link href="111"/></entry><entry xmlns="http://www.w3.org/2005/Atom"><title type="text">Item</title><id>222</id><content type="application/xml"><item><name>Orange</name><currencyCode>USD</currencyCode><currencySymbol>$</currencySymbol><price>3.55</price></item></content><link href="222"/></entry><entry xmlns="http://www.w3.org/2005/Atom"><title type="text">Item</title><id>333</id><content type="application/xml"><item><name>Pear</name><currencyCode>USD</currencyCode><currencySymbol>$</currencySymbol><price>1.55</price></item></content><link href="333"/></entry></feed> diff --git a/sca-cpp/trunk/modules/server/htdocs/test/json-properties.txt b/sca-cpp/trunk/modules/server/htdocs/test/json-properties.txt index 2cff8b7339..09809a10df 100644 --- a/sca-cpp/trunk/modules/server/htdocs/test/json-properties.txt +++ b/sca-cpp/trunk/modules/server/htdocs/test/json-properties.txt @@ -1,14 +1 @@ -{ - "id": "1", - "result": { - "host": "localhost", - "path": [ - "c", - "property-test" - ], - "query": { - "id": "1", - "method": "print" - } - } -}
\ No newline at end of file +{"id":"1","result":{"host":"localhost","path":["c","property-test"],"query":{"id":"1","method":"print"}}}
\ No newline at end of file diff --git a/sca-cpp/trunk/modules/server/htdocs/test/json-result.txt b/sca-cpp/trunk/modules/server/htdocs/test/json-result.txt index 72b27b67db..121bf74902 100644 --- a/sca-cpp/trunk/modules/server/htdocs/test/json-result.txt +++ b/sca-cpp/trunk/modules/server/htdocs/test/json-result.txt @@ -1,4 +1 @@ -{ - "id": 1, - "result": "Hello" -}
\ No newline at end of file +{"id":1,"result":"Hello"}
\ No newline at end of file diff --git a/sca-cpp/trunk/modules/server/impl-test.cpp b/sca-cpp/trunk/modules/server/impl-test.cpp index 1bd0843745..a9bd9ad585 100644 --- a/sca-cpp/trunk/modules/server/impl-test.cpp +++ b/sca-cpp/trunk/modules/server/impl-test.cpp @@ -42,11 +42,11 @@ const failable<value> post(unused const list<value>& params) { } const failable<value> put(unused const list<value>& params) { - return value(true); + return trueValue; } const failable<value> del(unused const list<value>& params) { - return value(true); + return trueValue; } const failable<value> echo(const list<value>& params) { diff --git a/sca-cpp/trunk/modules/server/mod-cpp.hpp b/sca-cpp/trunk/modules/server/mod-cpp.hpp index 8cae35e493..1321466383 100644 --- a/sca-cpp/trunk/modules/server/mod-cpp.hpp +++ b/sca-cpp/trunk/modules/server/mod-cpp.hpp @@ -54,47 +54,38 @@ const list<value> failableResult(const value& func, const list<value>& v) { const value reason = cadr(v); if (length(reason) == 0) { if (func == "start" || func == "stop") - return mklist<value>(lambda<value(const list<value>&)>()); - return mklist<value>(value(), string("Function not supported: ") + func); + return mklist<value>(lvvlambda()); + return mklist<value>(nilValue, string("Function not supported: ") + (string)func); } return v; } -struct applyImplementation { - const lib ilib; - const lambda<value(const list<value>&)> impl; - const list<value> px; - - applyImplementation(const lib& ilib, const lambda<value(const list<value>&)>& impl, const list<value>& px) : ilib(ilib), impl(impl), px(px) { - } - - const value operator()(const list<value>& params) const { - debug(params, "modeval::cpp::applyImplementation::input"); - - // Apply the component implementation function - const value val = failableResult(car(params), impl(append(params, px))); - - debug(val, "modeval::cpp::applyImplementation::result"); - return val; - } -}; - /** * Evaluate a C++ component implementation and convert it to * an applicable lambda function. */ -const failable<lambda<value(const list<value>&)> > evalImplementation(const string& path, const value& impl, const list<value>& px) { +const failable<lvvlambda > evalImplementation(const string& path, const value& impl, const list<value>& px) { // Configure the implementation's lambda function const value ipath(attributeValue("path", impl)); const value iname(attributeValue("library", impl)); - const string fpath(isNil(ipath)? path + iname : path + ipath + "/" + iname); + const string fpath(isNil(ipath)? path + (string)iname : path + (string)ipath + "/" + (string)iname); const lib ilib(*(new (gc_new<lib>()) lib(fpath + dynlibExt))); - const failable<lambda<value(const list<value>&)> > evalf(dynlambda<value(const list<value>&)>("apply", ilib)); - if (!hasContent(evalf)) - return evalf; - const lambda<value(const list<value>&)> l(applyImplementation(ilib, content(evalf), px)); - return l; + const failable<lvvlambda > fappl(dynlambda<const value(const list<value>&)>("apply", ilib)); + if (!hasContent(fappl)) + return fappl; + const lvvlambda appl = content(fappl); + + const lvvlambda applyImplementation = [ilib, appl, px](const list<value>& params) -> const value { + debug(params, "modeval::cpp::applyImplementation::params"); + + // Apply the component implementation function + const value val = failableResult(car(params), appl(append(params, px))); + + debug(val, "modeval::cpp::applyImplementation::result"); + return val; + }; + return applyImplementation; } } diff --git a/sca-cpp/trunk/modules/server/mod-eval.cpp b/sca-cpp/trunk/modules/server/mod-eval.cpp index 3fd69c1fea..9b28f3df67 100644 --- a/sca-cpp/trunk/modules/server/mod-eval.cpp +++ b/sca-cpp/trunk/modules/server/mod-eval.cpp @@ -42,22 +42,22 @@ namespace modeval { */ const value applyLifecycle(unused const list<value>& params) { // Return a nil function as we don't need to handle any subsequent events - return failable<value>(lambda<value(const list<value>&)>()); + return failable<value>(lvvlambda()); } /** * Evaluate a Scheme or C++ component implementation and convert it to an * applicable lambda function. */ -const failable<lambda<value(const list<value>&)> > evalImplementation(const string& path, const value& impl, const list<value>& px, unused const lambda<value(const list<value>&)>& lifecycle) { +const failable<lvvlambda > evalImplementation(const string& path, const value& impl, const list<value>& px, unused const lvvlambda& lifecycle) { const string itype(elementName(impl)); if (contains(itype, ".scheme")) return modscheme::evalImplementation(path, impl, px); if (contains(itype, ".cpp")) return modcpp::evalImplementation(path, impl, px); if (contains(itype, ".widget")) - return mkfailure<lambda<value(const list<value>&)> >(string("Unsupported implementation type: ") + itype, -1, false); - return mkfailure<lambda<value(const list<value>&)> >(string("Unsupported implementation type: ") + itype); + return mkfailure<lvvlambda >(string("Unsupported implementation type: ") + itype, -1, false); + return mkfailure<lvvlambda >(string("Unsupported implementation type: ") + itype); } } diff --git a/sca-cpp/trunk/modules/server/mod-eval.hpp b/sca-cpp/trunk/modules/server/mod-eval.hpp index ee99baa039..aa13584534 100644 --- a/sca-cpp/trunk/modules/server/mod-eval.hpp +++ b/sca-cpp/trunk/modules/server/mod-eval.hpp @@ -63,9 +63,9 @@ public: SSLConf() { } - string ca; - string cert; - string key; + gc_mutable_ref<string> ca; + gc_mutable_ref<string> cert; + gc_mutable_ref<string> key; }; /** @@ -76,13 +76,13 @@ public: VhostConf() { } - string domain; - string contribPath; - string composName; - string contributorName; - value contributor; - string authenticatorName; - value authenticator; + gc_mutable_ref<string> domain; + gc_mutable_ref<string> contribPath; + gc_mutable_ref<string> composName; + gc_mutable_ref<string> contributorName; + gc_mutable_ref<value> contributor; + gc_mutable_ref<string> authenticatorName; + gc_mutable_ref<value> authenticator; }; /** @@ -93,8 +93,8 @@ public: ContribConf() { } - string contribPath; - string composName; + gc_mutable_ref<string> contribPath; + gc_mutable_ref<string> composName; }; /** @@ -108,9 +108,9 @@ public: Composite(const list<value>& refs, const list<value>& svcs, const list<value>& impls) : refs(refs), svcs(svcs), impls(impls) { } - list<value> refs; - list<value> svcs; - list<value> impls; + gc_mutable_ref<list<value> > refs; + gc_mutable_ref<list<value> > svcs; + gc_mutable_ref<list<value> > impls; }; /** @@ -121,12 +121,12 @@ public: ServerConf() { } - ServerConf(apr_pool_t* p, const server_rec* s) : p(p), server(s), timeout(0) { + ServerConf(apr_pool_t* const p, const server_rec* s) : p(p), server(s), timeout(0) { } const gc_pool p; const server_rec* server; - lambda<value(const list<value>&)> lifecycle; + gc_mutable_ref<value> lifecycle; ContribConf contribc; SSLConf sslc; int timeout; @@ -139,16 +139,16 @@ public: */ class RequestConf { public: - RequestConf(apr_pool_t* p, const request_rec* r) : p(p), request(r), vhost(false), valias(false) { + RequestConf(apr_pool_t* const p, const request_rec* r) : p(p), request(r), vhost(false), valias(false) { } const gc_pool p; const request_rec* request; bool vhost; bool valias; - list<value> rpath; - list<value> vpath; - list<value> impls; + gc_mutable_ref<list<value> > rpath; + gc_mutable_ref<list<value> > vpath; + gc_mutable_ref<list<value> > impls; }; /** @@ -170,14 +170,14 @@ const failable<value> failableResult(const list<value>& v) { * Store current HTTP request for access from property and proxy lambda functions. */ #ifdef WANT_THREADS -perthread_ptr<request_rec> currentRequest; +const perthread_ptr<request_rec> currentRequest; #else request_rec* currentRequest = NULL; #endif class ScopedRequest { public: - ScopedRequest(request_rec* r) { + ScopedRequest(request_rec* const r) { currentRequest = r; } @@ -189,9 +189,9 @@ public: /** * Make an HTTP proxy lambda to an absolute URI */ -const value mkhttpProxy(const string& uri, const int timeout, const gc_pool& p) { +const value mkhttpProxy(const string& uri, const int timeout) { debug(uri, "modeval::mkhttpProxy::uri"); - return lambda<value(const list<value>&)>(http::proxy(uri, "", "", "", "", timeout, p)); + return lvvlambda(http::proxy(uri, emptyString, emptyString, emptyString, emptyString, timeout)); } /** @@ -199,24 +199,24 @@ const value mkhttpProxy(const string& uri, const int timeout, const gc_pool& p) */ class implProxy { public: - implProxy(const value& name, const list<value>& impls, const SSLConf& sslc, const int timeout) : name(name), impls(impls), sslc(sslc), timeout(timeout) { + implProxy(const value& name, const gc_mutable_ref<list<value> >& impls, const SSLConf& sslc, const int timeout) : name(name), impls(impls), sslc(sslc), timeout(timeout) { } const value callImpl(const value& cname, const list<value>& aparams) const { - //debug(impls, "modeval::implProxy::callImpl::impls"); + debug(impls, "modeval::implProxy::callImpl::impls"); // Lookup the component implementation - const list<value> impl(assoctree<value>(cname, impls)); + const list<value> impl(assoctree<value>(cname, (list<value>)impls)); if (isNil(impl)) - return mkfailure<value>(string("Couldn't find component implementation: ") + cname); + return mkfailure<value>(string("Couldn't find component implementation: ") + (string)cname); // Call its lambda function - const lambda<value(const list<value>&)> l(cadr<value>(impl)); + const lvvlambda l(cadr<value>(impl)); const value func = c_str(car(aparams)); const failable<value> val = failableResult(l(cons(func, cdr(aparams)))); debug(val, "modeval::implProxy::result"); if (!hasContent(val)) - return value(); + return nilValue; return content(val); } @@ -233,7 +233,7 @@ public: // Use an HTTP proxy if the target is an absolute :// target if (http::isAbsolute(uri)) { - gc_pool p(currentRequest->pool); + const gc_pool p(currentRequest->pool); // Interpret a uri in the form app://appname, convert it using the scheme, // top level domain and port number from the current request @@ -241,7 +241,7 @@ public: ostringstream appuri; appuri << httpd::scheme(currentRequest) << "://" << substr(uri, 6) << "." << http::topDomain(httpd::hostName(currentRequest)) << ":" << httpd::port(currentRequest) << "/"; debug(str(appuri), "modeval::implProxy::httpproxy::appuri"); - const lambda<value(const list<value>&)> px = lambda<value(const list<value>&)>(http::proxy(str(appuri), sslc.ca, sslc.cert, sslc.key, httpd::cookie(currentRequest), timeout, p)); + const lvvlambda px = lvvlambda(http::proxy(str(appuri), sslc.ca, sslc.cert, sslc.key, httpd::cookie(currentRequest), timeout)); return px(aparams); } @@ -249,13 +249,13 @@ public: // only if the target is in the same top level domain if (http::topDomain(http::hostName(uri, p)) == http::topDomain(httpd::hostName(currentRequest))) { debug(uri, "modeval::implProxy::httpproxy::samedomain"); - const lambda<value(const list<value>&)> px = lambda<value(const list<value>&)>(http::proxy(uri, sslc.ca, sslc.cert, sslc.key, httpd::cookie(currentRequest), timeout, p)); + const lvvlambda px = lvvlambda(http::proxy(uri, sslc.ca, sslc.cert, sslc.key, httpd::cookie(currentRequest), timeout)); return px(aparams); } // No SSL certificate or cookie on a cross domain call debug(uri, "modeval::implProxy::httpproxy::crossdomain"); - const lambda<value(const list<value>&)> px = lambda<value(const list<value>&)>(http::proxy(uri, "", "", "", "", timeout, p)); + const lvvlambda px = lvvlambda(http::proxy(uri, emptyString, emptyString, emptyString, emptyString, timeout)); return px(aparams); } @@ -269,54 +269,41 @@ public: private: const value name; - const list<value>& impls; + const gc_mutable_ref<list<value> >& impls; const SSLConf& sslc; const int timeout; }; -const value mkimplProxy(const value& name, const list<value>& impls, const SSLConf& sslc, const int timeout) { +const value mkimplProxy(const value& name, const gc_mutable_ref<list<value> >& impls, const SSLConf& sslc, const int timeout) { debug(name, "modeval::implProxy::impl"); - return lambda<value(const list<value>&)>(implProxy(name, impls, sslc, timeout)); + return lvvlambda(implProxy(name, impls, sslc, timeout)); } /** * Return a proxy lambda for an unwired reference. */ -class unwiredProxy { -public: - unwiredProxy(const value& name) : name(name) { - } - - const value operator()(const list<value>& params) const { +const value mkunwiredProxy(const string& name) { + debug(name, "modeval::mkunwiredProxy::name"); + const lvvlambda unwiredProxy = [name](const list<value>& params) -> const value { debug(name, "modeval::unwiredProxy::name"); - debug(params, "modeval::unwiredProxy::input"); + debug(params, "modeval::unwiredProxy::params"); // Get function returns a default empty value if (car(params) == "get") { - debug(value(), "modeval::unwiredProxy::result"); - return value(); + debug(nilValue, "modeval::unwiredProxy::result"); + return nilValue; } // All other functions return a failure return mkfailure<value>(string("Reference is not wired: ") + name); - } - -private: - const value name; -}; - -/** - * Make a proxy lambda for an unwired reference. - */ -const value mkunwiredProxy(const string& ref) { - debug(ref, "modeval::mkunwiredProxy::ref"); - return lambda<value(const list<value>&)>(unwiredProxy(ref)); + }; + return unwiredProxy; } /** * Convert a list of component references to a list of proxy lambdas. */ -const value mkrefProxy(const value& ref, const list<value>& impls, const SSLConf& sslc, const int timeout, const gc_pool& p) { +const value mkrefProxy(const value& ref, const gc_mutable_ref<list<value> >& impls, const SSLConf& sslc, const int timeout) { const value target = scdl::target(ref); const bool wbyimpl = scdl::wiredByImpl(ref); debug(ref, "modeval::mkrefProxy::ref"); @@ -325,18 +312,18 @@ const value mkrefProxy(const value& ref, const list<value>& impls, const SSLConf // Use an HTTP proxy or an internal proxy to the component implementation if (wbyimpl) - return mkimplProxy(value(), impls, sslc, timeout); + return mkimplProxy(nilValue, impls, sslc, timeout); if (isNil(target)) return mkunwiredProxy(scdl::name(ref)); if (http::isAbsolute(target)) - return mkhttpProxy(target, timeout, p); + return mkhttpProxy(target, timeout); return mkimplProxy(car(pathValues(target)), impls, sslc, timeout); } -const list<value> refProxies(const list<value>& refs, const list<value>& impls, const SSLConf& sslc, const int timeout, const gc_pool& p) { +const list<value> refProxies(const list<value>& refs, const gc_mutable_ref<list<value> >& impls, const SSLConf& sslc, const int timeout) { if (isNil(refs)) return refs; - return cons(mkrefProxy(car(refs), impls, sslc, timeout, p), refProxies(cdr(refs), impls, sslc, timeout, p)); + return cons(mkrefProxy(car(refs), impls, sslc, timeout), refProxies(cdr(refs), impls, sslc, timeout)); } /** @@ -344,75 +331,56 @@ const list<value> refProxies(const list<value>& refs, const list<value>& impls, * the property value. The host, user and email properties are configured with the values * from the HTTP request, if any. */ -struct propProxy { - const value v; - propProxy(const value& v) : v(v) { - } - const value operator()(unused const list<value>& params) const { +const lvvlambda mkvaluePropProxy(const value& v) { + return [v](unused const list<value>& params) -> const value { return v; - } -}; + }; +} -struct hostPropProxy { - const value v; - hostPropProxy(const value& v) : v(v) { - } - const value operator()(unused const list<value>& params) const { +const lvvlambda mkhostPropProxy(const value& v) { + return [v](unused const list<value>& params) -> const value { if (currentRequest == NULL) return http::hostName(); const value h = httpd::hostName(currentRequest, v); debug(h, "modeval::hostPropProxy::value"); return h; - } -}; + }; +} -struct appPropProxy { - const value v; - appPropProxy(const value& v) : v(v) { - } - const value operator()(unused const list<value>& params) const { +const lvvlambda mkappPropProxy(const value& v) { + return [v](unused const list<value>& params) -> const value { if (currentRequest == NULL) return v; const RequestConf& reqc = httpd::requestConf<RequestConf>(currentRequest, &mod_tuscany_eval); - const value a = isNil(reqc.vpath)? v : car(reqc.vpath); + const value a = isNil((const list<value>)reqc.vpath)? v : car((const list<value>)reqc.vpath); debug(a, "modeval::appPropProxy::value"); return a; - } -}; + }; +} -struct pathPropProxy { - const value v; - pathPropProxy(const value& v) : v(v) { - } - const value operator()(unused const list<value>& params) const { +const lvvlambda mkpathPropProxy(const value& v) { + return [v](unused const list<value>& params) -> const value { if (currentRequest == NULL) return v; const RequestConf& reqc = httpd::requestConf<RequestConf>(currentRequest, &mod_tuscany_eval); - const value p = reqc.rpath; + const value p = (const list<value>)reqc.rpath; debug(p, "modeval::pathPropProxy::value"); return p; - } -}; + }; +} -struct queryPropProxy { - const value v; - queryPropProxy(const value& v) : v(v) { - } - const value operator()(unused const list<value>& params) const { +const lvvlambda mkqueryPropProxy(const value& v) { + return [v](unused const list<value>& params) -> const value { if (currentRequest == NULL) return v; const value q = httpd::unescapeArgs(httpd::queryArgs(currentRequest)); debug(q, "modeval::queryPropProxy::value"); return q; - } -}; + }; +} -struct envPropProxy { - const string name; - const value v; - envPropProxy(const string& name, const value& v) : name(name), v(v) { - } - const value operator()(unused const list<value>& params) const { +const lvvlambda mkenvPropProxy(const string& name, const value& v) { + return [name, v](unused const list<value>& params) -> const value { if (currentRequest == NULL) return v; const char* env = apr_table_get(currentRequest->subprocess_env, c_str(name)); @@ -422,14 +390,11 @@ struct envPropProxy { const value e = string(env); debug(e, "modeval::envPropProxy::value"); return e; - } -}; + }; +} -struct realmPropProxy { - const value v; - realmPropProxy(const value& v) : v(v) { - } - const value operator()(unused const list<value>& params) const { +const lvvlambda mkrealmPropProxy(const value& v) { + return [v](unused const list<value>& params) -> const value { if (currentRequest == NULL) return v; const char* env = apr_table_get(currentRequest->subprocess_env, "REALM"); @@ -441,28 +406,22 @@ struct realmPropProxy { const value r = realm; debug(r, "modeval::realmPropProxy::value"); return r; - } -}; + }; +} -struct timeoutPropProxy { - const value v; - timeoutPropProxy(const value& v) : v(atoi(c_str((string)v))) { - } - const value operator()(unused const list<value>& params) const { +const lvvlambda mktimeoutPropProxy(const value& v) { + return [v](unused const list<value>& params) -> const value { if (currentRequest == NULL) return v; const ServerConf& sc = httpd::serverConf<ServerConf>(currentRequest, &mod_tuscany_eval); const value r = sc.timeout; debug(r, "modeval::timeoutPropProxy::value"); return r; - } -}; + }; +} -struct userPropProxy { - const value v; - userPropProxy(const value& v) : v(v) { - } - const value operator()(unused const list<value>& params) const { +const lvvlambda mkuserPropProxy(const value& v) { + return [v](unused const list<value>& params) -> const value { if (currentRequest == NULL) return v; if (currentRequest->user == NULL) @@ -470,37 +429,37 @@ struct userPropProxy { const value u = string(currentRequest->user); debug(u, "modeval::userPropProxy::value"); return u; - } -}; + }; +} const value mkpropProxy(const value& prop) { const value n = scdl::name(prop); - const value v = elementHasValue(prop)? elementValue(prop):value(string("")); + const value v = elementHasValue(prop)? elementValue(prop) : emptyStringValue; if (n == "app") - return lambda<value(const list<value>&)>(appPropProxy(v)); + return mkappPropProxy(v); if (n == "host") - return lambda<value(const list<value>&)>(hostPropProxy(v)); + return mkhostPropProxy(v); if (n == "path") - return lambda<value(const list<value>&)>(pathPropProxy(v)); + return mkpathPropProxy(v); if (n == "query") - return lambda<value(const list<value>&)>(queryPropProxy(v)); + return mkqueryPropProxy(v); if (n == "user") - return lambda<value(const list<value>&)>(userPropProxy(v)); + return mkuserPropProxy(v); if (n == "realm") - return lambda<value(const list<value>&)>(realmPropProxy(v)); + return mkrealmPropProxy(v); if (n == "timeout") - return lambda<value(const list<value>&)>(timeoutPropProxy(v)); + return mktimeoutPropProxy(v); if (n == "email") - return lambda<value(const list<value>&)>(envPropProxy("EMAIL", v)); + return mkenvPropProxy("EMAIL", v); if (n == "nickname") - return lambda<value(const list<value>&)>(envPropProxy("NICKNAME", v)); + return mkenvPropProxy("NICKNAME", v); if (n == "fullname") - return lambda<value(const list<value>&)>(envPropProxy("FULLNAME", v)); + return mkenvPropProxy("FULLNAME", v); if (n == "firstname") - return lambda<value(const list<value>&)>(envPropProxy("FIRSTNAME", v)); + return mkenvPropProxy("FIRSTNAME", v); if (n == "lastname") - return lambda<value(const list<value>&)>(envPropProxy("LASTNAME", v)); - return lambda<value(const list<value>&)>(propProxy(v)); + return mkenvPropProxy("LASTNAME", v); + return mkvaluePropProxy(v); } const list<value> propProxies(const list<value>& props) { @@ -512,51 +471,45 @@ const list<value> propProxies(const list<value>& props) { /** * Evaluate a component and convert it to an applicable lambda function. */ -struct implementationFailure { - const value reason; - implementationFailure(const value& r) : reason(r) { - } - - // Default implementation representing an implementation that - // couldn't be evaluated. Report the evaluation error on all - // subsequent calls expect start/stop. - const value operator()(unused const list<value>& params) const { - const value func = car(params); - if (func == "start" || func == "stop") - return mklist<value>(lambda<value(const list<value>&)>()); - return mklist<value>(value(), reason); - } -}; - -const value evalComponent(const string& contribPath, const value& comp, const list<value>& impls, const lambda<value(const list<value>&)> lifecycle, const SSLConf& sslc, const int timeout, const gc_pool& p) { - extern const failable<lambda<value(const list<value>&)> > evalImplementation(const string& cpath, const value& impl, const list<value>& px, const lambda<value(const list<value>&)>& lifecycle); +const value evalComponent(const string& contribPath, const value& comp, const gc_mutable_ref<list<value> >& impls, const lvvlambda& lifecycle, const SSLConf& sslc, const int timeout) { + extern const failable<lvvlambda > evalImplementation(const string& cpath, const value& impl, const list<value>& px, const lvvlambda& lifecycle); const value impl = scdl::implementation(comp); debug(comp, "modeval::evalComponent::comp"); debug(impl, "modeval::evalComponent::impl"); // Convert component references to configured proxy lambdas - const list<value> rpx(refProxies(scdl::references(comp), impls, sslc, timeout, p)); + const list<value> rpx(refProxies(scdl::references(comp), impls, sslc, timeout)); // Convert component properties to configured proxy lambdas const list<value> ppx(propProxies(scdl::properties(comp))); // Evaluate the component implementation and convert it to an applicable lambda function - const failable<lambda<value(const list<value>&)> > cimpl(evalImplementation(contribPath, impl, append(rpx, ppx), lifecycle)); - if (!hasContent(cimpl)) - return lambda<value(const list<value>&)>(implementationFailure(reason(cimpl))); + const failable<lvvlambda > cimpl(evalImplementation(contribPath, impl, append(rpx, ppx), lifecycle)); + if (!hasContent(cimpl)) { + // Return a lambda function which will report a component evaluation failure + // on all subsequent calls expect start/stop + const value r = reason(cimpl); + const lvvlambda implementationFailure = [r](const list<value>& params) -> const value { + const value func = car(params); + if (func == "start" || func == "stop") + return mklist<value>(lvvlambda()); + return mklist<value>(nilValue, r); + }; + return implementationFailure; + } return content(cimpl); } /** * Return a list of component-name + configured-implementation pairs. */ -const list<value> componentToImplementationAssoc(const list<value>& c, const string& contribPath, const list<value>& impls, const lambda<value(const list<value>&)> lifecycle, const SSLConf& sslc, const int timeout, const gc_pool& p) { +const list<value> componentToImplementationAssoc(const list<value>& c, const string& contribPath, const gc_mutable_ref<list<value> >& impls, const lvvlambda& lifecycle, const SSLConf& sslc, const int timeout) { if (isNil(c)) return c; return cons<value>(mklist<value>(scdl::name(car(c)), - evalComponent(contribPath, car(c), impls, lifecycle, sslc, timeout, p)), - componentToImplementationAssoc(cdr(c), contribPath, impls, lifecycle, sslc, timeout, p)); + evalComponent(contribPath, car(c), impls, lifecycle, sslc, timeout)), + componentToImplementationAssoc(cdr(c), contribPath, impls, lifecycle, sslc, timeout)); } /** @@ -566,24 +519,28 @@ const failable<list<value> > readComponents(const string& path) { ifstream is(path); if (fail(is)) return mkfailure<list<value> >(string("Could not read composite: ") + path); - return scdl::components(readXML(streamList(is))); + return scdl::components(content(xml::readElements(streamList(is)))); } /** * Get the components returned by a contributor. */ -const failable<list<value> > getComponents(const lambda<value(const list<value>&)>& contributor, const string& name) { +const failable<list<value> > getComponents(const lvvlambda& contributor, const string& name) { const failable<value> val = failableResult(contributor(cons<value>("get", mklist<value>(mklist<value>(name))))); if (!hasContent(val)) return mkfailure<list<value> >(val); - const list<value> c = assoc<value>(value("composite"), assoc<value>(value("content"), (list<list<value> >)cdr<value>(car<value>(content(val))))); - debug(c, "modeval::getComponents::comp"); - if (isNil(c)) + debug(content(val), "modeval::getComponents::val"); + const list<value> valc = assoc<value>(value("content"), cdr<value>(car<value>(content(val)))); + if (isNil(valc)) + return mkfailure<list<value> >(string("Could not get composite: ") + name); + const list<value> comp = assoc<value>(value("composite"), cdr<value>(valc)); + debug(comp, "modeval::getComponents::comp"); + if (isNil(comp)) return mkfailure<list<value> >(string("Could not get composite: ") + name); - const failable<list<string> > x = writeXML(car<value>(valuesToElements(mklist<value>(mklist<value>(c))))); + const failable<list<string> > x = xml::writeElements(car<value>(valuesToElements(mklist<value>(mklist<value>(comp))))); if (!hasContent(x)) return mkfailure<list<value> >(x); - return scdl::components(readXML(content(x))); + return scdl::components(content(xml::readElements(content(x)))); } /** @@ -592,17 +549,17 @@ const failable<list<value> > getComponents(const lambda<value(const list<value>& */ const failable<list<value> > applyLifecycleExpr(const list<value>& impls, const list<value>& expr) { if (isNil(impls)) - return list<value>(); + return nilListValue; // Evaluate lifecycle expression against a component implementation lambda - const lambda<value(const list<value>&)> l = cadr<value>(car(impls)); + const lvvlambda l = cadr<value>(car(impls)); const failable<value> r = failableResult(l(expr)); if (!hasContent(r)) return mkfailure<list<value> >(r); - const lambda<value(const list<value>&)> rl = content(r); + const lvvlambda rl = content(r); // Use the returned lambda function, if any, from now on - const lambda<value(const list<value>&)> al = isNil(rl)? l : rl; + const lvvlambda al = isNil(rl)? l : rl; // Continue with the rest of the list const failable<list<value> > nr = applyLifecycleExpr(cdr(impls), expr); @@ -661,7 +618,7 @@ const list<value> uriToComponentAssoc(const list<value>& c) { /** * Configure the components declared in the deployed composite. */ -const failable<Composite> confComponents(const string& contribPath, const string& composName, const value& contributor, const string& vhost, const list<value>& impls, const lambda<value(const list<value>&)> lifecycle, const SSLConf& sslc, const int timeout, const gc_pool& p) { +const failable<Composite> confComponents(const string& contribPath, const string& composName, const value& contributor, const string& vhost, const gc_mutable_ref<list<value> >& impls, const lvvlambda lifecycle, const SSLConf& sslc, const int timeout) { debug(contribPath, "modeval::confComponents::contribPath"); debug(composName, "modeval::confComponents::composName"); debug(contributor, "modeval::confComponents::contributor"); @@ -685,7 +642,7 @@ const failable<Composite> confComponents(const string& contribPath, const string const list<value> cimpls = mkbtree(sort(componentToImplementationAssoc(comps, isNil(contributor)? length(vhost) != 0? contribPath + vhost + "/" : contribPath : contribPath, - impls, lifecycle, sslc, timeout, p))); + impls, lifecycle, sslc, timeout))); debug(flatten(cimpls), "modeval::confComponents::impls"); return Composite(refs, svcs, cimpls); @@ -715,13 +672,31 @@ const failable<bool> stopComponents(const list<value>& simpls) { } /** + * Returns the media type accepted by a client. + */ +const value acceptMediaType(request_rec* const r) { + const char* const xa = apr_table_get(r->headers_in, "X-Accept"); + const char* const a = xa != NULL? xa : apr_table_get(r->headers_in, "Accept"); + if (a == NULL) + return nilValue; + const string s(a); + if (contains(s, "text/x-scheme")) + return string("scheme"); + if (contains(s, "application/json")) + return string("json"); + if (contains(s, "text/xml")) + return string("xml"); + return nilValue; +} + +/** * Handle an HTTP GET. */ -const failable<int> get(const list<value>& rpath, request_rec* r, const lambda<value(const list<value>&)>& impl) { +const failable<int> get(const list<value>& rpath, request_rec* const r, const lvvlambda& impl) { debug(r->uri, "modeval::get::uri"); // Inspect the query string - const list<list<value> > args = httpd::queryArgs(r); + const list<list<value> > args = httpd::unescapeArgs(httpd::queryArgs(r)); const list<value> ia = assoc(value("id"), args); const list<value> ma = assoc(value("method"), args); @@ -738,12 +713,11 @@ const failable<int> get(const list<value>& rpath, request_rec* r, const lambda<v return mkfailure<int>(val); // Return JSON result - js::JSContext cx; - return httpd::writeResult(json::jsonResult(id, content(val), cx), "application/json-rpc; charset=utf-8", r); + return httpd::writeResult(json::jsonResult(id, content(val)), "application/json-rpc; charset=utf-8", r); } // Evaluate the GET expression - const list<value> params(cddr(rpath)); + const list<value> params(append<value>(cddr(rpath), mkvalues(args))); const failable<value> val = failableResult(impl(cons<value>("get", mklist<value>(params)))); if (!hasContent(val)) return mkfailure<int>(val); @@ -754,58 +728,42 @@ const failable<int> get(const list<value>& rpath, request_rec* r, const lambda<v if (!isList(c) && isNil(c)) return HTTP_NOT_FOUND; - // Check if the client requested a specific format + // Write in the format requested by the client, if any const list<value> fmt = assoc<value>("format", args); - - // Write as a scheme value if requested by the client - if (!isNil(fmt) && cadr(fmt) == "scheme") - return httpd::writeResult(mklist<string>(scheme::writeValue(c)), "text/plain; charset=utf-8", r); + const value mtype = !isNil(fmt)? cadr(fmt) : acceptMediaType(r); + if (!isNil(mtype)) { + if (mtype == "scheme") + return httpd::writeResult(scheme::writeValue(c), "text/x-scheme; charset=utf-8", r); + if (mtype == "json") + return httpd::writeResult(json::writeValue(c), "application/json; charset=utf-8", r); + if (mtype == "xml") + return httpd::writeResult(xml::writeElements(valuesToElements(c)), "text/xml; charset=utf-8", r); + } // Write a simple value as a JSON value if (!isList(c)) { - js::JSContext cx; - if (isSymbol(c)) { - const list<value> lc = mklist<value>(mklist<value>("name", value(string(c)))); - debug(lc, "modeval::get::symbol"); - return httpd::writeResult(json::writeJSON(valuesToElements(lc), cx), "application/json; charset=utf-8", r); - } - - const list<value> lc = mklist<value>(mklist<value>("value", c)); - debug(lc, "modeval::get::value"); - return httpd::writeResult(json::writeJSON(valuesToElements(lc), cx), "application/json; charset=utf-8", r); + debug(c, "modeval::get::value"); + return httpd::writeResult(json::writeValue(c), "application/json; charset=utf-8", r); } - // Write an empty list as a JSON empty value + // Write an empty list as a JSON value if (isNil((list<value>)c)) { - js::JSContext cx; - debug(list<value>(), "modeval::get::empty"); - return httpd::writeResult(json::writeJSON(list<value>(), cx), "application/json; charset=utf-8", r); + debug(nilListValue, "modeval::get::empty"); + return httpd::writeResult(json::writeValue(c), "application/json; charset=utf-8", r); } // Write content-type / content-list pair if (isString(car<value>(c)) && !isNil(cdr<value>(c)) && isList(cadr<value>(c))) return httpd::writeResult(convertValues<string>(cadr<value>(c)), car<value>(c), r); - // Write an assoc value as a JSON result + // Write an assoc value as a JSON value if (isSymbol(car<value>(c)) && !isNil(cdr<value>(c))) { - js::JSContext cx; - const list<value> lc = mklist<value>(c); - debug(lc, "modeval::get::assoc"); - debug(valuesToElements(lc), "modeval::get::assoc::element"); - return httpd::writeResult(json::writeJSON(valuesToElements(lc), cx), "application/json; charset=utf-8", r); - } - - // Write value as JSON if requested by the client - if (!isNil(fmt) && cadr(fmt) == "json") { - js::JSContext cx; - return httpd::writeResult(json::writeJSON(valuesToElements(c), cx), "application/json; charset=utf-8", r); + debug(c, "modeval::get::assoc"); + return httpd::writeResult(json::writeValue(c), "application/json; charset=utf-8", r); } - // Convert list of values to element values - const list<value> e = valuesToElements(c); - debug(e, "modeval::get::elements"); - // Write an ATOM feed or entry + const list<value> e = valuesToElements(c); if (isList(car<value>(e)) && !isNil(car<value>(e))) { const list<value> el = car<value>(e); if (isSymbol(car<value>(el)) && car<value>(el) == element && !isNil(cdr<value>(el)) && isSymbol(cadr<value>(el)) && elementHasChildren(el) && !elementHasValue(el)) { @@ -817,14 +775,13 @@ const failable<int> get(const list<value>& rpath, request_rec* r, const lambda<v } // Write any other compound value as a JSON value - js::JSContext cx; - return httpd::writeResult(json::writeJSON(e, cx), "application/json; charset=utf-8", r); + return httpd::writeResult(json::writeValue(c), "application/json; charset=utf-8", r); } /** * Handle an HTTP POST. */ -const failable<int> post(const list<value>& rpath, request_rec* r, const lambda<value(const list<value>&)>& impl) { +const failable<int> post(const list<value>& rpath, request_rec* const r, const lvvlambda& impl) { debug(r->uri, "modeval::post::uri"); // Evaluate a JSON-RPC request and return a JSON result @@ -837,9 +794,8 @@ const failable<int> post(const list<value>& rpath, request_rec* r, const lambda< return rc; const list<string> ls = httpd::read(r); debug(ls, "modeval::post::input"); - js::JSContext cx; - const list<value> json = elementsToValues(content(json::readJSON(ls, cx))); - const list<list<value> > args = httpd::postArgs(json); + const value jsreq = content(json::readValue(ls)); + const list<list<value> > args = httpd::postArgs(jsreq); // Extract the request id, method and params const value id = cadr(assoc(value("id"), args)); @@ -852,7 +808,7 @@ const failable<int> post(const list<value>& rpath, request_rec* r, const lambda< return mkfailure<int>(val); // Return JSON result - return httpd::writeResult(json::jsonResult(id, content(val), cx), "application/json-rpc; charset=utf-8", r); + return httpd::writeResult(json::jsonResult(id, content(val)), "application/json-rpc; charset=utf-8", r); } // Evaluate an ATOM POST request and return the location of the corresponding created resource @@ -871,14 +827,21 @@ const failable<int> post(const list<value>& rpath, request_rec* r, const lambda< if (!hasContent(val)) return mkfailure<int>(val); - // Return the created resource location - debug(content(val), "modeval::post::location"); - apr_table_setn(r->headers_out, "Location", apr_pstrdup(r->pool, c_str(httpd::url(r->uri, content(val), r)))); + // Report HTTP status code + const value rval = content(val); + if (isNil(rval) || rval == falseValue) + return HTTP_NOT_FOUND; + if (isNumber(rval)) + return (int)rval; + + // Return the successfully created resource location + debug(rval, "modeval::post::location"); + apr_table_setn(r->headers_out, "Location", apr_pstrdup(r->pool, c_str(httpd::url(r->uri, rval, r)))); r->status = HTTP_CREATED; return OK; } - // Unknown content type, wrap the HTTP request struct in a value and pass it to + // Unknown content type, wrap the HTTP request structure in a value and pass it to // the component implementation function const failable<value> val = failableResult(impl(cons<value>("handle", mklist<value>(httpd::requestValue(r))))); if (!hasContent(val)) @@ -889,7 +852,7 @@ const failable<int> post(const list<value>& rpath, request_rec* r, const lambda< /** * Handle an HTTP PUT. */ -const failable<int> put(const list<value>& rpath, request_rec* r, const lambda<value(const list<value>&)>& impl) { +const failable<int> put(const list<value>& rpath, request_rec* const r, const lvvlambda& impl) { debug(r->uri, "modeval::put::uri"); // Read the ATOM entry @@ -904,35 +867,45 @@ const failable<int> put(const list<value>& rpath, request_rec* r, const lambda<v const failable<value> val = failableResult(impl(cons<value>("put", mklist<value>(cddr(rpath), aval)))); if (!hasContent(val)) return mkfailure<int>(val); - if (val == value(false)) + + // Report HTTP status + const value rval = content(val); + if (isNil(rval) || rval == falseValue) return HTTP_NOT_FOUND; + if (isNumber(rval)) + return (int)rval; return OK; } /** * Handle an HTTP DELETE. */ -const failable<int> del(const list<value>& rpath, request_rec* r, const lambda<value(const list<value>&)>& impl) { +const failable<int> del(const list<value>& rpath, request_rec* const r, const lvvlambda& impl) { debug(r->uri, "modeval::delete::uri"); // Evaluate an ATOM delete request const failable<value> val = failableResult(impl(cons<value>("delete", mklist<value>(cddr(rpath))))); if (!hasContent(val)) return mkfailure<int>(val); - if (val == value(false)) + + // Report HTTP status + const value rval = content(val); + if (isNil(rval) || rval == falseValue) return HTTP_NOT_FOUND; + if (isNumber(rval)) + return (int)rval; return OK; } /** * Proceed to handle a service component request. */ -int proceedToHandler(request_rec* r, const int rc) { +int proceedToHandler(request_rec* const r, const int rc) { r->handler = "mod_tuscany_eval"; return rc; } -int proceedToHandler(request_rec* r, const int rc, const bool valias, const list<value>& rpath, const list<value>& vpath, const list<value>& impls) { +int proceedToHandler(request_rec* const r, const int rc, const bool valias, const list<value>& rpath, const list<value>& vpath, const list<value>& impls) { r->handler = "mod_tuscany_eval"; r->filename = apr_pstrdup(r->pool, c_str(string("/redirect:") + r->uri)); @@ -948,7 +921,7 @@ int proceedToHandler(request_rec* r, const int rc, const bool valias, const list /** * Route a component request to the specified component. */ -int translateComponent(request_rec *r, const list<value>& rpath, const list<value>& vpath, const list<value>& impls) { +int translateComponent(request_rec* const r, const list<value>& rpath, const list<value>& vpath, const list<value>& impls) { debug(rpath, "modeval::translateComponent::rpath"); debug(flatten(impls), "modeval::translateComponent::impls"); @@ -967,7 +940,7 @@ int translateComponent(request_rec *r, const list<value>& rpath, const list<valu * Route a /references/component-name/reference-name request, * to the target of the component reference. */ -int translateReference(request_rec *r, const list<value>& rpath, const list<value>& vpath, const list<value>& refs, const list<value>& impls) { +int translateReference(request_rec* const r, const list<value>& rpath, const list<value>& vpath, const list<value>& refs, const list<value>& impls) { debug(rpath, "modeval::translateReference::rpath"); debug(flatten(refs), "modeval::translateReference::refs"); @@ -991,7 +964,7 @@ int translateReference(request_rec *r, const list<value>& rpath, const list<valu // Route to an absolute target URI using mod_proxy or an HTTP client redirect const list<value> pathInfo = cdddr(rpath); if (http::isAbsolute(target)) { - string turi = target + path(pathInfo) + (r->args != NULL? string("?") + string(r->args) : string("")); + const string turi = target + (string)path(pathInfo) + (r->args != NULL? string("?") + string(r->args) : emptyString); const string proxy(string("proxy:") + turi); debug(proxy, "modeval::translateReference::proxy"); r->filename = apr_pstrdup(r->pool, c_str(proxy)); @@ -1035,7 +1008,7 @@ const list<value> assocPath(const value& k, const list<value>& tree) { /** * Route a service request to the component providing the requested service. */ -int translateService(request_rec *r, const list<value>& rpath, const list<value>& vpath, const list<value>& svcs, const list<value>& impls) { +int translateService(request_rec* const r, const list<value>& rpath, const list<value>& vpath, const list<value>& svcs, const list<value>& impls) { debug(rpath, "modeval::translateService::rpath"); debug(flatten(svcs), "modeval::translateService::svcs"); @@ -1057,10 +1030,10 @@ int translateService(request_rec *r, const list<value>& rpath, const list<value> /** * Translate a request to the target app and component. */ -const int translateRequest(request_rec* r, const list<value>& rpath, const list<value>& vpath, const list<value>& refs, const list<value>& svcs, const list<value>& impls) { +const int translateRequest(request_rec* const r, const list<value>& rpath, const list<value>& vpath, const list<value>& refs, const list<value>& svcs, const list<value>& impls) { debug(vpath, "modeval::translateRequest::vpath"); debug(rpath, "modeval::translateRequest::rpath"); - const string prefix = isNil(rpath)? "" : car(rpath); + const string prefix = isNil(rpath)? emptyStringValue : car(rpath); // Translate a component request if ((prefix == string("components") || prefix == string("c")) && translateComponent(r, rpath, vpath, impls) == OK) @@ -1079,7 +1052,7 @@ const int translateRequest(request_rec* r, const list<value>& rpath, const list< const failable<request_rec*> fnr = httpd::internalSubRequest(r->uri, r); if (!hasContent(fnr)) return rcode(fnr); - request_rec* nr = content(fnr); + request_rec* const nr = content(fnr); nr->uri = r->filename; const int tr = ap_core_translate(nr); if (tr != OK) @@ -1095,7 +1068,7 @@ const int translateRequest(request_rec* r, const list<value>& rpath, const list< // Make sure a document root request ends with a '/' using // an external redirect if (isNil(rpath) && r->uri[strlen(r->uri) - 1] != '/') { - const string target = string(r->uri) + string("/") + (r->args != NULL? string("?") + string(r->args) : string("")); + const string target = string(r->uri) + string("/") + (r->args != NULL? string("?") + string(r->args) : emptyString); debug(target, "modeval::translateRequest::location"); return proceedToHandler(r, httpd::externalRedirect(target, r)); } @@ -1117,8 +1090,7 @@ 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; - gc_scoped_pool pool(r->pool); - + const gc_scoped_pool sp(r->pool); debug_httpdRequest(r, "modeval::translate::input"); // Get the server configuration @@ -1128,7 +1100,7 @@ int translate(request_rec *r) { const list<value> rpath = pathValues(r->uri); // Let default handler handle a resource request - const string prefix = isNil(rpath)? "" : car(rpath); + const string prefix = isNil(rpath)? emptyStringValue : car(rpath); if (prefix == string("vhosts") || prefix == string("v")) return DECLINED; @@ -1139,7 +1111,7 @@ int translate(request_rec *r) { // in that virtual host if (length(sc.vhostc.domain) != 0 && (length(sc.vhostc.contribPath) != 0 || !isNil(sc.vhostc.contributor)) && httpd::isVhostRequest(sc.server, sc.vhostc.domain, r)) { const string vname = http::subDomain(httpd::hostName(r)); - const failable<Composite> fvcompos = confComponents(sc.vhostc.contribPath, sc.vhostc.composName, sc.vhostc.contributor, vname, reqc.impls, sc.lifecycle, sc.sslc, sc.timeout, sc.p); + const failable<Composite> fvcompos = confComponents(sc.vhostc.contribPath, sc.vhostc.composName, sc.vhostc.contributor, vname, reqc.impls, (value)sc.lifecycle, sc.sslc, sc.timeout); if (!hasContent(fvcompos)) return DECLINED; const Composite vcompos = content(fvcompos); @@ -1153,14 +1125,14 @@ int translate(request_rec *r) { } // Translate a request targeting the main host - const int rc = translateRequest(r, rpath, list<value>(), sc.compos.refs, sc.compos.svcs, sc.compos.impls); + const int rc = translateRequest(r, rpath, nilListValue, sc.compos.refs, sc.compos.svcs, sc.compos.impls); if (rc != HTTP_NOT_FOUND) return rc; // Attempt to map the first segment of the request path to a virtual host if (length(prefix) != 0 && (length(sc.vhostc.contribPath) != 0 || !isNil(sc.vhostc.contributor))) { const string vname = prefix; - const failable<Composite> fvcompos = confComponents(sc.vhostc.contribPath, sc.vhostc.composName, sc.vhostc.contributor, vname, reqc.impls, sc.lifecycle, sc.sslc, sc.timeout, sc.p); + const failable<Composite> fvcompos = confComponents(sc.vhostc.contribPath, sc.vhostc.composName, sc.vhostc.contributor, vname, reqc.impls, (value)sc.lifecycle, sc.sslc, sc.timeout); if (!hasContent(fvcompos)) return DECLINED; const Composite vcompos = content(fvcompos); @@ -1175,16 +1147,16 @@ int translate(request_rec *r) { /** * Handle a component request. */ -const int handleRequest(const list<value>& rpath, request_rec *r, const list<value>& impls) { +const int handleRequest(const list<value>& rpath, request_rec* const r, const list<value>& impls) { debug(rpath, "modeval::handleRequest::path"); // Get the component implementation lambda const list<value> impl(assoctree<value>(cadr(rpath), impls)); if (isNil(impl)) { - mkfailure<int>(string("Couldn't find component implementation: ") + cadr(rpath)); + mkfailure<int>(string("Couldn't find component implementation: ") + (string)cadr(rpath)); return HTTP_NOT_FOUND; } - const lambda<value(const list<value>&)> l(cadr<value>(impl)); + const lvvlambda l(cadr<value>(impl)); // Handle HTTP method if (r->header_only) @@ -1203,7 +1175,7 @@ const int handleRequest(const list<value>& rpath, request_rec *r, const list<val /** * HTTP request handler. */ -int handler(request_rec *r) { +int handler(request_rec* r) { if (r->handler != NULL && r->handler[0] != '\0') return DECLINED; @@ -1217,7 +1189,7 @@ int handler(request_rec *r) { return DECLINED; // Create a scope for the current request - gc_scoped_pool pool(r->pool); + const gc_scoped_pool sp(r->pool); ScopedRequest sr(r); debug_httpdRequest(r, "modeval::handler::input"); @@ -1227,18 +1199,18 @@ int handler(request_rec *r) { // Handle an internal redirect as directed by the translate hook if (reqc.valias) { - const string redir = path(cons<value>(string("v"), reqc.vhost? reqc.vpath : list<value>())) + string(r->uri) + (r->args != NULL? string("?") + string(r->args) : string("")); + const string redir = path(cons<value>(string("v"), reqc.vhost? (const list<value>)reqc.vpath : nilListValue)) + string(r->uri) + (r->args != NULL? string("?") + string(r->args) : emptyString); debug(redir, "modeval::handler::internalredirect"); return httpd::internalRedirect(redir, r); } - if (isNil(reqc.rpath)) + if (isNil((const list<value>)reqc.rpath)) return HTTP_NOT_FOUND; // Get the server configuration const ServerConf& sc = httpd::serverConf<ServerConf>(r, &mod_tuscany_eval); // Handle a request targeting a component in a virtual host - if (!isNil(reqc.vpath)) { + if (!isNil((const list<value>)reqc.vpath)) { // Start the components in the virtual host const failable<list<value> > fsimpls = startComponents(reqc.impls); @@ -1247,7 +1219,7 @@ int handler(request_rec *r) { const list<value> simpls = content(fsimpls); // Merge the components in the virtual host with the components in the main host - reqc.impls = mkbtree(sort(append(flatten(sc.compos.impls), flatten(simpls)))); + reqc.impls = mkbtree(sort(append(flatten((const list<value>)sc.compos.impls), flatten(simpls)))); // Handle the request against the running components const int rc = handleRequest(reqc.rpath, r, reqc.impls); @@ -1265,7 +1237,7 @@ int handler(request_rec *r) { * Call an authenticator component to check a user's password. */ authn_status checkPassword(request_rec* r, const char* u, const char* p) { - gc_scoped_pool pool(r->pool); + const gc_scoped_pool sp(r->pool); // Prevent FakeBasicAuth spoofing const string user = u; @@ -1285,16 +1257,16 @@ authn_status checkPassword(request_rec* r, const char* u, const char* p) { // Retrieve the user's password hash const list<value> uid = pathValues(user); - const failable<value> val = failableResult(sc.vhostc.authenticator(cons<value>("get", mklist<value>(uid)))); + const failable<value> val = failableResult(((value)sc.vhostc.authenticator)(cons<value>("get", mklist<value>(uid)))); if (!hasContent(val)) { - mkfailure<int>(string("SCA authentication check user failed, user not found: ") + user); + mkfailure<int>(string("SCA authentication check user failed, user not found: ") + user, rcode(val), user != "admin"); return AUTH_USER_NOT_FOUND; } const value hval = content(val); - const list<value> hcontent = isList(hval) && !isNil(hval) && isList(car<value>(hval)) && !isNil(car<value>(hval))? assoc<value>(value("content"), cdr<value>(car<value>(hval))) : list<value>(); - const list<value> hassoc = isNil(hcontent)? list<value>() : assoc<value>(value("hash"), cdr<value>(hcontent)); + const list<value> hcontent = isList(hval) && !isNil(hval) && isList(car<value>(hval)) && !isNil(car<value>(hval))? assoc<value>(value("content"), cdr<value>(car<value>(hval))) : nilListValue; + const list<value> hassoc = isNil(hcontent)? nilListValue : assoc<value>(value("hash"), cdr<value>(hcontent)); if (isNil(hassoc)) { - mkfailure<int>(string("SCA authentication check user failed, hash not found: ") + user); + mkfailure<int>(string("SCA authentication check user failed, hash not found: ") + user, -1, user != "admin"); return AUTH_USER_NOT_FOUND; } const string hash = cadr<value>(hassoc); @@ -1320,7 +1292,7 @@ authn_status checkPassword(request_rec* r, const char* u, const char* p) { * Cleanup callback, called when the server is stopped or restarted. */ apr_status_t serverCleanup(void* v) { - gc_pool pool; + const gc_pool pool; ServerConf& sc = *(ServerConf*)v; debug("modeval::serverCleanup"); @@ -1328,10 +1300,14 @@ apr_status_t serverCleanup(void* v) { stopComponents(sc.compos.impls); // Call the module lifecycle function - if (isNil(sc.lifecycle)) + if (isNil((value)sc.lifecycle)) return APR_SUCCESS; - debug("modeval::serverCleanup::stop"); - sc.lifecycle(mklist<value>("stop")); + const lvvlambda ll = (value)sc.lifecycle; + if (isNil(ll)) + return APR_SUCCESS; + + debug((value)sc.lifecycle, "modeval::serverCleanup::stop"); + ll(mklist<value>("stop")); return APR_SUCCESS; } @@ -1340,7 +1316,7 @@ apr_status_t serverCleanup(void* v) { * Called after all the configuration commands have been run. * Process the server configuration and configure the deployed components. */ -const int postConfigMerge(const ServerConf& mainsc, server_rec* s) { +const int postConfigMerge(const ServerConf& mainsc, server_rec* const s) { if (s == NULL) return OK; ServerConf& sc = httpd::serverConf<ServerConf>(s, &mod_tuscany_eval); @@ -1348,9 +1324,9 @@ const int postConfigMerge(const ServerConf& mainsc, server_rec* s) { sc.lifecycle = mainsc.lifecycle; sc.contribc = mainsc.contribc; sc.vhostc = mainsc.vhostc; - if (sc.sslc.ca == "") sc.sslc.ca = mainsc.sslc.ca; - if (sc.sslc.cert == "") sc.sslc.cert = mainsc.sslc.cert; - if (sc.sslc.key == "") sc.sslc.key = mainsc.sslc.key; + if (sc.sslc.ca == emptyString) sc.sslc.ca = mainsc.sslc.ca; + if (sc.sslc.cert == emptyString) sc.sslc.cert = mainsc.sslc.cert; + if (sc.sslc.key == emptyString) sc.sslc.key = mainsc.sslc.key; sc.timeout = mainsc.timeout; sc.compos = mainsc.compos; return postConfigMerge(mainsc, s->next); @@ -1359,7 +1335,7 @@ const int postConfigMerge(const ServerConf& mainsc, server_rec* s) { int postConfig(apr_pool_t *p, unused apr_pool_t *plog, unused apr_pool_t *ptemp, server_rec *s) { extern const value applyLifecycle(const list<value>&); - gc_scoped_pool pool(p); + const gc_scoped_pool sp(p); // Get the server configuration and determine the server name ServerConf& sc = httpd::serverConf<ServerConf>(s, &mod_tuscany_eval); @@ -1388,7 +1364,7 @@ int postConfig(apr_pool_t *p, unused apr_pool_t *plog, unused apr_pool_t *ptemp, const failable<value> r = failableResult(applyLifecycle(mklist<value>("start"))); if (!hasContent(r)) return -1; - debug("modeval::postConfig::setlifecycle"); + debug(content(r), "modeval::postConfig::setlifecycle"); sc.lifecycle = content(r); } if (count > 1) { @@ -1396,12 +1372,12 @@ int postConfig(apr_pool_t *p, unused apr_pool_t *plog, unused apr_pool_t *ptemp, const failable<value> r = failableResult(applyLifecycle(mklist<value>("restart"))); if (!hasContent(r)) return -1; - debug("modeval::postConfig::setlifecycle"); + debug(content(r), "modeval::postConfig::setlifecycle"); sc.lifecycle = content(r); } // Configure the deployed components - const failable<Composite> compos = confComponents(sc.contribc.contribPath, sc.contribc.composName, value(), "", sc.compos.impls, sc.lifecycle, sc.sslc, sc.timeout, sc.p); + const failable<Composite> compos = confComponents(sc.contribc.contribPath, sc.contribc.composName, nilValue, emptyString, sc.compos.impls, (value)sc.lifecycle, sc.sslc, sc.timeout); if (!hasContent(compos)) { cfailure << "[Tuscany] Due to one or more errors mod_tuscany_eval loading failed. Causing apache to stop loading." << endl; return -1; @@ -1427,9 +1403,9 @@ void failureExitChild() { * Child process initialization. */ void childInit(apr_pool_t* p, server_rec* s) { - gc_scoped_pool pool(p); + const gc_scoped_pool sp(p); - ServerConf* psc = (ServerConf*)ap_get_module_config(s->module_config, &mod_tuscany_eval); + ServerConf* const psc = (ServerConf*)ap_get_module_config(s->module_config, &mod_tuscany_eval); if(psc == NULL) failureExitChild(); ServerConf& sc = *psc; @@ -1442,7 +1418,7 @@ void childInit(apr_pool_t* p, server_rec* s) { // Get the vhost contributor component implementation lambda if (length(sc.vhostc.contributorName) != 0) { - const list<value> impl(assoctree<value>(sc.vhostc.contributorName, sc.compos.impls)); + const list<value> impl(assoctree<value>((string)sc.vhostc.contributorName, (const list<value>)sc.compos.impls)); if (isNil(impl)) { mkfailure<int>(string("Couldn't find contributor component implementation: ") + sc.vhostc.contributorName); failureExitChild(); @@ -1452,7 +1428,7 @@ void childInit(apr_pool_t* p, server_rec* s) { // Get the vhost authenticator component implementation lambda if (length(sc.vhostc.authenticatorName) != 0) { - const list<value> impl(assoctree<value>(sc.vhostc.authenticatorName, sc.compos.impls)); + const list<value> impl(assoctree<value>((string)sc.vhostc.authenticatorName, (const list<value>)sc.compos.impls)); if (isNil(impl)) { mkfailure<int>(string("Couldn't find authenticator component implementation: ") + sc.vhostc.authenticatorName); failureExitChild(); @@ -1471,73 +1447,73 @@ void childInit(apr_pool_t* p, server_rec* s) { * Configuration commands. */ const char* confContribution(cmd_parms *cmd, unused void *c, const char *arg) { - gc_scoped_pool pool(cmd->pool); + const gc_scoped_pool sp(cmd->pool); ServerConf& sc = httpd::serverConf<ServerConf>(cmd, &mod_tuscany_eval); sc.contribc.contribPath = arg; return NULL; } const char* confComposite(cmd_parms *cmd, unused void *c, const char *arg) { - gc_scoped_pool pool(cmd->pool); + const gc_scoped_pool sp(cmd->pool); ServerConf& sc = httpd::serverConf<ServerConf>(cmd, &mod_tuscany_eval); sc.contribc.composName = arg; return NULL; } const char* confVirtualDomain(cmd_parms *cmd, unused void *c, const char *arg) { - gc_scoped_pool pool(cmd->pool); + const gc_scoped_pool sp(cmd->pool); ServerConf& sc = httpd::serverConf<ServerConf>(cmd, &mod_tuscany_eval); sc.vhostc.domain = arg; return NULL; } const char* confVirtualContribution(cmd_parms *cmd, unused void *c, const char *arg) { - gc_scoped_pool pool(cmd->pool); + const gc_scoped_pool sp(cmd->pool); ServerConf& sc = httpd::serverConf<ServerConf>(cmd, &mod_tuscany_eval); sc.vhostc.contribPath = arg; return NULL; } const char* confVirtualContributor(cmd_parms *cmd, unused void *c, const char *arg) { - gc_scoped_pool pool(cmd->pool); + const gc_scoped_pool sp(cmd->pool); ServerConf& sc = httpd::serverConf<ServerConf>(cmd, &mod_tuscany_eval); sc.vhostc.contributorName = arg; return NULL; } const char* confVirtualComposite(cmd_parms *cmd, unused void *c, const char *arg) { - gc_scoped_pool pool(cmd->pool); + const gc_scoped_pool sp(cmd->pool); ServerConf& sc = httpd::serverConf<ServerConf>(cmd, &mod_tuscany_eval); sc.vhostc.composName = arg; return NULL; } const char* confAuthenticator(cmd_parms *cmd, unused void *c, const char *arg) { - gc_scoped_pool pool(cmd->pool); + const gc_scoped_pool sp(cmd->pool); ServerConf& sc = httpd::serverConf<ServerConf>(cmd, &mod_tuscany_eval); sc.vhostc.authenticatorName = arg; return NULL; } const char* confCAFile(cmd_parms *cmd, unused void *c, const char *arg) { - gc_scoped_pool pool(cmd->pool); + const gc_scoped_pool sp(cmd->pool); ServerConf& sc = httpd::serverConf<ServerConf>(cmd, &mod_tuscany_eval); sc.sslc.ca = arg; return NULL; } const char* confCertFile(cmd_parms *cmd, unused void *c, const char *arg) { - gc_scoped_pool pool(cmd->pool); + const gc_scoped_pool sp(cmd->pool); ServerConf& sc = httpd::serverConf<ServerConf>(cmd, &mod_tuscany_eval); sc.sslc.cert = arg; return NULL; } const char* confCertKeyFile(cmd_parms *cmd, unused void *c, const char *arg) { - gc_scoped_pool pool(cmd->pool); + const gc_scoped_pool sp(cmd->pool); ServerConf& sc = httpd::serverConf<ServerConf>(cmd, &mod_tuscany_eval); sc.sslc.key = arg; return NULL; } const char* confTimeout(cmd_parms *cmd, unused void *c, const char *arg) { - gc_scoped_pool pool(cmd->pool); + const gc_scoped_pool sp(cmd->pool); ServerConf& sc = httpd::serverConf<ServerConf>(cmd, &mod_tuscany_eval); sc.timeout = atoi(arg); return NULL; } const char* confEnv(unused cmd_parms *cmd, unused void *c, const char *name, const char *value) { - gc_scoped_pool pool(cmd->pool); + const gc_scoped_pool sp(cmd->pool); setenv(name, value != NULL? value : "", 1); return NULL; } diff --git a/sca-cpp/trunk/modules/server/mod-scheme.hpp b/sca-cpp/trunk/modules/server/mod-scheme.hpp index 43d7bf4041..36d91dc904 100644 --- a/sca-cpp/trunk/modules/server/mod-scheme.hpp +++ b/sca-cpp/trunk/modules/server/mod-scheme.hpp @@ -49,39 +49,30 @@ const list<value> primitiveProcedures(const list<value>& l) { } /** - * Apply a Scheme component implementation function. - */ -struct applyImplementation { - const value impl; - const list<value> px; - - applyImplementation(const value& impl, const list<value>& px) : impl(impl), px(scheme::quotedParameters(primitiveProcedures(px))) { - } - - const value operator()(const list<value>& params) const { - const value expr = cons<value>(car(params), append(scheme::quotedParameters(cdr(params)), px)); - debug(expr, "modeval::scheme::applyImplementation::input"); - scheme::Env env = scheme::setupEnvironment(); - const value res = scheme::evalScript(expr, impl, env); - const value val = isNil(res)? mklist<value>(value(), string("Could not evaluate expression")) : mklist<value>(res); - debug(val, "modeval::scheme::applyImplementation::result"); - return val; - } -}; - -/** * Evaluate a Scheme component implementation and convert it to an * applicable lambda function. */ -const failable<lambda<value(const list<value>&)> > evalImplementation(const string& path, const value& impl, const list<value>& px) { - const string fpath(path + attributeValue("script", impl)); +const failable<lvvlambda > evalImplementation(const string& path, const value& impl, const list<value>& px) { + const string fpath(path + (string)attributeValue("script", impl)); ifstream is(fpath); if (fail(is)) - return mkfailure<lambda<value(const list<value>&)> >(string("Could not read implementation: ") + fpath); + return mkfailure<lvvlambda >(string("Could not read implementation: ") + fpath); const value script = scheme::readScript(is); if (isNil(script)) - return mkfailure<lambda<value(const list<value>&)> >(string("Could not read implementation: ") + fpath); - return lambda<value(const list<value>&)>(applyImplementation(script, px)); + return mkfailure<lvvlambda >(string("Could not read implementation: ") + fpath); + const list<value> pxproc = scheme::quotedParameters(primitiveProcedures(px)); + + const lvvlambda applyImplementation = [script, pxproc](const list<value>& params) -> const value { + // Apply a Scheme component implementation function + const value expr = cons<value>(car(params), append(scheme::quotedParameters(cdr(params)), pxproc)); + debug(expr, "modeval::scheme::applyImplementation::input"); + scheme::Env env = scheme::setupEnvironment(); + const value res = scheme::evalScript(expr, script, env); + const value val = isNil(res)? mklist<value>(nilValue, string("Could not evaluate expression")) : mklist<value>(res); + debug(val, "modeval::scheme::applyImplementation::result"); + return val; + }; + return applyImplementation; } } diff --git a/sca-cpp/trunk/modules/server/server-conf b/sca-cpp/trunk/modules/server/server-conf index bfa5ac8473..2674cd9ac5 100755 --- a/sca-cpp/trunk/modules/server/server-conf +++ b/sca-cpp/trunk/modules/server/server-conf @@ -22,6 +22,18 @@ here=`echo "import os; print os.path.realpath('$0')" | python`; here=`dirname $h mkdir -p $1 root=`echo "import os; print os.path.realpath('$1')" | python` +# Configure thread stack size on MacOS X +uname=`uname -s` +if [ "$uname" = "Darwin" ]; then + cat >>$root/conf/mpm.conf <<EOF +# Generated by: httpd-conf $* +# Set thread stack size +ThreadStackSize 2097152 + +EOF + +fi + # Serve Javascript scripts and CSS $here/../js/js-conf $1 diff --git a/sca-cpp/trunk/modules/wsgi/Makefile.am b/sca-cpp/trunk/modules/wsgi/Makefile.am index 43cffb2254..70356603d9 100644 --- a/sca-cpp/trunk/modules/wsgi/Makefile.am +++ b/sca-cpp/trunk/modules/wsgi/Makefile.am @@ -43,7 +43,7 @@ gae.prefix: $(top_builddir)/config.status EXTRA_DIST = domain-test.composite *.py htdocs/test/*.xml htdocs/test/*.txt htdocs/*.html client_test_SOURCES = client-test.cpp -client_test_LDFLAGS = -lxml2 -lcurl -lmozjs +client_test_LDFLAGS = -lxml2 -lcurl -ljansson noinst_PROGRAMS = client-test diff --git a/sca-cpp/trunk/modules/wsgi/client-test.cpp b/sca-cpp/trunk/modules/wsgi/client-test.cpp index da4fff973b..f0bc490896 100644 --- a/sca-cpp/trunk/modules/wsgi/client-test.cpp +++ b/sca-cpp/trunk/modules/wsgi/client-test.cpp @@ -27,7 +27,7 @@ #include "string.hpp" #include "../server/client-test.hpp" -int main(const int argc, const char** argv) { +int main(const int argc, const char** const argv) { tuscany::cout << "Testing..." << tuscany::endl; tuscany::server::testURI = argc < 2? "http://localhost:8090/wsgi" : argv[1]; tuscany::server::testBlobs = false; |