@@ -339,12 +339,6 @@ set(CPPCMS_PUBLIC_HEADERS | |||
base_view.h | |||
cache_interface.h | |||
cache_pool.h | |||
callback.h | |||
callback0.h | |||
callback1.h | |||
callback2.h | |||
callback3.h | |||
callback4.h | |||
clone_ptr.h | |||
# connection_forwarder.h | |||
copy_ptr.h | |||
@@ -21,7 +21,7 @@ | |||
#include "defs.h" | |||
#include "noncopyable.h" | |||
#include "callback1.h" | |||
#include "function.h" | |||
#include "hold_ptr.h" | |||
namespace cppcms { | |||
@@ -40,7 +40,7 @@ namespace cppcms { | |||
timer(service &srv); | |||
~timer(); | |||
typedef util::callback1<bool> handler; | |||
typedef function<void(bool)> handler; | |||
// | |||
// true if was error or cancelation | |||
@@ -1,29 +0,0 @@ | |||
/////////////////////////////////////////////////////////////////////////////// | |||
// | |||
// Copyright (C) 2008-2010 Artyom Beilis (Tonkikh) <artyomtnk@yahoo.com> | |||
// | |||
// This program is free software: you can redistribute it and/or modify | |||
// it under the terms of the GNU Lesser General Public License as published by | |||
// the Free Software Foundation, either version 3 of the License, or | |||
// (at your option) any later version. | |||
// | |||
// This program is distributed in the hope that it will be useful, | |||
// but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
// GNU Lesser General Public License for more details. | |||
// | |||
// You should have received a copy of the GNU Lesser General Public License | |||
// along with this program. If not, see <http://www.gnu.org/licenses/>. | |||
// | |||
/////////////////////////////////////////////////////////////////////////////// | |||
#ifndef CALLBACK_H | |||
#define CALLBACK_H | |||
#include "callback0.h" | |||
#include "callback1.h" | |||
#include "callback2.h" | |||
#include "callback3.h" | |||
#include "callback4.h" | |||
#endif |
@@ -1,121 +0,0 @@ | |||
/////////////////////////////////////////////////////////////////////////////// | |||
// | |||
// Copyright (C) 2008-2010 Artyom Beilis (Tonkikh) <artyomtnk@yahoo.com> | |||
// | |||
// This program is free software: you can redistribute it and/or modify | |||
// it under the terms of the GNU Lesser General Public License as published by | |||
// the Free Software Foundation, either version 3 of the License, or | |||
// (at your option) any later version. | |||
// | |||
// This program is distributed in the hope that it will be useful, | |||
// but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
// GNU Lesser General Public License for more details. | |||
// | |||
// You should have received a copy of the GNU Lesser General Public License | |||
// along with this program. If not, see <http://www.gnu.org/licenses/>. | |||
// | |||
/////////////////////////////////////////////////////////////////////////////// | |||
#ifndef CPPCMS_UTIL_CALLBACK0_H | |||
#define CPPCMS_UTIL_CALLBACK0_H | |||
#include "clone_ptr.h" | |||
namespace cppcms { namespace util { | |||
/// | |||
/// \brief Function object, similar to C++0x std::function<void()>, or boost::function<void()> | |||
/// | |||
/// Callback object, it can be created with any "function like object" -- a class with operator() or C function | |||
/// with appropriate signature. | |||
/// | |||
class callback0 { | |||
struct callable { | |||
virtual void call() = 0; | |||
virtual callable *clone() const = 0; | |||
virtual ~callable() {}; | |||
}; | |||
template<typename T> | |||
struct callable_functor : public callable{ | |||
T func; | |||
callable_functor(T f) : func(f) {} | |||
virtual ~callable_functor() { } | |||
virtual void call() { func(); } | |||
virtual callable *clone() const { return new callable_functor<T>(func); } | |||
}; | |||
clone_ptr<callable> call_ptr; | |||
public: | |||
typedef void result_type; | |||
/// | |||
/// Call the assigned function, does nothing if function was not assigned | |||
/// | |||
void operator()() const | |||
{ | |||
if(call_ptr.get()) { | |||
call_ptr->call(); | |||
} | |||
} | |||
/// | |||
/// Create an empty callback | |||
/// | |||
callback0(){} | |||
/// | |||
/// Copy constructor | |||
/// | |||
callback0(callback0 const &other) : call_ptr(other.call_ptr) | |||
{ | |||
} | |||
/// | |||
/// Assignment operator | |||
/// | |||
callback0 const &operator=(callback0 const &other) | |||
{ | |||
if(this!=&other) | |||
call_ptr = other.call_ptr; | |||
return *this; | |||
} | |||
/// | |||
/// Create a callback and copy callable object T to it. | |||
/// | |||
template<typename T> | |||
callback0(T c) : call_ptr(new callable_functor<T>(c)) | |||
{ | |||
} | |||
/// | |||
/// Assign a callable object to it | |||
/// | |||
template<typename T> | |||
callback0 const &operator=(T c) | |||
{ | |||
call_ptr.reset(new callable_functor<T>(c)); | |||
return *this; | |||
} | |||
/// | |||
/// Swap two callbacks | |||
/// | |||
void swap(callback0 &other) | |||
{ | |||
call_ptr.swap(other.call_ptr); | |||
} | |||
}; | |||
}} // cppcms util | |||
#endif |
@@ -1,121 +0,0 @@ | |||
/////////////////////////////////////////////////////////////////////////////// | |||
// | |||
// Copyright (C) 2008-2010 Artyom Beilis (Tonkikh) <artyomtnk@yahoo.com> | |||
// | |||
// This program is free software: you can redistribute it and/or modify | |||
// it under the terms of the GNU Lesser General Public License as published by | |||
// the Free Software Foundation, either version 3 of the License, or | |||
// (at your option) any later version. | |||
// | |||
// This program is distributed in the hope that it will be useful, | |||
// but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
// GNU Lesser General Public License for more details. | |||
// | |||
// You should have received a copy of the GNU Lesser General Public License | |||
// along with this program. If not, see <http://www.gnu.org/licenses/>. | |||
// | |||
/////////////////////////////////////////////////////////////////////////////// | |||
#ifndef CPPCMS_UTIL_CALLBACK1_H | |||
#define CPPCMS_UTIL_CALLBACK1_H | |||
#include "clone_ptr.h" | |||
namespace cppcms { namespace util { | |||
/// | |||
/// \brief Function object, similar to C++0x std::function<void(P1)>, or boost::function<void(P1)> | |||
/// | |||
/// Callback object, it can be created with any "function like object" -- a class with operator()(P1) or C function | |||
/// with appropriate signature. | |||
/// | |||
template<typename P1> | |||
class callback1 { | |||
struct callable { | |||
virtual void call(P1) = 0; | |||
virtual callable *clone() const = 0; | |||
virtual ~callable() {}; | |||
}; | |||
template<typename T> | |||
struct callable_functor : public callable{ | |||
T func; | |||
callable_functor(T f) : func(f) {} | |||
virtual ~callable_functor() { } | |||
virtual void call(P1 p1) { func(p1); } | |||
virtual callable *clone() const { return new callable_functor<T>(func); } | |||
}; | |||
clone_ptr<callable> call_ptr; | |||
public: | |||
typedef void result_type; | |||
typedef P1 argument_type; | |||
/// | |||
/// Call the assigned function, does nothing if function was not assigned | |||
/// | |||
void operator()(P1 p1) const | |||
{ | |||
if(call_ptr.get()) { | |||
call_ptr->call(p1); | |||
} | |||
} | |||
/// | |||
/// Create an empty callback | |||
/// | |||
callback1(){} | |||
/// | |||
/// Copy constructor | |||
/// | |||
callback1(callback1 const &other) : call_ptr(other.call_ptr) | |||
{ | |||
} | |||
/// | |||
/// Assignment operator | |||
/// | |||
callback1 const &operator=(callback1 const &other) | |||
{ | |||
if(this!=&other) | |||
call_ptr = other.call_ptr; | |||
return *this; | |||
} | |||
/// | |||
/// Create a callback and copy callable object T to it. | |||
/// | |||
template<typename T> | |||
callback1(T c) : call_ptr(new callable_functor<T>(c)) | |||
{ | |||
} | |||
/// | |||
/// Assign a callable object to it | |||
/// | |||
template<typename T> | |||
callback1 const &operator=(T c) | |||
{ | |||
call_ptr.reset(new callable_functor<T>(c)); | |||
return *this; | |||
} | |||
/// | |||
/// Swap two callbacks | |||
/// | |||
void swap(callback1 &other) | |||
{ | |||
call_ptr.swap(other.call_ptr); | |||
} | |||
}; | |||
}} // cppcms util | |||
#endif |
@@ -1,121 +0,0 @@ | |||
/////////////////////////////////////////////////////////////////////////////// | |||
// | |||
// Copyright (C) 2008-2010 Artyom Beilis (Tonkikh) <artyomtnk@yahoo.com> | |||
// | |||
// This program is free software: you can redistribute it and/or modify | |||
// it under the terms of the GNU Lesser General Public License as published by | |||
// the Free Software Foundation, either version 3 of the License, or | |||
// (at your option) any later version. | |||
// | |||
// This program is distributed in the hope that it will be useful, | |||
// but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
// GNU Lesser General Public License for more details. | |||
// | |||
// You should have received a copy of the GNU Lesser General Public License | |||
// along with this program. If not, see <http://www.gnu.org/licenses/>. | |||
// | |||
/////////////////////////////////////////////////////////////////////////////// | |||
#ifndef CPPCMS_UTIL_CALLBACK2_H | |||
#define CPPCMS_UTIL_CALLBACK2_H | |||
#include "clone_ptr.h" | |||
namespace cppcms { namespace util { | |||
/// | |||
/// \brief Function object, similar to C++0x std::function<void(P1,P2)>, or boost::function<void(P1,P2)> | |||
/// | |||
/// Callback object, it can be created with any "function like object" -- a class with operator()(P1,P2) or C function | |||
/// with appropriate signature. | |||
/// | |||
template<typename P1,typename P2> | |||
class callback2 { | |||
struct callable { | |||
virtual void call(P1,P2) = 0; | |||
virtual callable *clone() const = 0; | |||
virtual ~callable() {}; | |||
}; | |||
template<typename T> | |||
struct callable_functor : public callable{ | |||
T func; | |||
callable_functor(T f) : func(f) {} | |||
virtual ~callable_functor() { } | |||
virtual void call(P1 p1,P2 p2) { func(p1,p2); } | |||
virtual callable *clone() const { return new callable_functor<T>(func); } | |||
}; | |||
clone_ptr<callable> call_ptr; | |||
public: | |||
typedef void result_type; | |||
typedef P1 first_argument_type; | |||
typedef P2 second_argument_type; | |||
/// | |||
/// Call the assigned function, does nothing if function was not assigned | |||
/// | |||
void operator()(P1 p1,P2 p2) const | |||
{ | |||
if(call_ptr.get()) { | |||
call_ptr->call(p1,p2); | |||
} | |||
} | |||
/// | |||
/// Create an empty callback | |||
/// | |||
callback2(){} | |||
/// | |||
/// Copy constructor | |||
/// | |||
callback2(callback2 const &other) : call_ptr(other.call_ptr) | |||
{ | |||
} | |||
/// | |||
/// Assignment operator | |||
/// | |||
callback2 const &operator=(callback2 const &other) | |||
{ | |||
if(this!=&other) | |||
call_ptr = other.call_ptr; | |||
return *this; | |||
} | |||
/// | |||
/// Create a callback and copy callable object T to it. | |||
/// | |||
template<typename T> | |||
callback2(T c) : call_ptr(new callable_functor<T>(c)) | |||
{ | |||
} | |||
/// | |||
/// Assign a callable object to it | |||
/// | |||
template<typename T> | |||
callback2 const &operator=(T c) | |||
{ | |||
call_ptr.reset(new callable_functor<T>(c)); | |||
return *this; | |||
} | |||
/// | |||
/// Swap two callbacks | |||
/// | |||
void swap(callback2 &other) | |||
{ | |||
call_ptr.swap(other.call_ptr); | |||
} | |||
}; | |||
}} // cppcms util | |||
#endif |
@@ -1,119 +0,0 @@ | |||
/////////////////////////////////////////////////////////////////////////////// | |||
// | |||
// Copyright (C) 2008-2010 Artyom Beilis (Tonkikh) <artyomtnk@yahoo.com> | |||
// | |||
// This program is free software: you can redistribute it and/or modify | |||
// it under the terms of the GNU Lesser General Public License as published by | |||
// the Free Software Foundation, either version 3 of the License, or | |||
// (at your option) any later version. | |||
// | |||
// This program is distributed in the hope that it will be useful, | |||
// but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
// GNU Lesser General Public License for more details. | |||
// | |||
// You should have received a copy of the GNU Lesser General Public License | |||
// along with this program. If not, see <http://www.gnu.org/licenses/>. | |||
// | |||
/////////////////////////////////////////////////////////////////////////////// | |||
#ifndef CPPCMS_UTIL_CALLBACK3_H | |||
#define CPPCMS_UTIL_CALLBACK3_H | |||
#include "clone_ptr.h" | |||
namespace cppcms { namespace util { | |||
/// | |||
/// \brief Function object, similar to C++0x std::function<void(P1,P2,P3)>, or boost::function<void(P1,P2,P3)> | |||
/// | |||
/// Callback object, it can be created with any "function like object" -- a class with operator()(P1,P2,P3) or C function | |||
/// with appropriate signature. | |||
/// | |||
template<typename P1,typename P2,typename P3> | |||
class callback3 { | |||
struct callable { | |||
virtual void call(P1,P2,P3) = 0; | |||
virtual callable *clone() const = 0; | |||
virtual ~callable() {}; | |||
}; | |||
template<typename T> | |||
struct callable_functor : public callable{ | |||
T func; | |||
callable_functor(T f) : func(f) {} | |||
virtual ~callable_functor() { } | |||
virtual void call(P1 p1,P2 p2,P3 p3) { func(p1,p2,p3); } | |||
virtual callable *clone() const { return new callable_functor<T>(func); } | |||
}; | |||
clone_ptr<callable> call_ptr; | |||
public: | |||
typedef void result_type; | |||
/// | |||
/// Call the assigned function, does nothing if function was not assigned | |||
/// | |||
void operator()(P1 p1,P2 p2,P3 p3) const | |||
{ | |||
if(call_ptr.get()) { | |||
call_ptr->call(p1,p2,p3); | |||
} | |||
} | |||
/// | |||
/// Create an empty callback | |||
/// | |||
callback3(){} | |||
/// | |||
/// Copy constructor | |||
/// | |||
callback3(callback3 const &other) : call_ptr(other.call_ptr) | |||
{ | |||
} | |||
/// | |||
/// Assignment operator | |||
/// | |||
callback3 const &operator=(callback3 const &other) | |||
{ | |||
if(this!=&other) | |||
call_ptr = other.call_ptr; | |||
return *this; | |||
} | |||
/// | |||
/// Create a callback and copy callable object T to it. | |||
/// | |||
template<typename T> | |||
callback3(T c) : call_ptr(new callable_functor<T>(c)) | |||
{ | |||
} | |||
/// | |||
/// Assign a callable object to it | |||
/// | |||
template<typename T> | |||
callback3 const &operator=(T c) | |||
{ | |||
call_ptr.reset(new callable_functor<T>(c)); | |||
return *this; | |||
} | |||
/// | |||
/// Swap two callbacks | |||
/// | |||
void swap(callback3 &other) | |||
{ | |||
call_ptr.swap(other.call_ptr); | |||
} | |||
}; | |||
}} // cppcms util | |||
#endif |
@@ -1,119 +0,0 @@ | |||
/////////////////////////////////////////////////////////////////////////////// | |||
// | |||
// Copyright (C) 2008-2010 Artyom Beilis (Tonkikh) <artyomtnk@yahoo.com> | |||
// | |||
// This program is free software: you can redistribute it and/or modify | |||
// it under the terms of the GNU Lesser General Public License as published by | |||
// the Free Software Foundation, either version 3 of the License, or | |||
// (at your option) any later version. | |||
// | |||
// This program is distributed in the hope that it will be useful, | |||
// but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
// GNU Lesser General Public License for more details. | |||
// | |||
// You should have received a copy of the GNU Lesser General Public License | |||
// along with this program. If not, see <http://www.gnu.org/licenses/>. | |||
// | |||
/////////////////////////////////////////////////////////////////////////////// | |||
#ifndef CPPCMS_UTIL_CALLBACK4_H | |||
#define CPPCMS_UTIL_CALLBACK4_H | |||
#include "clone_ptr.h" | |||
namespace cppcms { namespace util { | |||
/// | |||
/// \brief Function object, similar to C++0x std::function<void(P1,P2,P3,P4)>, or boost::function<void(P1,P2,P3,P4)> | |||
/// | |||
/// Callback object, it can be created with any "function like object" -- a class with operator()(P1,P2,P3,P4) or C function | |||
/// with appropriate signature. | |||
/// | |||
template<typename P1,typename P2,typename P3,typename P4> | |||
class callback4 { | |||
struct callable { | |||
virtual void call(P1,P2,P3,P4) = 0; | |||
virtual callable *clone() const = 0; | |||
virtual ~callable() {}; | |||
}; | |||
template<typename T> | |||
struct callable_functor : public callable{ | |||
T func; | |||
callable_functor(T f) : func(f) {} | |||
virtual ~callable_functor() { } | |||
virtual void call(P1 p1,P2 p2,P3 p3,P4 p4) { func(p1,p2,p3,p4); } | |||
virtual callable *clone() const { return new callable_functor<T>(func); } | |||
}; | |||
clone_ptr<callable> call_ptr; | |||
public: | |||
typedef void result_type; | |||
/// | |||
/// Call the assigned function, does nothing if function was not assigned | |||
/// | |||
void operator()(P1 p1,P2 p2,P3 p3,P4 p4) const | |||
{ | |||
if(call_ptr.get()) { | |||
call_ptr->call(p1,p2,p3,p4); | |||
} | |||
} | |||
/// | |||
/// Create an empty callback | |||
/// | |||
callback4(){} | |||
/// | |||
/// Copy constructor | |||
/// | |||
callback4(callback4 const &other) : call_ptr(other.call_ptr) | |||
{ | |||
} | |||
/// | |||
/// Assignment operator | |||
/// | |||
callback4 const &operator=(callback4 const &other) | |||
{ | |||
if(this!=&other) | |||
call_ptr = other.call_ptr; | |||
return *this; | |||
} | |||
/// | |||
/// Create a callback and copy callable object T to it. | |||
/// | |||
template<typename T> | |||
callback4(T c) : call_ptr(new callable_functor<T>(c)) | |||
{ | |||
} | |||
/// | |||
/// Assign a callable object to it | |||
/// | |||
template<typename T> | |||
callback4 const &operator=(T c) | |||
{ | |||
call_ptr.reset(new callable_functor<T>(c)); | |||
return *this; | |||
} | |||
/// | |||
/// Swap two callbacks | |||
/// | |||
void swap(callback4 &other) | |||
{ | |||
call_ptr.swap(other.call_ptr); | |||
} | |||
}; | |||
}} // cppcms util | |||
#endif |
@@ -258,12 +258,12 @@ intrusive_ptr<connection> connection::self() | |||
} | |||
void connection::async_prepare_request( http::request &request, | |||
boost::function<void(bool)> const &h) | |||
function<void(bool)> const &h) | |||
{ | |||
async_read_headers(boost::bind(&connection::load_content,self(),_1,&request,h)); | |||
} | |||
void connection::aync_wait_for_close_by_peer(boost::function<void()> const &on_eof) | |||
void connection::aync_wait_for_close_by_peer(function<void()> const &on_eof) | |||
{ | |||
async_read_eof(boost::bind(&connection::handle_eof,self(),on_eof)); | |||
} | |||
@@ -24,13 +24,12 @@ | |||
#include "intrusive_ptr.h" | |||
#include <vector> | |||
#include <map> | |||
#include "function.h" | |||
#include "config.h" | |||
#ifdef CPPCMS_USE_EXTERNAL_BOOST | |||
# include <boost/function.hpp> | |||
# include <boost/system/error_code.hpp> | |||
namespace boost { namespace asio { class io_service; } } | |||
#else // Internal Boost | |||
# include <cppcms_boost/function.hpp> | |||
# include <cppcms_boost/system/error_code.hpp> | |||
namespace cppcms_boost { namespace asio { class io_service; } } | |||
namespace boost = cppcms_boost; | |||
@@ -50,10 +49,10 @@ namespace cppcms { | |||
namespace impl { | |||
namespace cgi { | |||
typedef boost::function<void(boost::system::error_code const &e)> handler; | |||
typedef boost::function<void(boost::system::error_code const &e,size_t)> io_handler; | |||
typedef boost::function<void()> callback; | |||
typedef boost::function<void(bool)> ehandler; | |||
typedef function<void(boost::system::error_code const &e)> handler; | |||
typedef function<void(boost::system::error_code const &e,size_t)> io_handler; | |||
typedef function<void()> callback; | |||
typedef function<void(bool)> ehandler; | |||
class acceptor : public util::noncopyable { | |||
public: | |||
@@ -1,3 +1,21 @@ | |||
/////////////////////////////////////////////////////////////////////////////// | |||
// | |||
// Copyright (C) 2008-2010 Artyom Beilis (Tonkikh) <artyomtnk@yahoo.com> | |||
// | |||
// This program is free software: you can redistribute it and/or modify | |||
// it under the terms of the GNU Lesser General Public License as published by | |||
// the Free Software Foundation, either version 3 of the License, or | |||
// (at your option) any later version. | |||
// | |||
// This program is distributed in the hope that it will be useful, | |||
// but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
// GNU Lesser General Public License for more details. | |||
// | |||
// You should have received a copy of the GNU Lesser General Public License | |||
// along with this program. If not, see <http://www.gnu.org/licenses/>. | |||
// | |||
/////////////////////////////////////////////////////////////////////////////// | |||
#ifndef CPPCMS_FUNCTION_H | |||
#define CPPCMS_FUNCTION_H | |||
@@ -23,7 +41,7 @@ namespace cppcms { | |||
public: \ | |||
typedef Result result_type; \ | |||
struct callable { \ | |||
virtual Result call(CPPCMS_TYPE_PARAMS) const=0; \ | |||
virtual Result call(CPPCMS_TYPE_PARAMS) =0; \ | |||
virtual callable *clone() const = 0; \ | |||
virtual ~callable(){} \ | |||
}; \ | |||
@@ -32,7 +50,7 @@ namespace cppcms { | |||
struct callable_impl : public callable { \ | |||
F func; \ | |||
callable_impl(F f) : func(f){} \ | |||
virtual R call(CPPCMS_TYPE_PARAMS) const \ | |||
virtual R call(CPPCMS_TYPE_PARAMS) \ | |||
{ return func(CPPCMS_CALL_PARAMS); } \ | |||
virtual callable *clone() const \ | |||
{ return new callable_impl<R,F>(func); } \ | |||
@@ -41,7 +59,7 @@ namespace cppcms { | |||
struct callable_impl<void,F> : public callable { \ | |||
F func; \ | |||
callable_impl(F f) : func(f){} \ | |||
virtual void call(CPPCMS_TYPE_PARAMS) const \ | |||
virtual void call(CPPCMS_TYPE_PARAMS) \ | |||
{ func(CPPCMS_CALL_PARAMS); } \ | |||
virtual callable *clone() const \ | |||
{ return new callable_impl<void,F>(func); } \ | |||
@@ -62,6 +80,7 @@ namespace cppcms { | |||
return call_ptr->call(CPPCMS_CALL_PARAMS); \ | |||
} \ | |||
bool empty() const { return call_ptr.get()==0; } \ | |||
void swap(function &other) { call_ptr.swap(other.call_ptr); } \ | |||
private: \ | |||
util::clone_ptr<callable> call_ptr; \ | |||
}; \ | |||
@@ -1,158 +0,0 @@ | |||
/////////////////////////////////////////////////////////////////////////////// | |||
// | |||
// Copyright (C) 2008-2010 Artyom Beilis (Tonkikh) <artyomtnk@yahoo.com> | |||
// | |||
// This program is free software: you can redistribute it and/or modify | |||
// it under the terms of the GNU Lesser General Public License as published by | |||
// the Free Software Foundation, either version 3 of the License, or | |||
// (at your option) any later version. | |||
// | |||
// This program is distributed in the hope that it will be useful, | |||
// but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
// GNU Lesser General Public License for more details. | |||
// | |||
// You should have received a copy of the GNU Lesser General Public License | |||
// along with this program. If not, see <http://www.gnu.org/licenses/>. | |||
// | |||
/////////////////////////////////////////////////////////////////////////////// | |||
#ifndef CPPCMS_HTP_CONNECTION_SCGI_H | |||
#define CPPCMS_HTP_CONNECTION_SCGI_H | |||
#include "http_connection.h" | |||
#include "asio_config.h" | |||
namespace cppcms { namespace http { | |||
template<typename Socket> | |||
class scgi_connection : public connection { | |||
aio::streambuf buf_; | |||
std::vector<char> data_; | |||
std::map<std::string,std::string> env_; | |||
Socket socket_; | |||
void on_done(error_code const &e,boost::fuction<void(bool>) callback) | |||
{ | |||
callback(bool(e)); | |||
} | |||
int check_size(aio::buffer &buf) | |||
{ | |||
std::istream s(&buf); | |||
size_t n; | |||
s>>n; | |||
if(s.failbit()) | |||
return -1; | |||
return n; | |||
} | |||
bool parse_env(std::vector<char> const &s) | |||
{ | |||
if(s.back()!=',') | |||
return false; | |||
std::vector<char>::const_iterator b,e,p; | |||
b=s.begin(); e=s.begin()+s.size()-1; | |||
while(b!=e) { | |||
p=std::find(b,e,0); | |||
if(p==e) | |||
return false; | |||
std::string key(b,p); | |||
b=p+1; | |||
p=std::find(b,e,0); | |||
if(p==e) | |||
return false; | |||
std::string val(b,p); | |||
b=p+1; | |||
env_.insert(std::make_pair(key,val)); | |||
} | |||
if(env_.find("CONTENT_LENGTH")==env_.end()) | |||
return false; | |||
return true; | |||
} | |||
public: | |||
virtual bool keep_alive() { return false; } | |||
virtual size_t read(void *buffer,size_t s) | |||
{ | |||
return aio::read(socket_,aio::buffer(buffer,s)); | |||
} | |||
virtual size_t write(void const *buffer,size_t s) | |||
{ | |||
return aio::write(socket_,aio::buffer(buffer,s)); | |||
} | |||
virtual bool prepare() | |||
{ | |||
try { | |||
aio::read_until(socket_,buf_,':'); | |||
int n=check_size(buf); | |||
if(n<0) | |||
return false; | |||
data_.resize(n+1,0); | |||
if(aio::read(socket_,aio::buffer(data))!=n+1) | |||
return false; | |||
if(!parse_env(data)) | |||
return false; | |||
} | |||
catch(std::exception const &e) { | |||
return false; | |||
} | |||
return true; | |||
} | |||
virtual aio::io_service &io_service() | |||
{ | |||
return socket_.io_service(); | |||
} | |||
virtual void async_read(void *buffer,size_t s,boost::function<void(bool)> c) | |||
{ | |||
aio::async_read(socket_,aio::buffer(buffer,s), | |||
boost::bind(&scgi_connection<Socket>::on_done,shared_from_this(),aio::placeholders::error,c)); | |||
} | |||
virtual void async_write(void const *buffer,size_t s,boost::function<void(bool)> c) | |||
{ | |||
aio::async_write(socket_,aio::buffer(buffer,s), | |||
boost::bind(&scgi_connection<Socket>::on_done,shared_from_this(),aio::placeholders::error,c)); | |||
} | |||
virtual void async_prepare(boost::function<void(bool)> c) | |||
{ | |||
aio::async_read_until(socket_,buf_,':', | |||
boost::bind(&scgi_connection<Socket>::on_net_read,shared_from_this(),aio::placeholders::error,c)); | |||
} | |||
private: | |||
void on_net_read(error_code const &e,boost::function<void(bool)> c) | |||
{ | |||
if(e) { | |||
c(false); | |||
return; | |||
} | |||
int n=check_size(buf); | |||
if(n<0) { | |||
c(false) ; | |||
return; | |||
} | |||
data_.resize(n+1,0); | |||
aio::async_read(socket_,aio::buffer(data_), | |||
boost::bind(&scgi_connection<Socket>::on_env_read,aio::placeholders::error,c)); | |||
} | |||
void on_env_read(error_code const &e,boost::function<void(bool)>) | |||
{ | |||
if(e) { | |||
c(false); | |||
return; | |||
} | |||
if(!parse_env(data)) { | |||
c(false); | |||
return; | |||
} | |||
c(true); | |||
} | |||
public: | |||
virtual std::string getenv(std::string const &key) | |||
{ | |||
std::map<std::string,std::string>::iterator p; | |||
p=env_.find(key); | |||
if(p==env_.end()) | |||
return std::string(); | |||
return p->second; | |||
} | |||
}; // connection_scgi | |||
} } | |||
#endif |
@@ -185,7 +185,7 @@ context::~context() | |||
{ | |||
} | |||
void context::async_on_peer_reset(util::callback0 const &h) | |||
void context::async_on_peer_reset(function<void()> const &h) | |||
{ | |||
// For some wired can't go without bind on SunCC | |||
conn_->aync_wait_for_close_by_peer(boost::bind(h)); | |||
@@ -23,9 +23,7 @@ | |||
#include "hold_ptr.h" | |||
#include "intrusive_ptr.h" | |||
#include "refcounted.h" | |||
#include "callback0.h" | |||
#include "callback1.h" | |||
#include "function.h" | |||
#include <locale> | |||
namespace cppcms { | |||
@@ -138,7 +136,7 @@ namespace cppcms { | |||
operation_aborted ///< Asynchronous operation was canceled | |||
} complition_type; | |||
typedef util::callback1<complition_type> handler; | |||
typedef function<void(complition_type)> handler; | |||
/// | |||
/// Send all pending output data to the client and | |||
@@ -167,7 +165,7 @@ namespace cppcms { | |||
/// 2. If async_flush_output fails, this does not mean that | |||
/// this handler would be called as well, so you need to check both | |||
/// | |||
void async_on_peer_reset(util::callback0 const &h); | |||
void async_on_peer_reset(function<void()> const &h); | |||
private: | |||
void on_request_ready(bool error); | |||
static void dispatch(intrusive_ptr<application> app,std::string url,bool syncronous); | |||
@@ -1,738 +0,0 @@ | |||
/////////////////////////////////////////////////////////////////////////////// | |||
// | |||
// Copyright (C) 2008-2010 Artyom Beilis (Tonkikh) <artyomtnk@yahoo.com> | |||
// | |||
// This program is free software: you can redistribute it and/or modify | |||
// it under the terms of the GNU Lesser General Public License as published by | |||
// the Free Software Foundation, either version 3 of the License, or | |||
// (at your option) any later version. | |||
// | |||
// This program is distributed in the hope that it will be useful, | |||
// but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
// GNU Lesser General Public License for more details. | |||
// | |||
// You should have received a copy of the GNU Lesser General Public License | |||
// along with this program. If not, see <http://www.gnu.org/licenses/>. | |||
// | |||
/////////////////////////////////////////////////////////////////////////////// | |||
#ifdef HAVE_CONFIG_H | |||
# include "config.h" | |||
#endif | |||
#include "manager.h" | |||
#include "cgicc_connection.h" | |||
#if !defined(CPPCMS_EMBEDDED) || defined(CPPCMS_EMBEDDED_THREAD) | |||
#include <dlfcn.h> | |||
#include <dirent.h> | |||
#include <poll.h> | |||
#include <signal.h> | |||
#include <errno.h> | |||
#include <unistd.h> | |||
#include <sys/mman.h> | |||
#include <sys/wait.h> | |||
#include <sys/types.h> | |||
#include "config.h" | |||
#ifdef CPPCMS_USE_EXTERNAL_BOOST | |||
# include <boost/shared_ptr.hpp> | |||
#else // Internal Boost | |||
# include <cppcms_boost/shared_ptr.hpp> | |||
namespace boost = cppcms_boost; | |||
#endif | |||
#include "thread_cache.h" | |||
#endif | |||
#include <algorithm> | |||
#include <stdlib.h> | |||
#include "scgi.h" | |||
#include "cgi.h" | |||
#include "session_cookies.h" | |||
#include "session_file_storage.h" | |||
#include "session_cache_backend.h" | |||
#include "session_dual.h" | |||
#ifdef EN_SQLITE_SESSIONS | |||
# include "session_sqlite_storage.h" | |||
#endif | |||
#ifdef EN_FORK_CACHE | |||
# include "process_cache.h" | |||
#endif | |||
#ifdef EN_FCGI_BACKEND | |||
# include "fcgi.h" | |||
#endif | |||
#ifdef EN_TCP_CACHE | |||
# include "tcp_cache.h" | |||
# include "session_tcp_storage.h" | |||
#endif | |||
#if !defined(CPPCMS_EMBEDDED) || defined(CPPCMS_EMBEDDED_THREAD) | |||
namespace { | |||
void set_signal_handler(int sig,void (*handler)(int)) | |||
{ | |||
struct sigaction sac; | |||
memset(&sac,0,sizeof(sac)); | |||
sac.sa_handler=handler; | |||
sigaction(sig,&sac,NULL); | |||
} | |||
} | |||
#endif | |||
namespace cppcms { | |||
namespace details { | |||
class single_run : public web_application{ | |||
public: | |||
single_run(manager &m) : web_application(m) | |||
{ | |||
}; | |||
virtual void execute() | |||
{ | |||
base_factory &factory=*app.workers; | |||
auto_ptr<worker_thread> worker(factory(app)); | |||
cgi_session *session=app.api->accept_session(); | |||
if(session) { | |||
try { | |||
if(session->prepare()) { | |||
worker->run(session->get_connection()); | |||
} | |||
} | |||
catch(...) { | |||
delete session; | |||
throw; | |||
} | |||
delete session; | |||
} | |||
} | |||
}; | |||
#if !defined(CPPCMS_EMBEDDED) || defined(CPPCMS_EMBEDDED_THREAD) | |||
fast_cgi_application *fast_cgi_application::handlers_owner=NULL; | |||
fast_cgi_application::event_t fast_cgi_application::wait() | |||
{ | |||
while(!the_end) { | |||
struct pollfd fds; | |||
fds.fd=app.api->get_socket(); | |||
fds.events=POLLIN | POLLERR; | |||
fds.revents=0; | |||
/* Wait for two events: | |||
* 1. New connection and then do accept | |||
* 2. Exit message - exit and do clean up */ | |||
if(poll(&fds,1,-1)<0) { | |||
if(errno==EINTR && !the_end) | |||
continue; | |||
return EXIT; | |||
} | |||
else if(fds.revents) { | |||
if(fds.revents & POLLERR) | |||
return EXIT; | |||
return ACCEPT; | |||
} | |||
} | |||
return EXIT; | |||
} | |||
void fast_cgi_application::shutdown() | |||
{ | |||
// Rise exit signal on | |||
// the selfpipe | |||
the_end=true; | |||
} | |||
void fast_cgi_application::handler(int id) | |||
{ | |||
fast_cgi_application *ptr=fast_cgi_application::get_instance(); | |||
if(ptr) { | |||
ptr->shutdown(); | |||
} | |||
} | |||
void fast_cgi_application::set_signal_handlers() | |||
{ | |||
handlers_owner=this; | |||
/* Signals defined by standard */ | |||
set_signal_handler(SIGTERM,handler); | |||
set_signal_handler(SIGUSR1,handler); | |||
/* Additional signal */ | |||
set_signal_handler(SIGINT,handler); | |||
} | |||
fast_cgi_single_threaded_app::fast_cgi_single_threaded_app(manager &m) : | |||
fast_cgi_application( m) | |||
{ | |||
base_factory &factory=*app.workers; | |||
worker=factory(app); | |||
} | |||
bool fast_cgi_single_threaded_app::run() | |||
{ | |||
// Blocking loop | |||
event_t event=wait(); | |||
if(event==EXIT) { | |||
return false; | |||
} // ELSE event==ACCEPT | |||
cgi_session *session=app.api->accept_session(); | |||
if(session) { | |||
try { | |||
if(session->prepare()) { | |||
worker->run(session->get_connection()); | |||
} | |||
} | |||
catch(...) { | |||
delete session; | |||
throw; | |||
} | |||
delete session; | |||
} | |||
return true; | |||
}; | |||
void fast_cgi_application::execute() | |||
{ | |||
the_end=false; | |||
set_signal_handlers(); | |||
while(run()){ | |||
/* Do Continue */ | |||
} | |||
} | |||
fast_cgi_multiple_threaded_app::fast_cgi_multiple_threaded_app(manager &m): | |||
fast_cgi_application(m) | |||
{ | |||
int threads_num=app.config.lval("server.threads",5); | |||
int buffer=app.config.lval("server.buffer",10); | |||
int i; | |||
threads_info=NULL; | |||
pids=NULL; | |||
size=threads_num; | |||
// Init Worker Threads | |||
workers.resize(size,0); | |||
base_factory &factory=*app.workers; | |||
for(i=0;i<size;i++) { | |||
workers[i]=factory(app).release(); | |||
} | |||
// Setup Jobs Manager | |||
jobs.init(buffer); | |||
start_threads(); | |||
} | |||
void *fast_cgi_multiple_threaded_app::thread_func(void *p) | |||
{ | |||
info_t *params=(info_t *)p; | |||
int id=params->first; | |||
fast_cgi_multiple_threaded_app *self=params->second; | |||
cgi_session *session; | |||
while((session=self->jobs.pop())!=NULL) { | |||
try{ | |||
if(session->prepare()){ | |||
self->workers[id]->run(session->get_connection()); | |||
} | |||
} | |||
catch(...){ | |||
delete session; | |||
return NULL; | |||
} | |||
delete session; | |||
} | |||
return NULL; | |||
} | |||
void fast_cgi_multiple_threaded_app::start_threads() | |||
{ | |||
int i; | |||
pids = new pthread_t [size]; | |||
threads_info = new info_t [size]; | |||
for(i=0;i<size;i++) { | |||
threads_info[i].first=i; | |||
threads_info[i].second=this; | |||
pthread_create(pids+i,NULL,thread_func,threads_info+i); | |||
} | |||
} | |||
void fast_cgi_multiple_threaded_app::wait_threads() | |||
{ | |||
int i; | |||
for(i=0;i<size;i++) { | |||
pthread_join(pids[i],NULL); | |||
} | |||
} | |||
bool fast_cgi_multiple_threaded_app::run() | |||
{ | |||
if(wait()==ACCEPT) { | |||
cgi_session *session=app.api->accept_session(); | |||
if(session){ | |||
jobs.push(session); | |||
} | |||
return true; | |||
} | |||
else {// Exit event | |||
int i; | |||
for(i=0;i<size;i++) { | |||
jobs.push(NULL); | |||
} | |||
wait_threads(); | |||
return false; | |||
} | |||
} | |||
#endif // if !defined(CPPCMS_EMBEDDED) || defined(CPPCMS_EMBEDDED_THREAD) | |||
#if !defined(CPPCMS_EMBEDDED) | |||
// Single instance of prefork | |||
prefork *prefork::self; | |||
void prefork::parent_handler(int s_catched) | |||
{ | |||
int i; | |||
int s; | |||
if(self->exit_flag==0) { | |||
self->exit_flag=1; | |||
s=SIGTERM; | |||
} | |||
else { | |||
s=SIGKILL; | |||
} | |||
set_signal_handler(SIGALRM,parent_handler); | |||
alarm(3); | |||
for(i=0;i<self->procs;i++) { | |||
kill(self->pids[i],s); | |||
} | |||
} | |||
void prefork::chaild_handler(int s) | |||
{ | |||
self->exit_flag=1; | |||
set_signal_handler(SIGALRM,chaild_handler); | |||
alarm(1); | |||
} | |||
void prefork::run() | |||
{ | |||
/* Signals defined by standard */ | |||
set_signal_handler(SIGTERM,chaild_handler); | |||
set_signal_handler(SIGUSR1,chaild_handler); | |||
/* Additional signal */ | |||
set_signal_handler(SIGINT,chaild_handler); | |||
base_factory &factory=*app.workers; | |||
auto_ptr<worker_thread> worker=factory(app); | |||
int limit=app.config.lval("server.iterations_limit",-1); | |||
if(limit!=-1) { | |||
srand(getpid()); | |||
limit=limit+(limit / 10 *(rand() % 100))/100; | |||
} | |||
int counter=0; | |||
while(!exit_flag){ | |||
if(limit!=-1 && counter>limit) | |||
return; | |||
counter++; | |||
auto_ptr<cgi_session> session; | |||
try{ | |||
session.reset(app.api->accept_session()); | |||
if(session.get() && session->prepare()) { | |||
worker->run(session->get_connection()); | |||
} | |||
} | |||
catch(exception const &e){ | |||
cerr<<e.what()<<endl; | |||
} | |||
} | |||
} | |||
prefork::prefork(manager &m) : | |||
web_application(m) | |||
{ | |||
procs=app.config.lval("server.procs",5); | |||
exit_flag=0; | |||
pids.resize(procs); | |||
self=this; | |||
} | |||
void prefork::execute() | |||
{ | |||
int i; | |||
for(i=0;i<procs;i++) { | |||
pid_t pid=fork(); | |||
if(pid<0) { | |||
perror("fork:"); | |||
int j; | |||
for(j=0;j<i;j++) { | |||
kill(pids[j],SIGKILL); | |||
wait(NULL); | |||
} | |||
exit(1); | |||
} | |||
if(pid>0) { | |||
pids[i]=pid; | |||
} | |||
else { // pid==0 | |||
run(); | |||
return; | |||
} | |||
} | |||
/* Signals defined by standard */ | |||
set_signal_handler(SIGTERM,parent_handler); | |||
set_signal_handler(SIGUSR1,parent_handler); | |||
/* Additional signal */ | |||
set_signal_handler(SIGINT,parent_handler); | |||
while(!prefork::exit_flag) { | |||
int stat; | |||
pid_t pid=wait(&stat); | |||
if(pid<0) { | |||
continue; | |||
} | |||
if(exit_flag) break; | |||
for(i=0;i<procs;i++) { | |||
if(pids[i]==pid) { | |||
if(!WIFEXITED(stat) || WEXITSTATUS(stat)!=0){ | |||
if(WIFEXITED(stat)) { | |||
cerr<<"Chaild "<<pid<<" exited with "<<WEXITSTATUS(stat)<<endl; | |||
} | |||
else if(WIFSIGNALED(stat)) { | |||
cerr<<"Chaild "<<pid<<" killed by "<<WTERMSIG(stat)<<endl; | |||
} | |||
else { | |||
cerr<<"Chaild "<<pid<<" exited for unknown reason"<<endl; | |||
} | |||
} | |||
pid=fork(); | |||
if(pid==0) { | |||
run(); | |||
return; | |||
} | |||
pids[i]=pid; | |||
break; | |||
} | |||
} | |||
} | |||
for(i=0;i<procs;i++) { | |||
while(wait(NULL)<0 && errno==EINTR) | |||
; | |||
} | |||
} | |||
#endif //if !defined(CPPCMS_EMBEDDED) | |||
} // END oF Details | |||
cache_factory *manager::get_cache_factory() | |||
{ | |||
#ifdef CPPCMS_EMBEDDED | |||
return new cache_factory(); | |||
#else | |||
string backend=config.sval("cache.backend","none"); | |||
if(backend=="none") { | |||
return new cache_factory(); | |||
} | |||
else if(backend=="threaded") { | |||
int n=config.lval("cache.limit",100); | |||
return new thread_cache_factory(n); | |||
} | |||
#ifdef EN_FORK_CACHE | |||
else if(backend=="fork") { | |||
#ifndef HAVE_PTHREADS_PSHARED | |||
// without pshared mutexes fork cache uses fcnlt for locking | |||
// and becomes not thread safe | |||
if(config.sval("server.mod","")=="thread") { | |||
throw cppcms_error("Can't use fork cache backend with mod_thread"); | |||
} | |||
#endif | |||
size_t s=config.lval("cache.memsize",64); | |||
string f=config.sval("cache.file",""); | |||
return new process_cache_factory(s*1024U,f=="" ? NULL: f.c_str()); | |||
} | |||
#endif | |||
#ifdef EN_TCP_CACHE | |||
else if(backend=="tcp") { | |||
vector<int> const &ports=config.llist("cache.ports"); | |||
vector<string> const &ips=config.slist("cache.ips"); | |||
return new tcp_cache_factory(ips,ports); | |||
} | |||
#endif | |||
else { | |||
throw cppcms_error("Unkown cache backend:" + backend); | |||
} | |||
#endif // cppcms_embedded | |||
} | |||
cgi_api *manager::get_api() | |||
{ | |||
#if defined(CPPCMS_EMBEDDED) && !defined(CPPCMS_EMBEDDED_THREAD) | |||
return new cgi_cgi_api(); | |||
#else | |||
string api=config.sval("server.api"); | |||
if(api=="cgi") { | |||
return new cgi_cgi_api(); | |||
} | |||
string socket=config.sval("server.socket",""); | |||
int backlog=config.lval("server.buffer",1); | |||
if(api=="scgi" ) { | |||
return new scgi_api(socket.c_str(),backlog); | |||
} | |||
#ifdef EN_FCGI_BACKEND | |||
if(api=="fastcgi"){ | |||
return new fcgi_api(socket.c_str(),backlog); | |||
} | |||
#endif | |||
throw cppcms_error("Unknown api:"+api); | |||
#endif // ! CGI only | |||
} | |||
web_application *manager::get_mod() | |||
{ | |||
#if defined(CPPCMS_EMBEDDED) && !defined(CPPCMS_EMBEDDED_THREAD) | |||
return new details::single_run(*this); | |||
#else | |||
if(config.sval("server.api","")=="cgi") { | |||
return new details::single_run(*this); | |||
} | |||
string mod=config.sval("server.mod"); | |||
#if !defined(CPPCMS_EMBEDDED) || defined(CPPCMS_EMBEDDED_THREAD) | |||
if(mod=="process") { | |||
return new details::fast_cgi_single_threaded_app(*this); | |||
} | |||
if(mod=="thread") { | |||
return new details::fast_cgi_multiple_threaded_app(*this); | |||
} | |||
#endif | |||
#if !defined(CPPCMS_EMBEDDED) | |||
if(mod=="prefork") { | |||
return new details::prefork(*this); | |||
} | |||
#endif | |||
throw cppcms_error("Unknown mod:" + mod); | |||
#endif | |||
} | |||
namespace { | |||
struct empty_backend { | |||
boost::shared_ptr<session_api> operator()(worker_thread &a) | |||
{ | |||
return boost::shared_ptr<session_api>(); // EMPTY | |||
} | |||
}; | |||
} | |||
session_backend_factory manager::get_sessions() | |||
{ | |||
string lock=config.sval("session.location","none"); | |||
if(lock=="none") | |||
return empty_backend(); | |||
session_backend_factory clnt; | |||
session_backend_factory srv; | |||
if(lock=="client" || lock=="both") { | |||
clnt=session_cookies::factory(); | |||
} | |||
if(lock=="server" || lock=="both") { | |||
string srv_backend=config.sval("session.backend","files"); | |||
if(srv_backend=="cache") | |||
srv=session_cache_backend::factory(); | |||
else if(srv_backend=="files") | |||
srv=session_file_storage::factory(config); | |||
#ifdef EN_SQLITE_SESSIONS | |||
else if(srv_backend=="sqlite") | |||
srv=session_sqlite_storage::factory(config); | |||
#endif | |||
#ifdef EN_TCP_CACHE | |||
else if(srv_backend=="tcp") | |||
srv=session_tcp_storage::factory(config); | |||
#endif | |||
else | |||
throw cppcms_error("Unknown backend:"+srv_backend); | |||
} | |||
if(lock=="server") | |||
return srv; | |||
if(lock=="client") | |||
return clnt; | |||
if(lock=="both") { | |||
int limit=config.ival("session.client_size_limit",2048); | |||
return session_dual::factory(clnt,srv,limit); | |||
} | |||
throw cppcms_error("Unknown location:"+lock); | |||
} | |||
void manager::execute() | |||
{ | |||
if(!workers.get()) { | |||
throw cppcms_error("No workers factory set up"); | |||
} | |||
if(!cache.get()) { | |||
set_cache(get_cache_factory()); | |||
} | |||
if(sessions.empty()) { | |||
set_sessions(get_sessions()); | |||
} | |||
if(!api.get()) { | |||
set_api(get_api()); | |||
} | |||
if(!gettext.get()){ | |||
set_gettext(get_gettext()); | |||
} | |||
if(!web_app.get()) { | |||
set_mod(get_mod()); | |||
} | |||
load_templates(); | |||
web_app->execute(); | |||
} | |||
void manager::load_templates() | |||
{ | |||
#if !defined(CPPCMS_EMBEDDED) | |||
string ext=config.sval("templates.ext", | |||
#ifdef __CYGWIN__ | |||
".dll" | |||
#else | |||
".so" | |||
#endif | |||
); | |||
// FIXME to something that works with autotools | |||
unsigned len=ext.size(); | |||
vector<string> const &dirs=config.slist("templates.dirs"); | |||
for(vector<string>::const_iterator dir=dirs.begin();dir!=dirs.end();++dir) { | |||
DIR *d=::opendir(dir->c_str()); | |||
if(!d) continue; | |||
for(struct dirent *entry=::readdir(d);entry;entry=::readdir(d)) { | |||
string filename=entry->d_name; | |||
if( filename.size()>len && | |||
filename.substr(filename.size()-len,len) == ext ) | |||
{ | |||
void *handler=::dlopen((*dir + "/" + filename).c_str(),RTLD_LAZY); | |||
if(handler) templates_list.push_back(handler); | |||
} | |||
} | |||
::closedir(d); | |||
} | |||
#endif | |||
} | |||
manager::~manager() | |||
{ | |||
#if !defined(CPPCMS_EMBEDDED) | |||
for_each(templates_list.begin(),templates_list.end(),::dlclose); | |||
#endif | |||
} | |||
void manager::set_sessions(session_backend_factory s) | |||
{ | |||
sessions=s; | |||
} | |||
void manager::set_worker(base_factory *w) | |||
{ | |||
workers=auto_ptr<base_factory>(w); | |||
} | |||
void manager::set_cache(cache_factory *c) | |||
{ | |||
cache=auto_ptr<cache_factory>(c); | |||
} | |||
void manager::set_api(cgi_api *a) | |||
{ | |||
api=auto_ptr<cgi_api>(get_api()); | |||
} | |||
void manager::set_mod(web_application *m) | |||
{ | |||
web_app=auto_ptr<web_application>(m); | |||
} | |||
transtext::trans_factory *manager::get_gettext() | |||
{ | |||
transtext::trans_factory *tmp=NULL; | |||
try{ | |||
tmp=new transtext::trans_factory(); | |||
tmp->load( config.sval ("locale.dir",""), | |||
config.slist("locale.lang_list"), | |||
config.sval ("locale.lang_default",""), | |||
config.slist ("locale.domain_list"), | |||
config.sval ("locale.domain_default","")); | |||
return tmp; | |||
} | |||
catch(...){ | |||
delete tmp; | |||
throw; | |||
} | |||
} | |||
void manager::set_gettext(transtext::trans_factory *s) | |||
{ | |||
gettext=auto_ptr<transtext::trans_factory>(s); | |||
} | |||
manager::manager(char const *f) | |||
{ | |||
config.load(0,NULL,f); | |||
} | |||
manager::manager(int argc, char **argv,char const *file) | |||
{ | |||
config.load(argc,argv,file); | |||
} | |||
manager::manager(int argc, char **argv) | |||
{ | |||
config.load(argc,argv); | |||
} | |||
} // END OF CPPCMS |
@@ -1,262 +0,0 @@ | |||
/////////////////////////////////////////////////////////////////////////////// | |||
// | |||
// Copyright (C) 2008-2010 Artyom Beilis (Tonkikh) <artyomtnk@yahoo.com> | |||
// | |||
// This program is free software: you can redistribute it and/or modify | |||
// it under the terms of the GNU Lesser General Public License as published by | |||
// the Free Software Foundation, either version 3 of the License, or | |||
// (at your option) any later version. | |||
// | |||
// This program is distributed in the hope that it will be useful, | |||
// but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
// GNU Lesser General Public License for more details. | |||
// | |||
// You should have received a copy of the GNU Lesser General Public License | |||
// along with this program. If not, see <http://www.gnu.org/licenses/>. | |||
// | |||
/////////////////////////////////////////////////////////////////////////////// | |||
#ifndef CPPCMS_MANAGER_H | |||
#define CPPCMS_MANAGER_H | |||
#include <pthread.h> | |||
#include <string> | |||
#include <memory> | |||
#include "worker_thread.h" | |||
#include "global_config.h" | |||
#include "cache_interface.h" | |||
#include "cgi_api.h" | |||
#include "posix_mutex.h" | |||
#include "transtext.h" | |||
#include "session_backend_factory.h" | |||
namespace cppcms { | |||
class manager; | |||
class base_factory { | |||
public: | |||
virtual std::auto_ptr<worker_thread> operator()(manager const &cf) const = 0; | |||
virtual ~base_factory() {}; | |||
}; | |||
template<typename T> | |||
class simple_factory : public base_factory { | |||
public: | |||
virtual std::auto_ptr<worker_thread> operator()(manager const &cf) const | |||
{ return std::auto_ptr<worker_thread>(new T(cf)); }; | |||
}; | |||
template<typename T,typename P> | |||
class one_param_factory : public base_factory { | |||
P const &P1; | |||
public: | |||
one_param_factory(P const &p) : P1(p) {}; | |||
virtual std::auto_ptr<worker_thread> operator()(manager const &cf) const | |||
{ return std::auto_ptr<worker_thread>(new T(cf,P1)); }; | |||
}; | |||
template<typename T,typename Pa,typename Pb> | |||
class two_params_factory : public base_factory { | |||
Pa const &P1; | |||
Pb const &P2; | |||
public: | |||
two_params_factory(Pa const &p1,Pb const &p2) : P1(p1), P2(p2) {}; | |||
virtual std::auto_ptr<worker_thread> operator()(manager const &cf) const | |||
{ return std::auto_ptr<worker_thread>(new T(cf,P1,P2)); }; | |||
}; | |||
class web_application { | |||
public: | |||
manager &app; | |||
web_application(manager &m) : app(m) {}; | |||
virtual void execute() = 0; | |||
virtual ~web_application() {}; | |||
}; | |||
namespace details { | |||
#if !defined(CPPCMS_EMBEDDED) || defined(CPPCMS_EMBEDDED_THREAD) | |||
class fast_cgi_application :public web_application { | |||
static fast_cgi_application *handlers_owner; | |||
protected: | |||
// General control | |||
bool the_end; | |||
static void handler(int id); | |||
typedef enum { EXIT , ACCEPT } event_t; | |||
virtual event_t wait(); | |||
void set_signal_handlers(); | |||
static fast_cgi_application *get_instance() { return handlers_owner; }; | |||
public: | |||
fast_cgi_application(manager &m) : web_application(m) {}; | |||
virtual ~fast_cgi_application() {}; | |||
void shutdown(); | |||
virtual bool run() { return false; }; | |||
virtual void execute(); | |||
}; | |||
class fast_cgi_single_threaded_app : public fast_cgi_application , public util::noncopyable { | |||
std::auto_ptr<worker_thread> worker; | |||
void setup(); | |||
public: | |||
virtual bool run(); | |||
fast_cgi_single_threaded_app(manager &m); | |||
virtual ~fast_cgi_single_threaded_app(){}; | |||
}; | |||
template <class T> | |||
class sefe_set { | |||
pthread_mutex_t access_mutex; | |||
pthread_cond_t new_data_availible; | |||
pthread_cond_t new_space_availible; | |||
protected: | |||
int max; | |||
int size; | |||
virtual T &get_int() = 0; | |||
virtual void put_int(T &val) = 0; | |||
public: | |||
void init(int size){ | |||
pthread_mutex_init(&access_mutex,NULL); | |||
pthread_cond_init(&new_data_availible,NULL); | |||
pthread_cond_init(&new_space_availible,NULL); | |||
max=size; | |||
this->size=0; | |||
}; | |||
sefe_set() {}; | |||
virtual ~sefe_set() {}; | |||
virtual void push(T val) { | |||
mutex_lock lock(access_mutex); | |||
while(size>=max) { | |||
pthread_cond_wait(&new_space_availible,&access_mutex); | |||
} | |||
put_int(val); | |||
pthread_cond_signal(&new_data_availible); | |||
}; | |||
T pop() { | |||
mutex_lock lock(access_mutex); | |||
while(size==0) { | |||
pthread_cond_wait(&new_data_availible,&access_mutex); | |||
} | |||
T data=get_int(); | |||
pthread_cond_signal(&new_space_availible); | |||
return data; | |||
}; | |||
}; | |||
template <class T> | |||
class sefe_queue : public sefe_set<T>{ | |||
T *queue; | |||
int head; | |||
int tail; | |||
int next(int x) { return (x+1)%this->max; }; | |||
protected: | |||
virtual void put_int(T &val) { | |||
queue[head]=val; | |||
head=next(head); | |||
this->size++; | |||
} | |||
virtual T &get_int() { | |||
this->size--; | |||
int ptr=tail; | |||
tail=next(tail); | |||
return queue[ptr]; | |||
} | |||
public: | |||
void init(int size) { | |||
if(queue) return; | |||
queue=new T [size]; | |||
sefe_set<T>::init(size); | |||
} | |||
sefe_queue() { queue = NULL; head=tail=0; }; | |||
virtual ~sefe_queue() { delete [] queue; }; | |||
}; | |||
class fast_cgi_multiple_threaded_app : public fast_cgi_application { | |||
int size; | |||
vector<worker_thread *> workers; | |||
sefe_queue<cgi_session *> jobs; | |||
typedef pair<int,fast_cgi_multiple_threaded_app*> info_t; | |||
info_t *threads_info; | |||
pthread_t *pids; | |||
static void *thread_func(void *p); | |||
void start_threads(); | |||
void wait_threads(); | |||
public: | |||
fast_cgi_multiple_threaded_app(manager &m); | |||
virtual bool run(); | |||
virtual ~fast_cgi_multiple_threaded_app() { | |||
delete [] pids; | |||
delete [] threads_info; | |||
for(unsigned i=0;i<workers.size();i++) | |||
delete workers[i]; | |||
}; | |||
}; | |||
#endif | |||
#if !defined(CPPCMS_EMBEDDED) | |||
class prefork : public web_application { | |||
vector<pid_t> pids; | |||
int procs; | |||
int exit_flag; | |||
static prefork *self; | |||
static void parent_handler(int s); | |||
static void chaild_handler(int s); | |||
void run(); | |||
public: | |||
prefork(manager &m); | |||
virtual void execute(); | |||
}; | |||
#endif | |||
} // END OF DETAILS | |||
void run_application(int argc,char *argv[],base_factory const &factory); | |||
class manager : private boost::noncopyable { | |||
cache_factory *get_cache_factory(); | |||
cgi_api *get_api(); | |||
web_application *get_mod(); | |||
session_backend_factory get_sessions(); | |||
transtext::trans_factory *get_gettext(); | |||
list<void *> templates_list; | |||
void load_templates(); | |||
public: | |||
cppcms_config config; | |||
auto_ptr<cache_factory> cache; | |||
auto_ptr<cgi_api> api; | |||
auto_ptr<base_factory> workers; | |||
auto_ptr<web_application> web_app; | |||
session_backend_factory sessions; | |||
auto_ptr<transtext::trans_factory> gettext; | |||
void set_worker(base_factory *w); | |||
void set_cache(cache_factory *c); | |||
void set_api(cgi_api *a); | |||
void set_mod(web_application *m); | |||
void set_gettext(transtext::trans_factory *); | |||
void set_sessions(session_backend_factory); | |||
manager(char const *file); | |||
manager(int argc, char **argv); | |||
manager(int argc, char **argv,char const *file); | |||
~manager(); | |||
void execute(); | |||
}; | |||
} | |||
#endif /* CPPCMS_MANAGER_H */ |
@@ -26,31 +26,31 @@ namespace cppcms { namespace util { | |||
struct binder0 { | |||
void (C::*member)(); | |||
P object; | |||
void operator()() { ((*object).*member)(); } | |||
void operator()() const { ((*object).*member)(); } | |||
}; | |||
template<typename C,typename P,typename P1> | |||
struct binder1 { | |||
void (C::*member)(P1); | |||
P object; | |||
void operator()(P1 p1) { ((*object).*member)(p1); } | |||
void operator()(P1 p1) const { ((*object).*member)(p1); } | |||
}; | |||
template<typename C,typename P,typename P1,typename P2> | |||
struct binder2 { | |||
void (C::*member)(P1,P2); | |||
P object; | |||
void operator()(P1 p1,P2 p2) { ((*object).*member)(p1,p2); } | |||
void operator()(P1 p1,P2 p2) const { ((*object).*member)(p1,p2); } | |||
}; | |||
template<typename C,typename P,typename P1,typename P2,typename P3> | |||
struct binder3 { | |||
void (C::*member)(P1,P2,P3); | |||
P object; | |||
void operator()(P1 p1,P2 p2,P3 p3) { ((*object).*member)(p1,p2,p3); } | |||
void operator()(P1 p1,P2 p2,P3 p3) const { ((*object).*member)(p1,p2,p3); } | |||
}; | |||
template<typename C,typename P,typename P1,typename P2,typename P3,typename P4> | |||
struct binder4 { | |||
void (C::*member)(P1,P2,P3,P4); | |||
P object; | |||
void operator()(P1 p1,P2 p2,P3 p3,P4 p4) { ((*object).*member)(p1,p2,p3,p4); } | |||
void operator()(P1 p1,P2 p2,P3 p3,P4 p4) const { ((*object).*member)(p1,p2,p3,p4); } | |||
}; | |||
} | |||
@@ -304,7 +304,7 @@ void service::shutdown() | |||
#endif | |||
} | |||
void service::after_fork(util::callback0 const &cb) | |||
void service::after_fork(function<void()> const &cb) | |||
{ | |||
impl_->on_fork_.push_back(cb); | |||
} | |||
@@ -589,7 +589,7 @@ cppcms::impl::service &service::impl() | |||
return *impl_; | |||
} | |||
void service::post(util::callback0 const &handler) | |||
void service::post(function<void()> const &handler) | |||
{ | |||
impl_->get_io_service().post(handler); | |||
} | |||
@@ -22,7 +22,7 @@ | |||
#include "defs.h" | |||
#include "noncopyable.h" | |||
#include "hold_ptr.h" | |||
#include "callback0.h" | |||
#include "function.h" | |||
#include <locale> | |||
@@ -66,8 +66,8 @@ namespace cppcms { | |||
cppcms::impl::service &impl(); | |||
void post(util::callback0 const &handler); | |||
void after_fork(util::callback0 const &handler); | |||
void post(function<void()> const &handler); | |||
void after_fork(function<void()> const &handler); | |||
int threads_no(); | |||
int procs_no(); | |||
@@ -59,7 +59,7 @@ namespace impl { | |||
std::auto_ptr<session_pool> session_pool_; | |||
std::locale default_locale_; | |||
std::vector<util::callback0> on_fork_; | |||
std::vector<function<void()> > on_fork_; | |||
int id_; | |||
@@ -1,46 +0,0 @@ | |||
/////////////////////////////////////////////////////////////////////////////// | |||
// | |||
// Copyright (C) 2008-2010 Artyom Beilis (Tonkikh) <artyomtnk@yahoo.com> | |||
// | |||
// This program is free software: you can redistribute it and/or modify | |||
// it under the terms of the GNU Lesser General Public License as published by | |||
// the Free Software Foundation, either version 3 of the License, or | |||
// (at your option) any later version. | |||
// | |||
// This program is distributed in the hope that it will be useful, | |||
// but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
// GNU Lesser General Public License for more details. | |||
// | |||
// You should have received a copy of the GNU Lesser General Public License | |||
// along with this program. If not, see <http://www.gnu.org/licenses/>. | |||
// | |||
/////////////////////////////////////////////////////////////////////////////// | |||
#ifndef CPPCMS_UTIL_SIGNAL0_H | |||
#define CPPCMS_UTIL_SIGNAL0_H | |||
#include "callback0.h" | |||
#include <list> | |||
namespace cppcms { namespace util { | |||
class signal0 { | |||
typedef std::list<callback0> callbacks_type; | |||
callbacks_type signals_; | |||
public: | |||
void connect(callback0 h) | |||
{ | |||
signals_.push_back(callback0()); | |||
signals_.back().swap(h); | |||
} | |||
void operator()() const | |||
{ | |||
for(callbacks_type::const_iterator p=signals_.begin();p!=signals_.end();++p) { | |||
(*p)(); | |||
} | |||
} | |||
}; | |||
}} // cppcms::util | |||
#endif |
@@ -1,3 +1,21 @@ | |||
/////////////////////////////////////////////////////////////////////////////// | |||
// | |||
// Copyright (C) 2008-2010 Artyom Beilis (Tonkikh) <artyomtnk@yahoo.com> | |||
// | |||
// This program is free software: you can redistribute it and/or modify | |||
// it under the terms of the GNU Lesser General Public License as published by | |||
// the Free Software Foundation, either version 3 of the License, or | |||
// (at your option) any later version. | |||
// | |||
// This program is distributed in the hope that it will be useful, | |||
// but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
// GNU Lesser General Public License for more details. | |||
// | |||
// You should have received a copy of the GNU Lesser General Public License | |||
// along with this program. If not, see <http://www.gnu.org/licenses/>. | |||
// | |||
/////////////////////////////////////////////////////////////////////////////// | |||
#include "function.h" | |||
#include "test.h" | |||
#include <iostream> | |||
@@ -52,7 +52,7 @@ namespace impl { | |||
} | |||
return false; | |||
} | |||
int post(util::callback0 const &job) | |||
int post(function<void()> const &job) | |||
{ | |||
boost::unique_lock<boost::mutex> lock(mutex_); | |||
int id=job_id_++; | |||
@@ -109,7 +109,7 @@ namespace impl { | |||
void worker() | |||
{ | |||
for(;;) { | |||
util::callback0 job; | |||
function<void()> job; | |||
{ | |||
boost::unique_lock<boost::mutex> lock(mutex_); | |||
@@ -124,7 +124,8 @@ namespace impl { | |||
} | |||
} | |||
job(); | |||
if(!job.empty()) | |||
job(); | |||
} | |||
} | |||
@@ -134,7 +135,7 @@ namespace impl { | |||
bool shut_down_; | |||
int job_id_; | |||
typedef std::list<std::pair<int,util::callback0> > queue_type; | |||
typedef std::list<std::pair<int,function<void()> > > queue_type; | |||
queue_type queue_; | |||
std::vector<boost::shared_ptr<boost::thread> > workers_; | |||
@@ -149,7 +150,7 @@ thread_pool::thread_pool(int n) : | |||
{ | |||
} | |||
int thread_pool::post(util::callback0 const &job) | |||
int thread_pool::post(function<void()> const &job) | |||
{ | |||
return impl_->post(job); | |||
} | |||
@@ -21,7 +21,7 @@ | |||
#include "defs.h" | |||
#include "noncopyable.h" | |||
#include "callback0.h" | |||
#include "function.h" | |||
#include "hold_ptr.h" | |||
namespace cppcms { | |||
@@ -33,7 +33,7 @@ namespace cppcms { | |||
class CPPCMS_API thread_pool : public util::noncopyable { | |||
public: | |||
int post(util::callback0 const &job); | |||
int post(function<void()> const &job); | |||
bool cancel(int id); | |||
thread_pool(int threads); | |||
void stop(); | |||
@@ -21,7 +21,7 @@ | |||
#include "noncopyable.h" | |||
#include "defs.h" | |||
#include "callback.h" | |||
#include "function.h" | |||
#include "hold_ptr.h" | |||
#include "mem_bind.h" | |||
#include <string> | |||
@@ -54,11 +54,11 @@ namespace cppcms { | |||
class CPPCMS_API url_dispatcher : public util::noncopyable { | |||
public: | |||
// Handlers | |||
typedef util::callback0 handler; | |||
typedef util::callback1<std::string> handler1; | |||
typedef util::callback2<std::string,std::string> handler2; | |||
typedef util::callback3<std::string,std::string,std::string> handler3; | |||
typedef util::callback4<std::string,std::string,std::string,std::string> handler4; | |||
typedef function<void()> handler; | |||
typedef function<void(std::string)> handler1; | |||
typedef function<void(std::string,std::string)> handler2; | |||
typedef function<void(std::string,std::string,std::string)> handler3; | |||
typedef function<void(std::string,std::string,std::string,std::string)> handler4; | |||
/// | |||
/// Assign \a handler to pattern \a regex thus if URL that matches | |||
@@ -1,234 +0,0 @@ | |||
/////////////////////////////////////////////////////////////////////////////// | |||
// | |||
// Copyright (C) 2008-2010 Artyom Beilis (Tonkikh) <artyomtnk@yahoo.com> | |||
// | |||
// This program is free software: you can redistribute it and/or modify | |||
// it under the terms of the GNU Lesser General Public License as published by | |||
// the Free Software Foundation, either version 3 of the License, or | |||
// (at your option) any later version. | |||
// | |||
// This program is distributed in the hope that it will be useful, | |||
// but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
// GNU Lesser General Public License for more details. | |||
// | |||
// You should have received a copy of the GNU Lesser General Public License | |||
// along with this program. If not, see <http://www.gnu.org/licenses/>. | |||
// | |||
/////////////////////////////////////////////////////////////////////////////// | |||
#define CPPCMS_SOURCE | |||
#include "config.h" | |||
#include "worker_thread.h" | |||
#include "global_config.h" | |||
#include "base_view.h" | |||
#ifndef CPPCMS_EMBEDDED | |||
#ifdef CPPCMS_USE_EXTERNAL_BOOST | |||
# include <boost/iostreams/filtering_stream.hpp> | |||
# include <boost/iostreams/filter/gzip.hpp> | |||
#else // Internal Boost | |||
# include <cppcms_boost/iostreams/filtering_stream.hpp> | |||
# include <cppcms_boost/iostreams/filter/gzip.hpp> | |||
namespace boost = cppcms_boost; | |||
#endif | |||
#endif | |||
#include "manager.h" | |||
using namespace cgicc; | |||
namespace cppcms { | |||
worker_thread::worker_thread(manager const &s) : | |||
app(s), | |||
cache(this), | |||
cout(&(this->out_buf)), | |||
on_start(), | |||
on_end(), | |||
session(*this) | |||
{ | |||
caching_module=app.cache->get(); | |||
static const transtext::trans tr; | |||
gt=&tr; | |||
} ; | |||
worker_thread::~worker_thread() | |||
{ | |||
app.cache->del(caching_module); | |||
} | |||
void worker_thread::main() | |||
{ | |||
on_start(); | |||
cout<<"<h1>Hello World</h2>\n"; | |||
on_end(); | |||
} | |||
void worker_thread::set_header(HTTPHeader *h) | |||
{ | |||
response_header=auto_ptr<HTTPHeader>(h); | |||
}; | |||
void worker_thread::add_header(string s) { | |||
other_headers.push_back(s); | |||
}; | |||
void worker_thread::set_cookie(cgicc::HTTPCookie const &c) | |||
{ | |||
response_header->setCookie(c); | |||
} | |||
void worker_thread::set_user_io() | |||
{ | |||
ostream &cout=cgi_conn->cout(); | |||
for(list<string>::iterator h=other_headers.begin();h!=other_headers.end();h++) { | |||
cout<<*h<<"\n"; | |||
} | |||
session.save(); | |||
cout<<header(); | |||
user_io=true; | |||
} | |||
void worker_thread::set_lang(string const &s) | |||
{ | |||
lang=s; | |||
gt=&app.gettext->get(s,""); | |||
} | |||
transtext::trans const *worker_thread::domain_gettext(string const &domain) | |||
{ | |||
return &app.gettext->get(lang,domain); | |||
} | |||
HTTPHeader &worker_thread::header() | |||
{ | |||
return *response_header; | |||
} | |||
void worker_thread::run(cgicc_connection &cgi_conn) | |||
{ | |||
cgi=&cgi_conn.cgi(); | |||
env=&(cgi->getEnvironment()); | |||
ostream &cgi_out=cgi_conn.cout(); | |||
other_headers.clear(); | |||
cache.reset(); | |||
set_lang(""); | |||
out_buf.str(""); | |||
this->cgi_conn=&cgi_conn; | |||
set_header(new HTTPHTMLHeader); | |||
gzip=gzip_done=false; | |||
user_io=false; | |||
#ifndef CPPCMS_EMBEDDED | |||
string encoding; | |||
if((encoding=cgi_conn.env("HTTP_ACCEPT_ENCODING"))!="") { | |||
if(strstr(encoding.c_str(),"gzip")!=NULL) { | |||
gzip=app.config.lval("gzip.enable",1); | |||
} | |||
} | |||
#endif | |||
if(app.config.lval("server.disable_xpowered_by",0)==0) { | |||
add_header("X-Powered-By: " PACKAGE_NAME "/" PACKAGE_VERSION); | |||
} | |||
try { | |||
/**********/ | |||
session.on_start(); | |||
main(); | |||
session.on_end(); | |||
/**********/ | |||
if(response_header.get() == NULL) { | |||
throw cppcms_error("Looks like a bug"); | |||
} | |||
} | |||
catch(std::exception const &e) { | |||
string msg=e.what(); | |||
cgi_out<<HTTPStatusHeader(500,msg); | |||
cgi_out<<"<html><body><p>"+msg+"</p><body></html>"; | |||
gzip=gzip_done=false; | |||
other_headers.clear(); | |||
out_buf.str(""); | |||
return; | |||
} | |||
if(user_io) { | |||
// user controls it's IO | |||
return; | |||
} | |||
for(list<string>::iterator h=other_headers.begin();h!=other_headers.end();h++) { | |||
cgi_out<<*h<<"\n"; | |||
} | |||
string out=out_buf.str(); | |||
out_buf.str(""); | |||
#ifndef CPPCMS_EMBEDDED | |||
if(gzip) { | |||
if(out.size()>0) { | |||
if(gzip_done){ | |||
cgi_out<<"Content-Length: "<<out.size()<<"\n"; | |||
} | |||
cgi_out<<"Content-Encoding: gzip\n"; | |||
cgi_out<<*response_header; | |||
if(gzip_done) { | |||
cgi_out<<out; | |||
} | |||
else{ | |||
int level=app.config.ival("gzip.level",-1); | |||
int length=app.config.ival("gzip.buffer",-1); | |||
deflate(out,cgi_out,level,length); | |||
} | |||
} | |||
else { | |||
cgi_out<<*response_header; | |||
} | |||
} | |||
else | |||
#endif | |||
{ | |||
cgi_out<<"Content-Length: "<<out.size()<<"\n"; | |||
cgi_out<<*response_header; | |||
cgi_out<<out; | |||
} | |||
} | |||
void worker_thread::no_gzip() | |||
{ | |||
gzip=false; | |||
} | |||
void worker_thread::render(string tmpl,string name,base_content &content,ostream &out ) | |||
{ | |||
using cppcms::details::views_storage; | |||
base_view::settings s(this,&out); | |||
auto_ptr<base_view> p(views_storage::instance().fetch_view(tmpl,name,s,&content)); | |||
if(!p.get()) throw cppcms_error("Template `"+name+"' not found in template set `" + tmpl +"'"); | |||
p->render(); | |||
}; | |||
void worker_thread::render(string tmpl,string name,base_content &content) | |||
{ | |||
render(tmpl,name,content,cout); | |||
}; | |||
void worker_thread::render(string name,base_content &content,ostream &o) | |||
{ | |||
render(current_template,name,content,o); | |||
}; | |||
void worker_thread::render(string name,base_content &content) | |||
{ | |||
render(current_template,name,content,cout); | |||
}; | |||
} | |||
@@ -1,121 +0,0 @@ | |||
/////////////////////////////////////////////////////////////////////////////// | |||
// | |||
// Copyright (C) 2008-2010 Artyom Beilis (Tonkikh) <artyomtnk@yahoo.com> | |||
// | |||
// This program is free software: you can redistribute it and/or modify | |||
// it under the terms of the GNU Lesser General Public License as published by | |||
// the Free Software Foundation, either version 3 of the License, or | |||
// (at your option) any later version. | |||
// | |||
// This program is distributed in the hope that it will be useful, | |||
// but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
// GNU Lesser General Public License for more details. | |||
// | |||
// You should have received a copy of the GNU Lesser General Public License | |||
// along with this program. If not, see <http://www.gnu.org/licenses/>. | |||
// | |||
/////////////////////////////////////////////////////////////////////////////// | |||
#ifndef _WORKER_THREAD_H_ | |||
#define _WORKER_THREAD_H_ | |||
#include <pthread.h> | |||
#include <sstream> | |||
#include <string> | |||
#include <cgicc/Cgicc.h> | |||
#include <cgicc/HTTPHTMLHeader.h> | |||
#include <cgicc/HTTPStatusHeader.h> | |||
#include <cgicc/HTMLClasses.h> | |||
#include "noncopyable.h" | |||
#include <memory> | |||
#include "signal0.h" | |||
#include "cppcms_error.h" | |||
#include "url_dispatcher.h" | |||
#include "cache_interface.h" | |||
#include "base_cache.h" | |||
#include "cgicc_connection.h" | |||
#include "transtext.h" | |||
#include "session_interface.h" | |||
namespace cppcms { | |||
class manager; | |||
class base_content; | |||
using namespace std; | |||
using cgicc::CgiEnvironment; | |||
using cgicc::Cgicc; | |||
using cgicc::HTTPHeader; | |||
class worker_thread: private util::noncopyable { | |||
int id; | |||
pthread_t pid; | |||
friend class cache_iface; | |||
friend class base_view; | |||
list<string> other_headers; | |||
base_cache *caching_module; | |||
bool user_io; | |||
bool gzip; | |||
bool gzip_done; | |||
stringbuf out_buf; | |||
transtext::trans const *gt; | |||
string lang; | |||
auto_ptr<HTTPHeader> response_header; | |||
string current_template; | |||
public: | |||
url_dispatcher url; | |||
manager const &app; | |||
Cgicc *cgi; | |||
CgiEnvironment const *env; | |||
cgicc_connection *cgi_conn; | |||
cache_iface cache; | |||
ostream cout; | |||
util::signal0 on_start; | |||
util::signal0 on_end; | |||
session_interface session; | |||
void set_header(HTTPHeader *h); | |||
void add_header(string s); | |||
void set_cookie(cgicc::HTTPCookie const &c); | |||
void set_user_io(); | |||
void no_gzip(); | |||
HTTPHeader &header(); | |||
void set_lang(); | |||
void set_lang(string const &s); | |||
inline void use_template(string s="") { current_template=s; }; | |||
void render(string name,base_content &content); | |||
void render(string templ,string name,base_content &content); | |||
void render(string name,base_content &content,ostream &); | |||
void render(string templ,string name,base_content &content,ostream &); | |||
virtual void main(); | |||
inline char const *gettext(char const *s) { return gt->gettext(s); }; | |||
inline char const *ngettext(char const *s,char const *p,int n) { return gt->ngettext(s,p,n); }; | |||
ostream &get_cout() { return cout; } | |||
transtext::trans const *domain_gettext(string const &domain); | |||
void run(cgicc_connection &); | |||
worker_thread(manager const &s); | |||
virtual ~worker_thread(); | |||
}; | |||
} | |||
#endif |