From 419f903ff44a22debba43976baae1e86c1e5d871 Mon Sep 17 00:00:00 2001 From: jsdelfino Date: Mon, 16 Jul 2012 06:47:59 +0000 Subject: Add a timeout property to the CURL HTTP clients. git-svn-id: http://svn.us.apache.org/repos/asf/tuscany@1361916 13f79535-47bb-0310-9956-ffa450edef68 --- sca-cpp/trunk/components/cache/client-test.cpp | 12 +- sca-cpp/trunk/components/chat/client-test.cpp | 2 +- sca-cpp/trunk/components/constdb/client-test.cpp | 8 +- sca-cpp/trunk/components/filedb/client-test.cpp | 8 +- sca-cpp/trunk/components/http/client-test.cpp | 14 +- sca-cpp/trunk/components/http/http.composite | 5 + .../trunk/components/http/httpdelete.componentType | 1 + sca-cpp/trunk/components/http/httpdelete.cpp | 20 +- .../trunk/components/http/httpget.componentType | 1 + sca-cpp/trunk/components/http/httpget.cpp | 20 +- .../trunk/components/http/httppatch.componentType | 1 + sca-cpp/trunk/components/http/httppatch.cpp | 20 +- .../trunk/components/http/httppost.componentType | 1 + sca-cpp/trunk/components/http/httppost.cpp | 20 +- .../trunk/components/http/httpput.componentType | 1 + sca-cpp/trunk/components/http/httpput.cpp | 20 +- sca-cpp/trunk/components/log/client-test.cpp | 10 +- sca-cpp/trunk/components/smtp/client-test.cpp | 2 +- sca-cpp/trunk/components/smtp/smtppost.cpp | 34 +- sca-cpp/trunk/components/sqldb/client-test.cpp | 8 +- sca-cpp/trunk/hosting/server/client-test.hpp | 436 +++++++++++++++++++++ .../server/data/apps/testhttp/app.composite | 7 + .../server/data/apps/testlogic/app.composite | 1 + .../server/data/apps/testsearch/app.composite | 1 + .../hosting/server/data/apps/twsms/app.composite | 1 + .../server/data/palettes/http/palette.composite | 5 + sca-cpp/trunk/modules/http/curl-connect.cpp | 2 +- sca-cpp/trunk/modules/http/curl-get.cpp | 2 +- sca-cpp/trunk/modules/http/curl-test.cpp | 7 +- sca-cpp/trunk/modules/http/http.hpp | 126 ++++-- sca-cpp/trunk/modules/http/mod-ssltunnel.cpp | 8 +- sca-cpp/trunk/modules/server/client-test.hpp | 30 +- 32 files changed, 700 insertions(+), 134 deletions(-) create mode 100644 sca-cpp/trunk/hosting/server/client-test.hpp (limited to 'sca-cpp') diff --git a/sca-cpp/trunk/components/cache/client-test.cpp b/sca-cpp/trunk/components/cache/client-test.cpp index b652ad3a88..63d1691f8b 100644 --- a/sca-cpp/trunk/components/cache/client-test.cpp +++ b/sca-cpp/trunk/components/cache/client-test.cpp @@ -43,7 +43,7 @@ const string partition1uri("http://localhost:8090/partitioner/a"); const string partition2uri("http://localhost:8090/partitioner/b"); bool testCache(const string& uri) { - http::CURLSession cs("", "", "", ""); + http::CURLSession cs("", "", "", "", 0); const list i = list() + "content" + (list() + "item" + (list() + "name" + string("Apple")) @@ -103,7 +103,7 @@ bool testDatacache() { } bool testMemocache() { - http::CURLSession cs("", "", "", ""); + http::CURLSession cs("", "", "", "", 0); const failable res = http::evalExpr(mklist(string("add"), 33, 22), memocacheuri, cs); assert(hasContent(res)); @@ -117,7 +117,7 @@ bool testMemocache() { } bool testPartitioner() { - http::CURLSession cs("", "", "", ""); + http::CURLSession cs("", "", "", "", 0); const failable res1 = http::get(partition1uri, cs); assert(hasContent(res1)); @@ -133,8 +133,8 @@ bool testPartitioner() { struct getLoop { const string path; const value entry; - http::CURLSession cs; - getLoop(const string& path, const value& entry, http::CURLSession cs) : path(path), entry(entry), cs(cs) { + http::CURLSession& cs; + getLoop(const string& path, const value& entry, http::CURLSession& cs) : path(path), entry(entry), cs(cs) { } const bool operator()() const { const failable val = http::get(memcacheuri + path, cs); @@ -153,7 +153,7 @@ bool testGetPerf() { + (list() + "id" + string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b")) + i); - http::CURLSession cs("", "", "", ""); + http::CURLSession cs("", "", "", "", 0); const failable id = http::post(a, memcacheuri, cs); assert(hasContent(id)); const string p = path(content(id)); diff --git a/sca-cpp/trunk/components/chat/client-test.cpp b/sca-cpp/trunk/components/chat/client-test.cpp index 9595194fe9..220382fa89 100644 --- a/sca-cpp/trunk/components/chat/client-test.cpp +++ b/sca-cpp/trunk/components/chat/client-test.cpp @@ -86,7 +86,7 @@ bool testListen() { bool testPost() { gc_scoped_pool pool; - http::CURLSession ch("", "", "", ""); + http::CURLSession ch("", "", "", "", 0); const failable id = http::post(entry, "http://localhost:8090/print-sender/sca2@localhost", ch); assert(hasContent(id)); return true; diff --git a/sca-cpp/trunk/components/constdb/client-test.cpp b/sca-cpp/trunk/components/constdb/client-test.cpp index 766e1d2583..ea45762cd6 100644 --- a/sca-cpp/trunk/components/constdb/client-test.cpp +++ b/sca-cpp/trunk/components/constdb/client-test.cpp @@ -39,7 +39,7 @@ namespace constdb { const string uri("http://localhost:8090/constdb"); bool testConstDb() { - http::CURLSession cs("", "", "", ""); + http::CURLSession cs("", "", "", "", 0); const list i = list() + "content" + (list() + "item" + (list() + "name" + string("Apple")) @@ -93,8 +93,8 @@ bool testConstDb() { struct getLoop { const string path; const value entry; - http::CURLSession cs; - getLoop(const string& path, const value& entry, http::CURLSession cs) : path(path), entry(entry), cs(cs) { + http::CURLSession& cs; + getLoop(const string& path, const value& entry, http::CURLSession& cs) : path(path), entry(entry), cs(cs) { } const bool operator()() const { const failable val = http::get(uri + path, cs); @@ -113,7 +113,7 @@ bool testGetPerf() { + (list() + "id" + string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b")) + i); - http::CURLSession cs("", "", "", ""); + http::CURLSession cs("", "", "", "", 0); const failable id = http::post(a, uri, cs); assert(hasContent(id)); const string p = path(content(id)); diff --git a/sca-cpp/trunk/components/filedb/client-test.cpp b/sca-cpp/trunk/components/filedb/client-test.cpp index 19f76c22fe..e0f98d8c3b 100644 --- a/sca-cpp/trunk/components/filedb/client-test.cpp +++ b/sca-cpp/trunk/components/filedb/client-test.cpp @@ -39,7 +39,7 @@ namespace filedb { const string uri("http://localhost:8090/filedb"); bool testFileDB() { - http::CURLSession cs("", "", "", ""); + http::CURLSession cs("", "", "", "", 0); const list i = list() + "content" + (list() + "item" + (list() + "name" + string("Apple")) @@ -93,8 +93,8 @@ bool testFileDB() { struct getLoop { const string path; const value entry; - http::CURLSession cs; - getLoop(const string& path, const value& entry, http::CURLSession cs) : path(path), entry(entry), cs(cs) { + http::CURLSession& cs; + getLoop(const string& path, const value& entry, http::CURLSession& cs) : path(path), entry(entry), cs(cs) { } const bool operator()() const { const failable val = http::get(uri + path, cs); @@ -113,7 +113,7 @@ bool testGetPerf() { + (list() + "id" + string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b")) + i); - http::CURLSession cs("", "", "", ""); + http::CURLSession cs("", "", "", "", 0); const failable id = http::post(a, uri, cs); assert(hasContent(id)); const string p = path(content(id)); diff --git a/sca-cpp/trunk/components/http/client-test.cpp b/sca-cpp/trunk/components/http/client-test.cpp index c040ed39df..bb1918f1f8 100644 --- a/sca-cpp/trunk/components/http/client-test.cpp +++ b/sca-cpp/trunk/components/http/client-test.cpp @@ -42,7 +42,7 @@ const string putURI("http://localhost:8090/httpput"); const string deleteURI("http://localhost:8090/httpdelete"); bool testGet() { - http::CURLSession cs("", "", "", ""); + http::CURLSession cs("", "", "", "", 0); const failable val = http::get(getURI, cs); assert(hasContent(val)); @@ -50,8 +50,8 @@ bool testGet() { } struct getLoop { - http::CURLSession cs; - getLoop(http::CURLSession cs) : cs(cs) { + http::CURLSession& cs; + getLoop(http::CURLSession& cs) : cs(cs) { } const bool operator()() const { const failable val = http::get(getURI, cs); @@ -61,7 +61,7 @@ struct getLoop { }; bool testGetPerf() { - http::CURLSession cs("", "", "", ""); + http::CURLSession cs("", "", "", "", 0); const lambda gl = getLoop(cs); cout << "HTTP get test " << time(gl, 5, 200) << " ms" << endl; @@ -70,7 +70,7 @@ bool testGetPerf() { } bool testPost() { - http::CURLSession cs("", "", "", ""); + http::CURLSession cs("", "", "", "", 0); const failable val = http::get(postURI, cs); assert(hasContent(val)); @@ -78,7 +78,7 @@ bool testPost() { } bool testPut() { - http::CURLSession cs("", "", "", ""); + http::CURLSession cs("", "", "", "", 0); const failable val = http::get(putURI, cs); assert(hasContent(val)); @@ -86,7 +86,7 @@ bool testPut() { } bool testDelete() { - http::CURLSession cs("", "", "", ""); + http::CURLSession cs("", "", "", "", 0); const failable val = http::get(deleteURI, cs); assert(hasContent(val)); diff --git a/sca-cpp/trunk/components/http/http.composite b/sca-cpp/trunk/components/http/http.composite index ea0adedf51..32c0da62c0 100644 --- a/sca-cpp/trunk/components/http/http.composite +++ b/sca-cpp/trunk/components/http/http.composite @@ -23,6 +23,7 @@ + 0 @@ -31,6 +32,7 @@ + 0 @@ -40,6 +42,7 @@ + 0 @@ -49,6 +52,7 @@ + 0 @@ -58,6 +62,7 @@ + 0 diff --git a/sca-cpp/trunk/components/http/httpdelete.componentType b/sca-cpp/trunk/components/http/httpdelete.componentType index 34e2a60632..c2d728a538 100644 --- a/sca-cpp/trunk/components/http/httpdelete.componentType +++ b/sca-cpp/trunk/components/http/httpdelete.componentType @@ -22,6 +22,7 @@ xmlns:t="http://tuscany.apache.org/xmlns/sca/1.1" targetNamespace="http://tuscany.apache.org/xmlns/sca/components"> + diff --git a/sca-cpp/trunk/components/http/httpdelete.cpp b/sca-cpp/trunk/components/http/httpdelete.cpp index d78a4d60df..c725461ec2 100644 --- a/sca-cpp/trunk/components/http/httpdelete.cpp +++ b/sca-cpp/trunk/components/http/httpdelete.cpp @@ -37,7 +37,7 @@ namespace httpdelete { /** * Evaluate an HTTP delete. */ -const failable get(const lambda&)> url, http::CURLSession& ch) { +const failable get(const lambda&)>& url, http::CURLSession& ch) { debug("httpdelete::get"); const value u = url(mklist("get", list())); debug(u, "httpdelete::get::url"); @@ -49,7 +49,7 @@ const failable get(const lambda&)> url, http::CUR */ class applyhttp { public: - applyhttp(const lambda&)> url, const perthread_ptr& ch) : url(url), ch(ch) { + applyhttp(const lambda&)>& url, const perthread_ptr& ch) : url(url), ch(ch) { } const value operator()(const list& params) const { @@ -68,16 +68,24 @@ private: /** * Create a new CURL session. */ -const gc_ptr newsession() { - return new (gc_new()) http::CURLSession("", "", "", ""); -} +class newsession { +public: + newsession(const lambda&)>& timeout) : timeout(timeout) { + } + const gc_ptr operator()() const { + const int t = atoi(c_str((string)timeout(list()))); + return new (gc_new()) http::CURLSession("", "", "", "", t); + } +private: + const lambda&)> timeout; +}; /** * Start the component. */ const failable start(const list& params) { // Create a CURL session - const perthread_ptr ch = perthread_ptr(lambda()>(newsession)); + const perthread_ptr ch = perthread_ptr(lambda()>(newsession(cadr(params)))); // Return the component implementation lambda function return value(lambda&)>(applyhttp(car(params), ch))); diff --git a/sca-cpp/trunk/components/http/httpget.componentType b/sca-cpp/trunk/components/http/httpget.componentType index a45474b88d..c6c24fbed8 100644 --- a/sca-cpp/trunk/components/http/httpget.componentType +++ b/sca-cpp/trunk/components/http/httpget.componentType @@ -22,6 +22,7 @@ xmlns:t="http://tuscany.apache.org/xmlns/sca/1.1" targetNamespace="http://tuscany.apache.org/xmlns/sca/components"> + diff --git a/sca-cpp/trunk/components/http/httpget.cpp b/sca-cpp/trunk/components/http/httpget.cpp index 8515d6f41e..884dc1a6ff 100644 --- a/sca-cpp/trunk/components/http/httpget.cpp +++ b/sca-cpp/trunk/components/http/httpget.cpp @@ -38,7 +38,7 @@ namespace httpget { /** * Evaluate an HTTP get. */ -const failable get(const lambda&)> url, http::CURLSession& ch) { +const failable get(const lambda&)>& url, http::CURLSession& ch) { debug("httpget::get"); const value u = url(mklist("get", list())); debug(u, "httpget::get::url"); @@ -50,7 +50,7 @@ const failable get(const lambda&)> url, http::CUR */ class applyhttp { public: - applyhttp(const lambda&)> url, const perthread_ptr& ch) : url(url), ch(ch) { + applyhttp(const lambda&)>& url, const perthread_ptr& ch) : url(url), ch(ch) { } const value operator()(const list& params) const { @@ -70,16 +70,24 @@ private: /** * Create a new CURL session. */ -const gc_ptr newsession() { - return new (gc_new()) http::CURLSession("", "", "", ""); -} +class newsession { +public: + newsession(const lambda&)>& timeout) : timeout(timeout) { + } + const gc_ptr operator()() const { + const int t = atoi(c_str((string)timeout(list()))); + return new (gc_new()) http::CURLSession("", "", "", "", t); + } +private: + const lambda&)> timeout; +}; /** * Start the component. */ const failable start(const list& params) { // Create a CURL session - const perthread_ptr ch = perthread_ptr(lambda()>(newsession)); + const perthread_ptr ch = perthread_ptr(lambda()>(newsession(cadr(params)))); // Return the component implementation lambda function return value(lambda&)>(applyhttp(car(params), ch))); diff --git a/sca-cpp/trunk/components/http/httppatch.componentType b/sca-cpp/trunk/components/http/httppatch.componentType index 0ab5ecf45b..eb3a96078b 100644 --- a/sca-cpp/trunk/components/http/httppatch.componentType +++ b/sca-cpp/trunk/components/http/httppatch.componentType @@ -22,6 +22,7 @@ xmlns:t="http://tuscany.apache.org/xmlns/sca/1.1" targetNamespace="http://tuscany.apache.org/xmlns/sca/components"> + diff --git a/sca-cpp/trunk/components/http/httppatch.cpp b/sca-cpp/trunk/components/http/httppatch.cpp index 3e6f7af2c0..051b1e09ac 100644 --- a/sca-cpp/trunk/components/http/httppatch.cpp +++ b/sca-cpp/trunk/components/http/httppatch.cpp @@ -38,7 +38,7 @@ namespace httppatch { /** * Evaluate an HTTP patch. */ -const failable get(const lambda&)> url, const lambda&)> val, http::CURLSession& ch) { +const failable get(const lambda&)>& url, const lambda&)>& val, http::CURLSession& ch) { debug("httppatch::get"); const value u = url(mklist("get", list())); const value v = val(mklist("get", list())); @@ -52,7 +52,7 @@ const failable get(const lambda&)> url, const lam */ class applyhttp { public: - applyhttp(const lambda&)> url, const lambda&)> val, const perthread_ptr& ch) : url(url), val(val), ch(ch) { + applyhttp(const lambda&)>& url, const lambda&)>& val, const perthread_ptr& ch) : url(url), val(val), ch(ch) { } const value operator()(const list& params) const { @@ -72,16 +72,24 @@ private: /** * Create a new CURL session. */ -const gc_ptr newsession() { - return new (gc_new()) http::CURLSession("", "", "", ""); -} +class newsession { +public: + newsession(const lambda&)>& timeout) : timeout(timeout) { + } + const gc_ptr operator()() const { + const int t = atoi(c_str((string)timeout(list()))); + return new (gc_new()) http::CURLSession("", "", "", "", t); + } +private: + const lambda&)> timeout; +}; /** * Start the component. */ const failable start(const list& params) { // Create a CURL session - const perthread_ptr ch = perthread_ptr(lambda()>(newsession)); + const perthread_ptr ch = perthread_ptr(lambda()>(newsession(caddr(params)))); // Return the component implementation lambda function return value(lambda&)>(applyhttp(car(params), cadr(params), ch))); diff --git a/sca-cpp/trunk/components/http/httppost.componentType b/sca-cpp/trunk/components/http/httppost.componentType index 2cb7310332..42b0096446 100644 --- a/sca-cpp/trunk/components/http/httppost.componentType +++ b/sca-cpp/trunk/components/http/httppost.componentType @@ -22,6 +22,7 @@ xmlns:t="http://tuscany.apache.org/xmlns/sca/1.1" targetNamespace="http://tuscany.apache.org/xmlns/sca/components"> + diff --git a/sca-cpp/trunk/components/http/httppost.cpp b/sca-cpp/trunk/components/http/httppost.cpp index 8d0f526bdc..84fd984e19 100644 --- a/sca-cpp/trunk/components/http/httppost.cpp +++ b/sca-cpp/trunk/components/http/httppost.cpp @@ -38,7 +38,7 @@ namespace httppost { /** * Evaluate an HTTP post. */ -const failable get(const lambda&)> url, const lambda&)> val, http::CURLSession& ch) { +const failable get(const lambda&)>& url, const lambda&)>& val, http::CURLSession& ch) { debug("httppost::get"); const value u = url(mklist("get", list())); const value v = val(mklist("get", list())); @@ -52,7 +52,7 @@ const failable get(const lambda&)> url, const lam */ class applyhttp { public: - applyhttp(const lambda&)> url, const lambda&)> val, const perthread_ptr& ch) : url(url), val(val), ch(ch) { + applyhttp(const lambda&)>& url, const lambda&)>& val, const perthread_ptr& ch) : url(url), val(val), ch(ch) { } const value operator()(const list& params) const { @@ -72,16 +72,24 @@ private: /** * Create a new CURL session. */ -const gc_ptr newsession() { - return new (gc_new()) http::CURLSession("", "", "", ""); -} +class newsession { +public: + newsession(const lambda&)>& timeout) : timeout(timeout) { + } + const gc_ptr operator()() const { + const int t = atoi(c_str((string)timeout(list()))); + return new (gc_new()) http::CURLSession("", "", "", "", t); + } +private: + const lambda&)> timeout; +}; /** * Start the component. */ const failable start(const list& params) { // Create a CURL session - const perthread_ptr ch = perthread_ptr(lambda()>(newsession)); + const perthread_ptr ch = perthread_ptr(lambda()>(newsession(caddr(params)))); // Return the component implementation lambda function return value(lambda&)>(applyhttp(car(params), cadr(params), ch))); diff --git a/sca-cpp/trunk/components/http/httpput.componentType b/sca-cpp/trunk/components/http/httpput.componentType index 654bb5e82f..791a7faa8a 100644 --- a/sca-cpp/trunk/components/http/httpput.componentType +++ b/sca-cpp/trunk/components/http/httpput.componentType @@ -22,6 +22,7 @@ xmlns:t="http://tuscany.apache.org/xmlns/sca/1.1" targetNamespace="http://tuscany.apache.org/xmlns/sca/components"> + diff --git a/sca-cpp/trunk/components/http/httpput.cpp b/sca-cpp/trunk/components/http/httpput.cpp index c157ee32cc..2ae5da396e 100644 --- a/sca-cpp/trunk/components/http/httpput.cpp +++ b/sca-cpp/trunk/components/http/httpput.cpp @@ -38,7 +38,7 @@ namespace httpput { /** * Evaluate an HTTP put. */ -const failable get(const lambda&)> url, const lambda&)> val, http::CURLSession& ch) { +const failable get(const lambda&)>& url, const lambda&)>& val, http::CURLSession& ch) { debug("httpput::get"); const value u = url(mklist("get", list())); const value v = val(mklist("get", list())); @@ -52,7 +52,7 @@ const failable get(const lambda&)> url, const lam */ class applyhttp { public: - applyhttp(const lambda&)> url, const lambda&)> val, const perthread_ptr& ch) : url(url), val(val), ch(ch) { + applyhttp(const lambda&)>& url, const lambda&)>& val, const perthread_ptr& ch) : url(url), val(val), ch(ch) { } const value operator()(const list& params) const { @@ -72,16 +72,24 @@ private: /** * Create a new CURL session. */ -const gc_ptr newsession() { - return new (gc_new()) http::CURLSession("", "", "", ""); -} +class newsession { +public: + newsession(const lambda&)>& timeout) : timeout(timeout) { + } + const gc_ptr operator()() const { + const int t = atoi(c_str((string)timeout(list()))); + return new (gc_new()) http::CURLSession("", "", "", "", t); + } +private: + const lambda&)> timeout; +}; /** * Start the component. */ const failable start(const list& params) { // Create a CURL session - const perthread_ptr ch = perthread_ptr(lambda()>(newsession)); + const perthread_ptr ch = perthread_ptr(lambda()>(newsession(caddr(params)))); // Return the component implementation lambda function return value(lambda&)>(applyhttp(car(params), cadr(params), ch))); diff --git a/sca-cpp/trunk/components/log/client-test.cpp b/sca-cpp/trunk/components/log/client-test.cpp index c67d3a4b27..d8cac5ee81 100644 --- a/sca-cpp/trunk/components/log/client-test.cpp +++ b/sca-cpp/trunk/components/log/client-test.cpp @@ -39,7 +39,7 @@ namespace log { const string uri("http://localhost:8090/log"); bool testLog() { - http::CURLSession cs("", "", "", ""); + http::CURLSession cs("", "", "", "", 0); const list i = list() + "content" + (list() + "item" + (list() + "name" + string("Apple")) @@ -58,8 +58,8 @@ bool testLog() { struct logLoop { const value a; const string uri; - http::CURLSession cs; - logLoop(const value& a, const string& uri, http::CURLSession cs) : a(a), uri(uri), cs(cs) { + http::CURLSession& cs; + logLoop(const value& a, const string& uri, http::CURLSession& cs) : a(a), uri(uri), cs(cs) { } const bool operator()() const { const failable id = http::post(a, uri, cs); @@ -77,7 +77,7 @@ bool testLogPerf() { + (list() + "id" + string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b")) + i); - http::CURLSession cs("", "", "", ""); + http::CURLSession cs("", "", "", "", 0); const failable id = http::post(a, uri, cs); assert(hasContent(id)); @@ -88,7 +88,7 @@ bool testLogPerf() { } bool testLogger() { - http::CURLSession cs("", "", "", ""); + http::CURLSession cs("", "", "", "", 0); const failable res = http::evalExpr(mklist(string("sum"), 33, 22), string("http://localhost:8090/client"), cs); assert(hasContent(res)); diff --git a/sca-cpp/trunk/components/smtp/client-test.cpp b/sca-cpp/trunk/components/smtp/client-test.cpp index 216861d35e..10274a6248 100644 --- a/sca-cpp/trunk/components/smtp/client-test.cpp +++ b/sca-cpp/trunk/components/smtp/client-test.cpp @@ -39,7 +39,7 @@ namespace smtp { const string postURI("http://localhost:8090/smtppost"); bool testPost() { - http::CURLSession cs("", "", "", ""); + http::CURLSession cs("", "", "", "", 0); const failable val = http::get(postURI, cs); assert(hasContent(val)); diff --git a/sca-cpp/trunk/components/smtp/smtppost.cpp b/sca-cpp/trunk/components/smtp/smtppost.cpp index db2ac9ef18..1030ccc223 100644 --- a/sca-cpp/trunk/components/smtp/smtppost.cpp +++ b/sca-cpp/trunk/components/smtp/smtppost.cpp @@ -38,7 +38,7 @@ namespace smtppost { /** * Post/send an email message using SMTP. */ -const failable post(const string& url, const string& user, const string& pass, const string& from, const string& to, const string& subject, const value& val, const http::CURLSession& cs) { +const failable post(const string& url, const string& user, const string& pass, const string& from, const string& to, const string& subject, const value& val, http::CURLSession& cs) { // Convert value to a content request const failable > > freq = http::contentRequest(val, url); if (!hasContent(freq)) @@ -48,8 +48,10 @@ const failable post(const string& url, const string& user, const string& // Setup the CURL session const failable fch = http::setup(url, cs); - if (!hasContent(fch)) + if (!hasContent(fch)) { + http::cleanup(cs); return mkfailure(fch); + } CURL* ch = content(fch); curl_easy_setopt(ch, CURLOPT_USE_SSL, (long)CURLUSESSL_ALL); @@ -80,18 +82,22 @@ const failable post(const string& url, const string& user, const string& curl_slist_free_all(rcpt); // Return the CURL return code or true - if (rc) + if (rc) { + http::cleanup(cs); return mkfailure(string(curl_easy_strerror(rc))); + } + + http::cleanup(cs); return value(true); } /** * Evaluate an SMTP post/send. */ -const failable get(const lambda&)> url, - const lambda&)> user, const lambda&)> pass, - const lambda&)> from, const lambda&)> to, - const lambda&)> subject, const lambda&)> val, +const failable get(const lambda&)>& url, + const lambda&)>& user, const lambda&)>& pass, + const lambda&)>& from, const lambda&)>& to, + const lambda&)>& subject, const lambda&)>& val, http::CURLSession& ch) { debug("smtppost::get"); const value u = url(mklist("get", list())); @@ -116,11 +122,11 @@ const failable get(const lambda&)> url, */ class applysmtp { public: - applysmtp(const lambda&)> url, - const lambda&)> user, const lambda&)> pass, - const lambda&)> from, const lambda&)> to, - const lambda&)> subject, const lambda&)> val, - const perthread_ptr& ch) : + applysmtp(const lambda&)>& url, + const lambda&)>& user, const lambda&)>& pass, + const lambda&)>& from, const lambda&)>& to, + const lambda&)>& subject, const lambda&)>& val, + perthread_ptr& ch) : url(url), user(user), pass(pass), from(from), to(to), subject(subject), val(val), ch(ch) { } @@ -147,7 +153,7 @@ private: * Create a new CURL session. */ const gc_ptr newsession() { - return new (gc_new()) http::CURLSession("", "", "", ""); + return new (gc_new()) http::CURLSession("", "", "", "", 0); } /** @@ -155,7 +161,7 @@ const gc_ptr newsession() { */ const failable start(const list& params) { // Create a CURL session - const perthread_ptr ch = perthread_ptr(lambda()>(newsession)); + perthread_ptr ch = perthread_ptr(lambda()>(newsession)); // Return the component implementation lambda function return value(lambda&)>(applysmtp(car(params), cadr(params), caddr(params), cadddr(params), caddddr(params), cadddddr(params), caddddddr(params), ch))); diff --git a/sca-cpp/trunk/components/sqldb/client-test.cpp b/sca-cpp/trunk/components/sqldb/client-test.cpp index d5f07de969..0cbcb57363 100644 --- a/sca-cpp/trunk/components/sqldb/client-test.cpp +++ b/sca-cpp/trunk/components/sqldb/client-test.cpp @@ -39,7 +39,7 @@ namespace sqldb { const string uri("http://localhost:8090/sqldb"); bool testSqlDb() { - http::CURLSession cs("", "", "", ""); + http::CURLSession cs("", "", "", "", 0); const list i = list() + "content" + (list() + "item" + (list() + "name" + string("Apple")) @@ -93,8 +93,8 @@ bool testSqlDb() { struct getLoop { const string path; const value entry; - http::CURLSession cs; - getLoop(const string& path, const value& entry, http::CURLSession cs) : path(path), entry(entry), cs(cs) { + http::CURLSession& cs; + getLoop(const string& path, const value& entry, http::CURLSession& cs) : path(path), entry(entry), cs(cs) { } const bool operator()() const { const failable val = http::get(uri + path, cs); @@ -113,7 +113,7 @@ bool testGetPerf() { + (list() + "id" + string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b")) + i); - http::CURLSession cs("", "", "", ""); + http::CURLSession cs("", "", "", "", 0); const failable id = http::post(a, uri, cs); assert(hasContent(id)); const string p = path(content(id)); diff --git a/sca-cpp/trunk/hosting/server/client-test.hpp b/sca-cpp/trunk/hosting/server/client-test.hpp new file mode 100644 index 0000000000..7d85fc99a6 --- /dev/null +++ b/sca-cpp/trunk/hosting/server/client-test.hpp @@ -0,0 +1,436 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +/* $Rev$ $Date$ */ + +/** + * Test HTTP client functions. + */ + +#include +#include +#include +#include +#include "stream.hpp" +#include "string.hpp" +#include "parallel.hpp" +#include "perf.hpp" +#include "../../modules/http/http.hpp" + +namespace tuscany { +namespace server { + +string testURI = "http://localhost:8090"; +bool testBlobs = true; + +ostream* curlWriter(const string& s, ostream* os) { + (*os) << s; + return os; +} + +const bool testGetDoc() { + gc_scoped_pool pool; + http::CURLSession ch("", "", "", "", 0); + { + ostringstream os; + const failable > r = http::get(curlWriter, &os, testURI + "/", ch); + assert(hasContent(r)); + assert(contains(str(os), "HTTP/1.1 200") || contains(str(os), "HTTP/1.0 200")); + assert(contains(str(os), "")); + } + { + const failable r = http::getcontent(testURI + "/", ch); + assert(hasContent(r)); + assert(contains(car(list(content(r))), "")); + } + return true; +} + +struct getDocLoop { + http::CURLSession& ch; + getDocLoop(http::CURLSession& ch) : ch(ch) { + } + const bool operator()() const { + const failable r = http::getcontent(testURI + "/", ch); + assert(hasContent(r)); + assert(contains(car(list(content(r))), "")); + return true; + } +}; + +const bool testGetDocPerf() { + gc_scoped_pool pool; + http::CURLSession ch("", "", "", "", 0); + const lambda gl = getDocLoop(ch); + cout << "GET doc test " << time(gl, 10, 50) << " ms" << endl; + return true; +} + +struct getCompositeLoop { + http::CURLSession& ch; + getCompositeLoop(http::CURLSession& ch) : ch(ch) { + } + const bool operator()() const { + const failable r = http::getcontent(testURI + "/r/Editor/composites/test", ch); + assert(hasContent(r)); + return true; + } +}; + +const bool testGetCompositePerf() { + gc_scoped_pool pool; + http::CURLSession ch("", "", "", "", 0); + const lambda gl = getCompositeLoop(ch); + cout << "GET composite test " << time(gl, 10, 50) << " ms" << endl; + return true; +} + +struct getPageLoop { + http::CURLSession& ch; + getPageLoop(http::CURLSession& ch) : ch(ch) { + } + const bool operator()() const { + const failable r = http::getcontent(testURI + "/r/Editor/pages/test", ch); + assert(hasContent(r)); + return true; + } +}; + +const bool testGetPagePerf() { + gc_scoped_pool pool; + http::CURLSession ch("", "", "", "", 0); + const lambda gl = getPageLoop(ch); + cout << "GET page test " << time(gl, 10, 50) << " ms" << endl; + return true; +} + +struct getAppLoop { + http::CURLSession& ch; + getAppLoop(http::CURLSession& ch) : ch(ch) { + } + const bool operator()() const { + const failable r = http::getcontent(testURI + "/r/Editor/apps/test", ch); + assert(hasContent(r)); + return true; + } +}; + +const bool testGetAppPerf() { + gc_scoped_pool pool; + http::CURLSession ch("", "", "", "", 0); + const lambda gl = getAppLoop(ch); + cout << "GET app test " << time(gl, 10, 50) << " ms" << endl; + return true; +} + +const bool testEval() { + gc_scoped_pool pool; + http::CURLSession ch("", "", "", "", 0); + const failable r = http::evalExpr(mklist(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 r = http::evalExpr(mklist(string("echo"), string("Hello")), uri, ch); + assert(hasContent(r)); + assert(content(r) == string("Hello")); + return true; + } +}; + +const value blob(string(2048, 'A')); +const list 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 r = content(http::evalExpr(mklist(string("echo"), blobs), uri, ch)); + assert(hasContent(r)); + assert(content(r) == blobs); + return true; + } +}; + +const bool testEvalPerf() { + gc_scoped_pool pool; + http::CURLSession ch("", "", "", "", 0); + const lambda el = evalLoop(testURI, ch); + cout << "JSON-RPC eval echo test " << time(el, 5, 200) << " ms" << endl; + + if (testBlobs) { + const lambda bel = blobEvalLoop(testURI, ch); + cout << "JSON-RPC eval blob test " << time(bel, 5, 200) << " ms" << endl; + } + return true; +} + +bool testPost() { + gc_scoped_pool pool; + const list i = list() + "content" + (list() + "item" + + (list() + "name" + string("Apple")) + + (list() + "price" + string("$2.99"))); + const list a = list() + (list() + "entry" + + (list() + "title" + string("item")) + + (list() + "id" + string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b")) + + i); + http::CURLSession ch("", "", "", "", 0); + const failable 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 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 id = http::post(val, uri, ch); + assert(hasContent(id)); + return true; + } +}; + +const bool testPostPerf() { + gc_scoped_pool pool; + http::CURLSession ch("", "", "", "", 0); + { + const list i = list() + "content" + (list() + "item" + + (list() + "name" + string("Apple")) + + (list() + "price" + string("$2.99"))); + const list val = list() + (list() + "entry" + + (list() + "title" + string("item")) + + (list() + "id" + string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b")) + + i); + const lambda pl = postLoop(testURI, val, ch); + cout << "ATOMPub POST small test " << time(pl, 5, 200) << " ms" << endl; + } + if (testBlobs) { + const list i = list() + "content" + (list() + "item" + + (list() + "name" + string("Apple")) + + (list() + "blob1" + blob) + + (list() + "blob2" + blob) + + (list() + "price" + string("$2.99"))); + const list val = list() + (list() + "entry" + + (list() + "title" + string("item")) + + (list() + "id" + string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b")) + + i); + const lambda pl = postBlobLoop(testURI, val, ch); + cout << "ATOMPub POST blob test " << time(pl, 5, 200) << " ms" << endl; + } + 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 pl = postLoop(uri, val, ch); + time(pl, 0, count); + return true; +} + +const list > startPost(worker& w, const int threads, const lambda& l) { + if (threads == 0) + return list >(); + return cons(submit(w, l), startPost(w, threads - 1, l)); +} + +const bool checkPost(const list >& r) { + if (isNil(r)) + return true; + assert(car(r) == true); + return checkPost(cdr(r)); +} + +struct postThreadLoop { + const lambda l; + worker& w; + const int threads; + postThreadLoop(const lambda& l, worker& w, const int threads) : l(l), w(w), threads(threads) { + } + const bool operator()() const { + list > r = startPost(w, threads, l); + checkPost(r); + return true; + } +}; + +const bool testPostThreadPerf() { + gc_scoped_pool pool; + const int count = 50; + const int threads = 10; + worker w(threads); + + const list i = list() + "content" + (list() + "item" + + (list() + "name" + string("Apple")) + + (list() + "price" + string("$2.99"))); + const value val = list() + (list() + "entry" + + (list() + "title" + string("item")) + + (list() + "id" + string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b")) + + i); + + const lambda pl= curry(lambda(postThread), testURI, count, val); + const lambda ptl = postThreadLoop(pl, w, threads); + double t = time(ptl, 0, 1) / (threads * count); + cout << "ATOMPub POST thread test " << t << " ms" << endl; + + return true; +} + +#else + +const bool postProc(const string& uri, const int count, const value& val) { + gc_scoped_pool pool; + http::CURLSession ch("", "", "", "", 0); + const lambda pl = postLoop(uri, val, ch); + time(pl, 0, count); + return true; +} + +const list startPost(const int procs, const lambda& l) { + if (procs == 0) + return list(); + pid_t pid = fork(); + if (pid == 0) { + assert(l() == true); + exit(0); + } + return cons(pid, startPost(procs - 1, l)); +} + +const bool checkPost(const list& r) { + if (isNil(r)) + return true; + int status; + waitpid(car(r), &status, 0); + assert(status == 0); + return checkPost(cdr(r)); +} + +struct postForkLoop { + const lambda l; + const int procs; + postForkLoop(const lambda& l, const int procs) : l(l), procs(procs) { + } + const bool operator()() const { + list r = startPost(procs, l); + checkPost(r); + return true; + } +}; + +const bool testPostForkPerf() { + gc_scoped_pool pool; + const int count = 50; + const int procs = 10; + + const list i = list() + "content" + (list() + "item" + + (list() + "name" + string("Apple")) + + (list() + "price" + string("$2.99"))); + const value val = list() + (list() + "entry" + + (list() + "title" + string("item")) + + (list() + "id" + string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b")) + + i); + + const lambda pl= curry(lambda(postProc), testURI, count, val); + const lambda ptl = postForkLoop(pl, procs); + double t = time(ptl, 0, 1) / (procs * count); + cout << "ATOMPub POST fork test " << t << " ms" << endl; + + return true; +} + +#endif + +const bool testPut() { + gc_scoped_pool pool; + const list i = list() + "content" + (list() + "item" + + (list() + "name" + string("Apple")) + + (list() + "price" + string("$2.99"))); + const list a = list() + (list() + "entry" + + (list() + "title" + string("item")) + + (list() + "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)); + 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)); + return true; +} + +const bool testServer() { + tuscany::server::testGetDoc(); +#ifdef FOO + tuscany::server::testPost(); + tuscany::server::testPut(); + tuscany::server::testDel(); + tuscany::server::testEval(); +#endif + tuscany::server::testGetDocPerf(); + tuscany::server::testGetCompositePerf(); + tuscany::server::testGetPagePerf(); + tuscany::server::testGetAppPerf(); +#ifdef FOO + tuscany::server::testPostPerf(); +#ifdef WANT_THREADS + tuscany::server::testPostThreadPerf(); +#else + tuscany::server::testPostForkPerf(); +#endif + tuscany::server::testEvalPerf(); +#endif + return true; +} + +} +} diff --git a/sca-cpp/trunk/hosting/server/data/apps/testhttp/app.composite b/sca-cpp/trunk/hosting/server/data/apps/testhttp/app.composite index a252a2ca64..aa78b576d0 100644 --- a/sca-cpp/trunk/hosting/server/data/apps/testhttp/app.composite +++ b/sca-cpp/trunk/hosting/server/data/apps/testhttp/app.composite @@ -51,36 +51,43 @@ + + + + + + + diff --git a/sca-cpp/trunk/hosting/server/data/apps/testlogic/app.composite b/sca-cpp/trunk/hosting/server/data/apps/testlogic/app.composite index db63d75b82..d838773839 100644 --- a/sca-cpp/trunk/hosting/server/data/apps/testlogic/app.composite +++ b/sca-cpp/trunk/hosting/server/data/apps/testlogic/app.composite @@ -64,6 +64,7 @@ + diff --git a/sca-cpp/trunk/hosting/server/data/apps/testsearch/app.composite b/sca-cpp/trunk/hosting/server/data/apps/testsearch/app.composite index d1411b5bea..6c2ba82131 100644 --- a/sca-cpp/trunk/hosting/server/data/apps/testsearch/app.composite +++ b/sca-cpp/trunk/hosting/server/data/apps/testsearch/app.composite @@ -51,6 +51,7 @@ + diff --git a/sca-cpp/trunk/hosting/server/data/apps/twsms/app.composite b/sca-cpp/trunk/hosting/server/data/apps/twsms/app.composite index 7c30c38e93..e8b2e27584 100644 --- a/sca-cpp/trunk/hosting/server/data/apps/twsms/app.composite +++ b/sca-cpp/trunk/hosting/server/data/apps/twsms/app.composite @@ -102,6 +102,7 @@ + diff --git a/sca-cpp/trunk/hosting/server/data/palettes/http/palette.composite b/sca-cpp/trunk/hosting/server/data/palettes/http/palette.composite index 13f92e8954..f4d0c2bdf5 100644 --- a/sca-cpp/trunk/hosting/server/data/palettes/http/palette.composite +++ b/sca-cpp/trunk/hosting/server/data/palettes/http/palette.composite @@ -40,6 +40,7 @@ + @@ -50,6 +51,7 @@ + @@ -77,6 +79,7 @@ + @@ -88,12 +91,14 @@ + + diff --git a/sca-cpp/trunk/modules/http/curl-connect.cpp b/sca-cpp/trunk/modules/http/curl-connect.cpp index 0bb193623f..9f5ee17368 100644 --- a/sca-cpp/trunk/modules/http/curl-connect.cpp +++ b/sca-cpp/trunk/modules/http/curl-connect.cpp @@ -36,7 +36,7 @@ namespace http { const bool testConnect(const string& url, const string& ca = "", const string& cert = "", const string& key = "") { gc_scoped_pool p; - CURLSession cs(ca, cert, key, ""); + CURLSession cs(ca, cert, key, "", 0); const failable crc = connect(url, cs); assert(hasContent(crc)); diff --git a/sca-cpp/trunk/modules/http/curl-get.cpp b/sca-cpp/trunk/modules/http/curl-get.cpp index cd575ccc66..a16daeeae3 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, ""); + CURLSession ch(ca, cert, key, "", 0); const failable val = get(url, ch); assert(hasContent(val)); cout << content(val) << endl; diff --git a/sca-cpp/trunk/modules/http/curl-test.cpp b/sca-cpp/trunk/modules/http/curl-test.cpp index 2a1803b873..f0806ea577 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("", "", "", ""); + CURLSession ch("", "", "", "", 0); { ostringstream os; const failable > r = get(curlWriter, &os, testURI, ch); @@ -69,7 +69,7 @@ struct getLoop { }; const bool testGetPerf() { - CURLSession ch("", "", "", ""); + CURLSession ch("", "", "", "", 0); lambda gl = getLoop(ch); cout << "Static GET test " << time(gl, 5, 200) << " ms" << endl; return true; @@ -79,8 +79,9 @@ const bool testGetPerf() { } int main() { + tuscany::gc_scoped_pool p; tuscany::cout << "Testing..." << tuscany::endl; - tuscany::http::testURI = tuscany::string("http://") + tuscany::http::hostName() + ":8090"; + //tuscany::http::testURI = tuscany::string("http://") + tuscany::http::hostName() + ":8090"; tuscany::http::testGet(); tuscany::http::testGetPerf(); diff --git a/sca-cpp/trunk/modules/http/http.hpp b/sca-cpp/trunk/modules/http/http.hpp index e8c88f8a83..408b9fdee5 100644 --- a/sca-cpp/trunk/modules/http/http.hpp +++ b/sca-cpp/trunk/modules/http/http.hpp @@ -71,13 +71,32 @@ public: */ class CURLSession { public: - CURLSession() : h(NULL), p(NULL), sock(NULL), wpollset(NULL), wpollfd(NULL), rpollset(NULL), rpollfd(NULL), owner(false), ca(""), cert(""), key(""), cookie("") { + CURLSession() : h(NULL), p(), sock(NULL), wpollset(NULL), wpollfd(NULL), rpollset(NULL), rpollfd(NULL), owner(false), ca(""), cert(""), key(""), cookie(""), timeout(0) { } - CURLSession(const string& ca, const string& cert, const string& key, const string& cookie) : h(curl_easy_init()), p(gc_pool(mkpool())), sock(NULL), wpollset(NULL), wpollfd(NULL), rpollset(NULL), rpollfd(NULL), owner(true), ca(ca), cert(cert), key(key), cookie(cookie) { + 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 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) { + 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) { + } + + 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() { @@ -86,12 +105,11 @@ public: if (h == NULL) return; curl_easy_cleanup(h); - destroy(p); } private: CURL* h; - gc_pool p; + gc_child_pool p; apr_socket_t* sock; apr_pollset_t* wpollset; apr_pollfd_t* wpollfd; @@ -101,16 +119,18 @@ private: friend CURL* handle(const CURLSession& cs); friend apr_socket_t* sock(const CURLSession& cs); - friend const failable setup(const string& url, const CURLSession& cs); + friend const failable setup(const string& url, CURLSession& cs); + friend const failable cleanup(CURLSession& cs); friend const failable connect(const string& url, CURLSession& cs); - friend const failable send(const char* c, const size_t l, const CURLSession& cs); - friend const failable recv(char* c, const size_t l, const CURLSession& cs); + friend const failable send(const char* c, const size_t l, CURLSession& cs); + friend const failable recv(char* c, const size_t l, CURLSession& cs); public: string ca; string cert; string key; string cookie; + int timeout; }; /** @@ -242,11 +262,13 @@ const string topDomain(const string& host) { /** * Setup a CURL session */ -const failable setup(const string& url, const CURLSession& cs) { +const failable setup(const string& url, CURLSession& cs) { // Init CURL session - CURL* ch = handle(cs); - curl_easy_reset(ch); + if (cs.h != NULL) + cleanup(cs); + cs.h = curl_easy_init(); + CURL* ch = cs.h; curl_easy_setopt(ch, CURLOPT_USERAGENT, "libcurl/1.0"); #ifdef WANT_MAINTAINER_CURL_VERBOSE curl_easy_setopt(ch, CURLOPT_VERBOSE, true); @@ -256,6 +278,8 @@ const failable setup(const string& url, const CURLSession& cs) { curl_easy_setopt(ch, CURLOPT_TCP_NODELAY, true); curl_easy_setopt(ch, CURLOPT_FOLLOWLOCATION, true); curl_easy_setopt(ch, CURLOPT_POSTREDIR, CURL_REDIR_POST_ALL); + curl_easy_setopt(ch, CURLOPT_NOSIGNAL, 1); + curl_easy_setopt(ch, CURLOPT_TIMEOUT, cs.timeout); // Setup SSL options if (cs.ca != "") { @@ -309,6 +333,17 @@ const failable setup(const string& url, const CURLSession& cs) { return ch; } +/** + * Cleanup a CURL session + */ +const failable cleanup(CURLSession& cs) { + if (cs.h == NULL) + return true; + curl_easy_cleanup(cs.h); + cs.h = NULL; + return true; +} + /** * Context passed to the read callback function. */ @@ -364,14 +399,16 @@ curl_slist* headers(curl_slist* cl, const list& h) { return headers(curl_slist_append(cl, c_str(string(car(h)))), cdr(h)); } -template const failable > apply(const list >& hdr, const lambda& reduce, const R& initial, const string& url, const string& verb, const CURLSession& cs) { +template const failable > apply(const list >& hdr, const lambda& reduce, const R& initial, const string& url, const string& verb, CURLSession& cs) { debug(url, "http::apply::url"); debug(verb, "http::apply::verb"); // Setup the CURL session const failable fch = setup(url, cs); - if (!hasContent(fch)) + if (!hasContent(fch)) { + cleanup(cs); return mkfailure>(fch); + } CURL* ch = content(fch); // Set the request headers @@ -417,22 +454,27 @@ template const failable > apply(const list >& h curl_slist_free_all(hl); // Return the HTTP return code or content - if (rc) + if (rc) { + cleanup(cs); return mkfailure >(string(curl_easy_strerror(rc))); + } long httprc; curl_easy_getinfo (ch, CURLINFO_RESPONSE_CODE, &httprc); if (httprc != 200 && httprc != 201) { + cleanup(cs); ostringstream es; es << "HTTP code " << httprc; return mkfailure >(str(es)); } + + cleanup(cs); return mklist(hcx.accum, wcx.accum); } /** * Evaluate an expression remotely, at the given URL. */ -const failable evalExpr(const value& expr, const string& url, const CURLSession& cs) { +const failable evalExpr(const value& expr, const string& url, CURLSession& cs) { debug(url, "http::evalExpr::url"); debug(expr, "http::evalExpr::input"); @@ -498,7 +540,7 @@ const string contentType(const list& h) { /** * HTTP GET, return the resource at the given URL. */ -template const failable > get(const lambda& reduce, const R& initial, const string& url, const CURLSession& cs) { +template const failable > get(const lambda& reduce, const R& initial, const string& url, CURLSession& cs) { debug(url, "http::get::url"); const list > req = mklist(list(), list()); return apply(req, reduce, initial, url, "GET", cs); @@ -507,7 +549,7 @@ template const failable > get(const lambda getcontent(const string& url, const CURLSession& cs) { +const failable getcontent(const string& url, CURLSession& cs) { debug(url, "http::get::url"); // Get the contents of the resource at the given URL @@ -591,7 +633,7 @@ const failable responseValue(const list > res) { /** * HTTP GET, return a list of values representing the resource at the given URL. */ -const failable get(const string& url, const CURLSession& cs) { +const failable get(const string& url, CURLSession& cs) { debug(url, "http::get::url"); // Get the contents of the resource at the given URL @@ -689,7 +731,7 @@ const failable > > contentRequest(const value& c, unused const /** * HTTP POST. */ -const failable post(const value& val, const string& url, const CURLSession& cs) { +const failable post(const value& val, const string& url, CURLSession& cs) { debug(url, "http::post::url"); // Convert value to a content request @@ -718,7 +760,7 @@ const failable post(const value& val, const string& url, const CURLSessio /** * HTTP PUT. */ -const failable put(const value& val, const string& url, const CURLSession& cs) { +const failable put(const value& val, const string& url, CURLSession& cs) { debug(url, "http::put::url"); // Convert value to a content request @@ -739,7 +781,7 @@ const failable put(const value& val, const string& url, const CURLSession /** * HTTP PATCH. */ -const failable patch(const value& val, const string& url, const CURLSession& cs) { +const failable patch(const value& val, const string& url, CURLSession& cs) { debug(url, "http::put::patch"); // Convert value to a content request @@ -760,7 +802,7 @@ const failable patch(const value& val, const string& url, const CURLSessi /** * HTTP DELETE. */ -const failable del(const string& url, const CURLSession& cs) { +const failable del(const string& url, CURLSession& cs) { debug(url, "http::delete::url"); const list > req = mklist(list(), list()); @@ -804,32 +846,42 @@ const failable connect(const string& url, CURLSession& cs) { // Setup the CURL session const failable fch = setup(url, cs); - if (!hasContent(fch)) + if (!hasContent(fch)) { + cleanup(cs); return mkfailure(fch); + } CURL* ch = content(fch); // Connect curl_easy_setopt(ch, CURLOPT_CONNECT_ONLY, true); const CURLcode rc = curl_easy_perform(ch); - if (rc) + if (rc) { + cleanup(cs); return mkfailure(string(curl_easy_strerror(rc))); + } // Convert the connected socket to an apr_socket_t int sd; const CURLcode grc = curl_easy_getinfo(ch, CURLINFO_LASTSOCKET, &sd); - if (grc) + if (grc) { + cleanup(cs); return mkfailure(string(curl_easy_strerror(grc))); + } cs.sock = sock(sd, cs.p); // Create pollsets and pollfds which can be used to poll the socket apr_status_t rpcrc = apr_pollset_create(&cs.rpollset, 1, pool(cs.p), 0); - if (rpcrc != APR_SUCCESS) + if (rpcrc != APR_SUCCESS) { + cleanup(cs); return mkfailure(apreason(rpcrc)); + } cs.rpollfd = pollfd(cs.sock, APR_POLLIN, cs.p); apr_pollset_add(cs.rpollset, cs.rpollfd); apr_status_t wpcrc = apr_pollset_create(&cs.wpollset, 1, pool(cs.p), 0); - if (wpcrc != APR_SUCCESS) + if (wpcrc != APR_SUCCESS) { + cleanup(cs); return mkfailure(apreason(wpcrc)); + } cs.wpollfd = pollfd(cs.sock, APR_POLLOUT, cs.p); apr_pollset_add(cs.wpollset, cs.wpollfd); @@ -839,15 +891,17 @@ const failable connect(const string& url, CURLSession& cs) { /** * Send an array of chars. */ -const failable send(const char* c, const size_t l, const CURLSession& cs) { +const failable send(const char* c, const size_t l, CURLSession& cs) { // Send the data size_t wl = 0; const CURLcode rc = curl_easy_send(cs.h, c, (size_t)l, &wl); if (rc == CURLE_OK && wl == (size_t)l) return true; - if (rc != CURLE_AGAIN) + if (rc != CURLE_AGAIN) { + cleanup(cs); return mkfailure(curlreason(rc)); + } // If the socket was not ready, wait for it to become ready const apr_pollfd_t* pollfds; @@ -863,7 +917,7 @@ const failable send(const char* c, const size_t l, const CURLSession& cs) /** * Receive an array of chars. */ -const failable recv(char* c, const size_t l, const CURLSession& cs) { +const failable recv(char* c, const size_t l, CURLSession& cs) { // Receive data size_t rl; @@ -872,15 +926,19 @@ const failable recv(char* c, const size_t l, const CURLSession& cs) { return (size_t)rl; if (rc == 1) return 0; - if (rc != CURLE_AGAIN) + if (rc != CURLE_AGAIN) { + cleanup(cs); return mkfailure(curlreason(rc)); + } // If the socket was not ready, wait for it to become ready const apr_pollfd_t* pollfds; apr_int32_t pollcount; apr_status_t pollrc = apr_pollset_poll(cs.rpollset, -1, &pollcount, &pollfds); - if (pollrc != APR_SUCCESS) + if (pollrc != APR_SUCCESS) { + cleanup(cs); return mkfailure(apreason(pollrc)); + } // Receive again return recv(c, l, cs); @@ -933,7 +991,7 @@ 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 gc_pool& p) : p(p), uri(uri), ca(ca), cert(cert), key(key), cookie(cookie), cs(*(new (gc_new(p)) CURLSession(ca, cert, key, cookie))) { + 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(p)) CURLSession(ca, cert, key, cookie, timeout))) { } const value operator()(const list& args) const { @@ -975,7 +1033,7 @@ struct proxy { const string cert; const string key; const string cookie; - const CURLSession& cs; + CURLSession& cs; }; } diff --git a/sca-cpp/trunk/modules/http/mod-ssltunnel.cpp b/sca-cpp/trunk/modules/http/mod-ssltunnel.cpp index a23687d6b4..b66cd29959 100644 --- a/sca-cpp/trunk/modules/http/mod-ssltunnel.cpp +++ b/sca-cpp/trunk/modules/http/mod-ssltunnel.cpp @@ -104,6 +104,7 @@ int postConfigMerge(ServerConf& mainsc, apr_pool_t* p, server_rec* s) { int postConfig(apr_pool_t* p, unused apr_pool_t* plog, unused apr_pool_t* ptemp, server_rec* s) { gc_scoped_pool pool(p); + ServerConf& sc = httpd::serverConf(s, &mod_tuscany_ssltunnel); debug(httpd::serverName(s), "modssltunnel::postConfig::serverName"); @@ -147,7 +148,7 @@ int tunnel(conn_rec* conn, const string& ca, const string& cert, const string& k apr_socket_t* csock = (apr_socket_t*)ap_get_module_config(conn->conn_config, &core_module); // Open connection to target - http::CURLSession cs(ca, cert, key, ""); + http::CURLSession cs(ca, cert, key, "", 0); const failable crc = http::connect(url, cs); if (!hasContent(crc)) return abort(conn, csock, reason(crc)); @@ -271,9 +272,9 @@ int processConnection(conn_rec *conn) { if (ap_get_module_config(conn->base_server->module_config, &mod_tuscany_ssltunnel) == NULL) return DECLINED; - // Create a scoped memory pool - gc_scoped_pool pool; + gc_scoped_pool pool(conn->pool); + // Get the server configuration const ServerConf& sc = httpd::serverConf(conn->base_server, &mod_tuscany_ssltunnel); if (length(sc.pass) == 0) return DECLINED; @@ -296,7 +297,6 @@ int handler(request_rec* r) { if (strcmp(r->server->server_scheme, "https")) return DECLINED; - // Create a scoped memory pool gc_scoped_pool pool(r->pool); // Build the target URL diff --git a/sca-cpp/trunk/modules/server/client-test.hpp b/sca-cpp/trunk/modules/server/client-test.hpp index 2207127e67..1c7b26da39 100644 --- a/sca-cpp/trunk/modules/server/client-test.hpp +++ b/sca-cpp/trunk/modules/server/client-test.hpp @@ -46,7 +46,7 @@ ostream* curlWriter(const string& s, ostream* os) { const bool testGet() { gc_scoped_pool pool; - http::CURLSession ch("", "", "", ""); + http::CURLSession ch("", "", "", "", 0); { ostringstream os; const failable > r = http::get(curlWriter, &os, "http://localhost:8090/index.html", ch); @@ -63,7 +63,7 @@ const bool testGet() { } struct getLoop { - http::CURLSession ch; + http::CURLSession& ch; getLoop(http::CURLSession& ch) : ch(ch) { } const bool operator()() const { @@ -76,7 +76,7 @@ struct getLoop { const bool testGetPerf() { gc_scoped_pool pool; - http::CURLSession ch("", "", "", ""); + http::CURLSession ch("", "", "", "", 0); const lambda gl = getLoop(ch); cout << "Static GET test " << time(gl, 5, 200) << " ms" << endl; return true; @@ -84,7 +84,7 @@ const bool testGetPerf() { const bool testEval() { gc_scoped_pool pool; - http::CURLSession ch("", "", "", ""); + http::CURLSession ch("", "", "", "", 0); const failable r = http::evalExpr(mklist(string("echo"), string("Hello")), testURI, ch); assert(hasContent(r)); assert(content(r) == string("Hello")); @@ -93,7 +93,7 @@ const bool testEval() { struct evalLoop { const string uri; - http::CURLSession ch; + http::CURLSession& ch; evalLoop(const string& uri, http::CURLSession& ch) : uri(uri), ch(ch) { } const bool operator()() const { @@ -109,7 +109,7 @@ const list blobs = mklist(blob, blob); struct blobEvalLoop { const string uri; - http::CURLSession ch; + http::CURLSession& ch; blobEvalLoop(const string& uri, http::CURLSession& ch) : uri(uri), ch(ch) { } const bool operator()() const { @@ -122,7 +122,7 @@ struct blobEvalLoop { const bool testEvalPerf() { gc_scoped_pool pool; - http::CURLSession ch("", "", "", ""); + http::CURLSession ch("", "", "", "", 0); const lambda el = evalLoop(testURI, ch); cout << "JSON-RPC eval echo test " << time(el, 5, 200) << " ms" << endl; @@ -142,7 +142,7 @@ bool testPost() { + (list() + "title" + string("item")) + (list() + "id" + string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b")) + i); - http::CURLSession ch("", "", "", ""); + http::CURLSession ch("", "", "", "", 0); const failable id = http::post(a, testURI, ch); assert(hasContent(id)); return true; @@ -151,7 +151,7 @@ bool testPost() { struct postLoop { const string uri; const value val; - http::CURLSession ch; + http::CURLSession& ch; postLoop(const string& uri, const value& val, http::CURLSession& ch) : uri(uri), val(val), ch(ch) { } const bool operator()() const { @@ -164,7 +164,7 @@ struct postLoop { struct postBlobLoop { const string uri; const value val; - http::CURLSession ch; + http::CURLSession& ch; postBlobLoop(const string& uri, const value& val, http::CURLSession& ch) : uri(uri), val(val), ch(ch) { } const bool operator()() const { @@ -177,7 +177,7 @@ struct postBlobLoop { const bool testPostPerf() { gc_scoped_pool pool; - http::CURLSession ch("", "", "", ""); + http::CURLSession ch("", "", "", "", 0); { const list i = list() + "content" + (list() + "item" + (list() + "name" + string("Apple")) @@ -209,7 +209,7 @@ const bool testPostPerf() { const bool postThread(const string& uri, const int count, const value& val) { gc_scoped_pool pool; - http::CURLSession ch("", "", "", ""); + http::CURLSession ch("", "", "", "", 0); const lambda pl = postLoop(uri, val, ch); time(pl, 0, count); return true; @@ -267,7 +267,7 @@ const bool testPostThreadPerf() { const bool postProc(const string& uri, const int count, const value& val) { gc_scoped_pool pool; - http::CURLSession ch("", "", "", ""); + http::CURLSession ch("", "", "", "", 0); const lambda pl = postLoop(uri, val, ch); time(pl, 0, count); return true; @@ -337,7 +337,7 @@ const bool testPut() { + (list() + "title" + string("item")) + (list() + "id" + string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b")) + i); - http::CURLSession ch("", "", "", ""); + http::CURLSession ch("", "", "", "", 0); value rc = content(http::put(a, testURI + "/111", ch)); assert(rc == value(true)); return true; @@ -345,7 +345,7 @@ const bool testPut() { const bool testDel() { gc_scoped_pool pool; - http::CURLSession ch("", "", "", ""); + http::CURLSession ch("", "", "", "", 0); value rc = content(http::del(testURI + "/111", ch)); assert(rc == value(true)); return true; -- cgit v1.2.3