Browse Source

First building example

master
Artyom Beilis 15 years ago
parent
commit
2e9d3671e9
30 changed files with 475 additions and 395 deletions
  1. +71
    -53
      Makefile.am
  2. +66
    -30
      application.cpp
  3. +11
    -6
      application.h
  4. +1
    -0
      applications_pool.cpp
  5. +57
    -0
      applications_pool.h
  6. +8
    -4
      asio_config.h
  7. +8
    -3
      cgi_acceptor.h
  8. +42
    -3
      cgi_api.cpp
  9. +3
    -4
      cgi_api.h
  10. +4
    -2
      config.txt
  11. +30
    -67
      configure.in
  12. +1
    -0
      cppcms_error.cpp
  13. +2
    -1
      cppcms_error.h
  14. +21
    -0
      cppcms_error_category.cpp
  15. +2
    -13
      cppcms_error_category.h
  16. +14
    -0
      defs.h
  17. +1
    -0
      global_config.cpp
  18. +23
    -166
      hello_world.cpp
  19. +55
    -0
      http_context.cpp
  20. +3
    -1
      http_context.h
  21. +1
    -0
      http_cookie.cpp
  22. +1
    -0
      http_request.cpp
  23. +27
    -15
      http_response.cpp
  24. +0
    -2
      http_response.h
  25. +3
    -3
      light.conf
  26. +1
    -1
      scgi_api.h
  27. +14
    -16
      service.cpp
  28. +1
    -1
      service_impl.h
  29. +2
    -2
      thread_pool.cpp
  30. +2
    -2
      url_dispatcher.cpp

+ 71
- 53
Makefile.am View File

@@ -1,73 +1,91 @@
SUBDIRS = ./transtext tests
#SUBDIRS = ./transtext tests

noinst_PROGRAMS = hello_world.fcgi
noinst_HEADERS = hello_world_view.h
dist_bin_SCRIPTS = cppcms_tmpl_cc cppcms_run
bin_PROGRAMS = cppcms_make_key
noinst_PROGRAMS = hello_world
#noinst_HEADERS = hello_world_view.h
#dist_bin_SCRIPTS = cppcms_tmpl_cc cppcms_run
#bin_PROGRAMS = cppcms_make_key

EXTRA_DIST = hello_world_skin1.tmpl hello_world_view1.tmpl hello_world_skin2.tmpl Changelog autogen.sh config.txt
#EXTRA_DIST = hello_world_skin1.tmpl hello_world_view1.tmpl hello_world_skin2.tmpl Changelog autogen.sh config.txt

hello_world_fcgi_SOURCES = hello_world.cpp hello_world_view1.cpp hello_world_view2.cpp
hello_world_fcgi_LDADD = libcppcms.la transtext/libcppcmstranstext.la
hello_world_fcgi_CXXFLAGS= -Wall -I./transtext
hello_world_SOURCES= hello_world.cpp
hello_world_LDADD= libcppcms.la
hello_world_CXXFLAGS= -g -Wall



hello_world_view1.cpp: hello_world_skin1.tmpl hello_world_view1.tmpl
./cppcms_tmpl_cc hello_world_skin1.tmpl hello_world_view1.tmpl -o hello_world_view1.cpp -n view1 -d test
#hello_world_view1.cpp: hello_world_skin1.tmpl hello_world_view1.tmpl
# ./cppcms_tmpl_cc hello_world_skin1.tmpl hello_world_view1.tmpl -o hello_world_view1.cpp -n view1 -d test

hello_world_view2.cpp: hello_world_skin2.tmpl hello_world_view1.tmpl
./cppcms_tmpl_cc hello_world_skin2.tmpl hello_world_view1.tmpl -o hello_world_view2.cpp -n view2 -d test
#hello_world_view2.cpp: hello_world_skin2.tmpl hello_world_view1.tmpl
# ./cppcms_tmpl_cc hello_world_skin2.tmpl hello_world_view1.tmpl -o hello_world_view2.cpp -n view2 -d test

lib_LTLIBRARIES = libcppcms.la
libcppcms_la_SOURCES = global_config.cpp manager.cpp worker_thread.cpp \
text_tool.cpp cache_interface.cpp base_cache.cpp thread_cache.cpp scgi.cpp \
base_view.cpp util.cpp form.cpp application.cpp session_interface.cpp \
session_cookies.cpp hmac_encryptor.cpp encryptor.cpp md5.c base64.cpp \
session_sid.cpp session_file_storage.cpp session_dual.cpp cppcms_error.cpp \
url_dispatcher.cpp regex.cpp format.cpp json.cpp encoding.cpp
libcppcms_la_SOURCES = \
service.cpp \
cgi_api.cpp \
http_request.cpp \
http_response.cpp \
http_context.cpp \
global_config.cpp \
cppcms_error.cpp \
cppcms_error_category.cpp \
thread_pool.cpp \
applications_pool.cpp \
application.cpp \
url_dispatcher.cpp \
http_cookie.cpp




#libcppcms_la_SOURCES = global_config.cpp manager.cpp worker_thread.cpp \
# text_tool.cpp cache_interface.cpp base_cache.cpp thread_cache.cpp scgi.cpp \
# base_view.cpp util.cpp form.cpp application.cpp session_interface.cpp \
# session_cookies.cpp hmac_encryptor.cpp encryptor.cpp md5.c base64.cpp \
# session_sid.cpp session_file_storage.cpp session_dual.cpp cppcms_error.cpp \
# url_dispatcher.cpp regex.cpp format.cpp json.cpp encoding.cpp

libcppcms_la_LDFLAGS = -no-undefined -version-info 0:0:0
libcppcms_la_LIBADD = @CPPCMS_LIBS@ transtext/libcppcmstranstext.la
libcppcms_la_CXXFLAGS = -Wall -I./transtext
libcppcms_la_LIBADD = @CPPCMS_LIBS@
libcppcms_la_CXXFLAGS = -g -Wall

if EN_FORK_CACHE
libcppcms_la_SOURCES += process_cache.cpp
endif
#if EN_FORK_CACHE
#libcppcms_la_SOURCES += process_cache.cpp
#endif

if EN_FCGI_BACKEND
libcppcms_la_SOURCES += fcgi.cpp
endif
#if EN_FCGI_BACKEND
#libcppcms_la_SOURCES += fcgi.cpp
#endif

if EN_ENCR_SESSIONS
libcppcms_la_SOURCES += aes_encryptor.cpp
endif

if EN_SQLITE_SESSIONS
libcppcms_la_SOURCES += session_sqlite_storage.cpp
#libcppcms_la_SOURCES += aes_encryptor.cpp
endif

nobase_pkginclude_HEADERS = global_config.h text_tool.h cppcms_error.h \
manager.h worker_thread.h fcgi.h cache_interface.h archive.h \
base_cache.h thread_cache.h cgicc_connection.h scgi.h cgi_api.h \
process_cache.h shmem_allocator.h posix_mutex.h config.h cgi.h base_view.h \
util.h form.h application.h session_interface.h session_api.h session_cookies.h \
hmac_encryptor.h aes_encryptor.h encryptor.h md5.h base64.h session_backend_factory.h \
session_sid.h session_storage.h session_file_storage.h session_dual.h \
session_cache_backend.h session_sqlite_storage.h tcp_cache_protocol.h tcp_cache.h \
tcp_connector.h session_tcp_storage.h tcp_messenger.h asio_config.h fcntl_mutex.h

if EN_TCP_CACHE
libcppcms_la_SOURCES += tcp_cache.cpp tcp_messenger.cpp session_tcp_storage.cpp tcp_connector.cpp
bin_PROGRAMS += cppcms_tcp_scale
cppcms_tcp_scale_SOURCES = base_cache.cpp thread_cache.cpp tcp_cache_server.cpp session_file_storage.cpp cppcms_error.cpp
cppcms_tcp_scale_CXXFLAGS=-DNO_BUILDER_INTERFACE
cppcms_tcp_scale_LDADD = @TCPSCALE_LIBS@
if EN_SQLITE_SESSIONS
cppcms_tcp_scale_SOURCES += session_sqlite_storage.cpp
endif

endif
#if EN_SQLITE_SESSIONS
#libcppcms_la_SOURCES += session_sqlite_storage.cpp
#endif

#nobase_pkginclude_HEADERS = global_config.h text_tool.h cppcms_error.h \
# manager.h worker_thread.h fcgi.h cache_interface.h archive.h \
# base_cache.h thread_cache.h cgicc_connection.h scgi.h cgi_api.h \
# process_cache.h shmem_allocator.h posix_mutex.h config.h cgi.h base_view.h \
# util.h form.h application.h session_interface.h session_api.h session_cookies.h \
# hmac_encryptor.h aes_encryptor.h encryptor.h md5.h base64.h session_backend_factory.h \
# session_sid.h session_storage.h session_file_storage.h session_dual.h \
# session_cache_backend.h session_sqlite_storage.h tcp_cache_protocol.h tcp_cache.h \
# tcp_connector.h session_tcp_storage.h tcp_messenger.h asio_config.h fcntl_mutex.h

#if EN_TCP_CACHE
#libcppcms_la_SOURCES += tcp_cache.cpp tcp_messenger.cpp session_tcp_storage.cpp tcp_connector.cpp
#bin_PROGRAMS += cppcms_tcp_scale
#cppcms_tcp_scale_SOURCES = base_cache.cpp thread_cache.cpp tcp_cache_server.cpp session_file_storage.cpp cppcms_error.cpp
#cppcms_tcp_scale_CXXFLAGS=-DNO_BUILDER_INTERFACE
#cppcms_tcp_scale_LDADD = @TCPSCALE_LIBS@
#if EN_SQLITE_SESSIONS
#cppcms_tcp_scale_SOURCES += session_sqlite_storage.cpp
#endif
#
#endif




+ 66
- 30
application.cpp View File

@@ -1,48 +1,84 @@
#define CPPCMS_SOURCE

#include "application.h"
#include "http_context.h"
#include "service.h"
#include "cppcms_error.h"
#include "url_dispatcher.h"


namespace cppcms {
application::application(worker_thread &w) :
worker(w),
url(w.url),
app(worker.app),
cgi(worker.cgi),
env(worker.env),
cgi_conn(worker.cgi_conn),
cache(worker.cache),
session(worker.session),
cout(worker.cout),
on_start(worker.on_start),
on_end(worker.on_end)

struct application::data {
data(cppcms::service *s):
service(s),
conn(0),
pool_id(-1)
{
}
cppcms::service *service;
http::context *conn;
int pool_id;
url_dispatcher url;
};

application::application(cppcms::service &srv) :
d(new data(&srv))
{

}

application::~application()
{
}

void application::on_404()
cppcms::service &application::service()
{
set_header(new cgicc::HTTPStatusHeader(404,"Not found"));
cout<< "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\"\n"
" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n"
"<html>\n"
" <head>\n"
" <title>404 - Not Found</title>\n"
" </head>\n"
" <body>\n"
" <h1>404 - Not Found</h1>\n"
" </body>\n"
"</html>\n";
return *d->service;
}

void application::main()
cppcms_config const &application::settings()
{
on_start();
if(url.dispatch(env->getPathInfo())<0) {
on_404();
}
on_end();
return service().settings();
}

http::request &application::request()
{
return context().request();
}
http::response &application::response()
{
return context().response();
}

url_dispatcher &application::dispatcher()
{
return d->url;
}


http::context &application::context()
{
if(!d->conn)
throw cppcms_error("Trying to access uninitialized context");
return *d->conn;
}

void application::assign_context(http::context *conn)
{
d->conn=conn;
}

void application::pool_id(int id)
{
d->pool_id=id;
}

int application::pool_id()
{
return d->pool_id;
}



} // cppcms

+ 11
- 6
application.h View File

@@ -9,13 +9,13 @@ namespace cppcms {

class service;
class cppcms_config;
class context;
class url_dispatcher;
class applications_pool;

namespace http {
class request;
class response;
class context;
}

class CPPCMS_API application : public util::noncopyable {
@@ -24,17 +24,22 @@ namespace cppcms {
~application();

cppcms::service &service();
cppcms_config const &config();
cppcms::context &context();
cppcms_config const &settings();
http::context &context();
http::request &request();
http::response &response();
url_dispatcher &dispatcher();
private:
struct data;
util::hold_ptr<data> d;

void assign_context(http::context *conn);
private:
void pool_id(int id);
int pool_id();


struct data; // future use
util::hold_ptr<data> d;


friend class applications_pool;
};



+ 1
- 0
applications_pool.cpp View File

@@ -1,3 +1,4 @@
#define CPPCMS_SOURCE
#include "applications_pool.h"
#include "application.h"
#include <set>


+ 57
- 0
applications_pool.h View File

@@ -34,6 +34,63 @@ namespace cppcms {
util::hold_ptr<data> d;
};

namespace details {
template<typename T>
struct simple_factory0 : public applications_pool::factory
{
std::auto_ptr<application> operator()(service &s) const
{
std::auto_ptr<application> app(new T(s));
return app;
}
};
template<typename T,typename P1>
struct simple_factory1 : public applications_pool::factory
{
simple_factory1(P1 p1) : p1_(p1) {}
P1 p1_;
std::auto_ptr<application> operator()(service &s) const
{
std::auto_ptr<application> app(new T(s,p1_));
return app;
}
};
template<typename T,typename P1,typename P2>
struct simple_factory2 : public applications_pool::factory
{
simple_factory2(P1 p1,P2 p2) : p1_(p1),p2_(p2) {}
P1 p1_;
P2 p2_;
std::auto_ptr<application> operator()(service &s) const
{
std::auto_ptr<application> app(new T(s,p1_,p2_));
return app;
}
};
} // details

template<typename T>
std::auto_ptr<applications_pool::factory> applications_factory()
{
std::auto_ptr<applications_pool::factory> f(new details::simple_factory0<T>);
return f;
}
template<typename T,typename P1>
std::auto_ptr<applications_pool::factory> applications_factory(P1 p1)
{
std::auto_ptr<applications_pool::factory> f(new details::simple_factory1<T,P1>(p1));
return f;
}
template<typename T,typename P1,typename P2>
std::auto_ptr<applications_pool::factory> applications_factory(P1 p1,P2 p2)
{
std::auto_ptr<applications_pool::factory> f(new details::simple_factory2<T,P1,P2>(p1,p2));
return f;
}


} // cppcms




+ 8
- 4
asio_config.h View File

@@ -1,10 +1,14 @@
#ifndef CPPCMS_ASIO_CONF_H
#define CPPCMS_ASIO_CONF_H

#if defined(_WIN32)
# define _WIN32_WINNT 0x0500
#elif defined(__CYGWIN__)
# define _WIN32_WINNT 0x0500
#include "defs.h"
#if defined(CPPCMS_WIN32)
# ifndef _WIN32_WINNT
# define _WIN32_WINNT 0x0501
# endif
#endif

#if defined(CPPCMS_CYGWIN)
# define __USE_W32_SOCKETS 1
#endif



+ 8
- 3
cgi_acceptor.h View File

@@ -35,7 +35,12 @@ namespace impl {
virtual void stop()
{
stopped_=true;
acceptor_.cancel();
boost::system::error_code e;
#ifdef CPPCMS_WIN32
acceptor_.close(e);
#else
acceptor_.cancel(e);
#endif
}
private:
void on_accept(boost::system::error_code const &e)
@@ -51,7 +56,7 @@ namespace impl {
{
socket->set_option(boost::asio::ip::tcp::no_delay(true));
}
#if !defined(_WIN32) && !defined(__CYGWIN__)
#if !defined(CPPCMS_WIN32)
void set_options(boost::asio::local::stream_protocol::socket *socket)
{
// nothing;
@@ -66,7 +71,7 @@ namespace impl {
bool stopped_;
};

#if !defined(_WIN32) && !defined(__CYGWIN__)
#if !defined(CPPCMS_WIN32)
template<typename API>
class unix_socket_acceptor : public socket_acceptor<boost::asio::local::stream_protocol,API>
{


+ 42
- 3
cgi_api.cpp View File

@@ -1,3 +1,4 @@
#define CPPCMS_SOURCE
#include "asio_config.h"

#include "application.h"
@@ -38,6 +39,16 @@ namespace {

namespace cppcms { namespace impl { namespace cgi {

connection::connection(cppcms::service &srv) :
service_(&srv)
{
}

connection::~connection()
{
}


cppcms::service &connection::service()
{
return *service_;
@@ -86,7 +97,7 @@ void connection::load_content(boost::system::error_code const &e)

async_read( &content_.front(),
content_.size(),
boost::bind(&connection::on_content_read,shared_from_this(),_1));
boost::bind(&connection::process_request,shared_from_this(),_1));

}

@@ -138,9 +149,12 @@ void connection::setup_application()
url_dispatcher::dispatch_type how;
if(application_.get() == 0 || (how=application_->dispatcher().dispatchable(path))!=url_dispatcher::none) {
make_error_response(http::response::not_found);
on_response_complete();
return;
}

application_->assign_context(context_.get());

if(how == url_dispatcher::asynchronous) {
dispatch(false);
}
@@ -157,10 +171,15 @@ void connection::dispatch(bool in_thread)
{
try {
application_->dispatcher().dispatch();
context_->response().finalize();
context_->response().out() << std::flush;
}
catch(std::exception const &e){
// TODO
if(!context_->response().some_output_was_written()) {
if(!in_thread)
context_->response().io_mode(http::response::asynchronous);
make_error_response(http::response::internal_server_error);
}
// TODO log it
}
if(in_thread)
get_io_service().post(boost::bind(&connection::on_response_complete,shared_from_this()));
@@ -170,13 +189,33 @@ void connection::dispatch(bool in_thread)

void connection::on_response_complete()
{
application_->assign_context(0);
service().applications_pool().put(application_);

if(context_->response().io_mode() == http::response::asynchronous) {
async_chunk_=context_->response().get_async_chunk();
if(!async_chunk_.empty()) {
async_write(
async_chunk_.c_str(),
async_chunk_.size(),
boost::bind(&connection::try_restart,shared_from_this(),_1));
return;
}
}
try_restart(boost::system::error_code());
}

void connection::try_restart(boost::system::error_code const &e)
{
if(e) return;

if(keep_alive()) {
context_.reset();
on_accepted();
}
}


namespace {
struct reader {
reader(connection *C,io_handler const &H,size_t S,char *P) : h(H), s(S), p(P),conn(C)


+ 3
- 4
cgi_api.h View File

@@ -4,13 +4,11 @@
#include "noncopyable.h"

#include <vector>

#include "asio_config.h"

#include <boost/enable_shared_from_this.hpp>
#include <boost/function.hpp>
#include <boost/system/error_code.hpp>

namespace boost { namespace asio { class io_service; } }


namespace cppcms {
@@ -69,7 +67,6 @@ namespace cgi {
void async_write(void const *,size_t,io_handler const &h);
private:
void load_content(boost::system::error_code const &e);
void on_content_read(boost::system::error_code const &e);
void process_request(boost::system::error_code const &e);

void load_multipart_form_data();
@@ -77,12 +74,14 @@ namespace cgi {
void setup_application();
void dispatch(bool thread);
void on_response_complete();
void try_restart(boost::system::error_code const &);

std::auto_ptr<http::context> context_;
std::vector<char> content_;
std::auto_ptr<application> application_;

cppcms::service *service_;
std::string async_chunk_;

};



+ 4
- 2
config.txt View File

@@ -1,6 +1,7 @@
# Server API settings

server.api = "fastcgi" # fastcgi -- preferred API
service.worker_threads = 0
service.api = "scgi" # fastcgi -- preferred API
# scgi -- simplefied FCGI API -- yet another alternative
# cgi -- Use only in case you application does huge amount of work
# such the fork()+exec() time in neligable
@@ -23,7 +24,8 @@ server.buffer = 100 # Default 1 -- relevant for multi-threaded model
# How many requests may be "on-hold" even if
# thread pool is full. Also sets "listen(2) backlog parameter

server.socket = "/tmp/hello-fastcgi.socket" # Default is "" -- use default socket given
service.port = 8000
# service.socket = "/tmp/hello-fastcgi.socket" # Default is "" -- use default socket given
# by web server -

# server.disable_xpowered_by = 0 # Disable X-Powered-By header (default enabled)


+ 30
- 67
configure.in View File

@@ -82,33 +82,6 @@ AC_TRY_RUN([ #include <pthread.h>
echo "Check: process shared mutex... ok"],[echo "Check: process shared mutex not supported"],[echo "Cross compile, assume no"])


if test "x$enable_forkcache" != "xno" ; then
AC_CHECK_LIB(mm,main,[
have_mm=yes
CPPCMS_LIBS="-lmm $CPPCMS_LIBS"
AC_DEFINE([EN_FORK_CACHE],[],["Enable fork cache"])
],
[ echo "======================================================================"
echo " OSSP mm library (libmm) not installed"
echo " The fork cache backend is disabled "
echo "======================================================================" ])
fi

AM_CONDITIONAL(EN_FORK_CACHE,[test "x$have_mm" = "xyes" ])

if test "x$enable_fastcgi" != "xno" ; then
AC_CHECK_LIB(fcgi++,main,[
have_fcgi=yes
CPPCMS_LIBS="-lfcgi++ -lfcgi $CPPCMS_LIBS"
AC_DEFINE([EN_FCGI_BACKEND],[],["Enable fastcgi backend"])
],
[ echo "======================================================================"
echo "Fast CGI library not installed"
echo "============== FastCGI API will be disabled =========================="
echo "You still have scgi and cgi API" ])
fi
AM_CONDITIONAL(EN_FCGI_BACKEND,[test "x$have_fcgi" = "xyes" ])

if test "x$enable_crypt" != "xno" ; then
AC_CHECK_LIB(gcrypt,main,[
have_gcrypt=yes
@@ -121,19 +94,6 @@ if test "x$enable_crypt" != "xno" ; then
fi
AM_CONDITIONAL(EN_ENCR_SESSIONS,[test "x$have_gcrypt" = "xyes" ])

if test "x$enable_sqlite" != "xno" ; then
AC_CHECK_LIB(sqlite3,sqlite3_open,[
have_sqlite3=yes
LIBS="-lsqlite3 $LIBS"
AC_DEFINE([EN_SQLITE_SESSIONS],[],["Enable sqlite sessions"])
],
[ echo "====================================================================="
echo "libsqlite3 not found, Sqlite sessions backend is disabled"
echo "=====================================================================" ])
fi
AM_CONDITIONAL(EN_SQLITE_SESSIONS,[test "x$have_sqlite3" = "xyes" ])


have_auto_type_detection=no

AC_TRY_COMPILE([],[int \$1=10;],[
@@ -226,12 +186,13 @@ then
fi
fi

case $host in
*cygwin*) CPPCMS_LIBS="-lws2_32 -lwsock32 $CPPCMS_LIBS"
esac

if test "x$have_asio" = "xyes"
then
AC_DEFINE([EN_TCP_CACHE],[],["Enable tcp cache"])
case $host in
*cygwin*) LIBS="-lws2_32 $LIBS"
esac
fi


@@ -250,34 +211,36 @@ then
AC_SEARCH_LIBS(gethostbyname,nsl socket)
fi

if test "x$bsts" = "x"
then
AC_CHECK_LIB(boost_regex,main,[
CPPCMS_LIBS="-lboost_regex $CPPCMS_LIBS"
],
[AC_CHECK_LIB(boost_regex-gcc-mt,main,[
],[AC_CHECK_LIB(boost_regex-gcc-mt,main,[
CPPCMS_LIBS="-lboost_regex-gcc-mt $CPPCMS_LIBS"
],[ echo "boost::regex not found" ; exit -1])])
if test "x$cms_bld" = "xnormal"
then
AC_CHECK_LIB(boost_iostreams,main,[
CPPCMS_LIBS="-lboost_iostreams $CPPCMS_LIBS"
],[AC_CHECK_LIB(boost_iostreams-gcc-mt,main,[
CPPCMS_LIBS="-lboost_iostreams-gcc-mt $CPPCMS_LIBS"
],[ echo "boost::iostreams not found" ; exit -1])])
fi
AC_CHECK_LIB(boost_signals,main,[
CPPCMS_LIBS="-lboost_signals $CPPCMS_LIBS"
],[AC_CHECK_LIB(boost_signals-gcc-mt,main,[
CPPCMS_LIBS="-lboost_signals-gcc-mt $CPPCMS_LIBS"
],[ echo "boost::signals not found" ; exit -1])])
else
CPPCMS_LIBS="-lboost_regex-$bsts -lboost_iostreams-$bsts -lboost_signals-$bsts $CPPCMS_LIBS"
if test "x$cms_bld" = "xnormal"
then
CPPCMS_LIBS="-lboost_iostreams-$bsts CPPCMS_LIBS"
fi
fi

AC_CHECK_LIB(boost_iostreams,main,[
CPPCMS_LIBS="-lboost_iostreams $CPPCMS_LIBS"
],[AC_CHECK_LIB(boost_iostreams-gcc-mt,main,[
CPPCMS_LIBS="-lboost_iostreams-gcc-mt $CPPCMS_LIBS"
],[ echo "boost::iostreams not found" ; exit -1])])

AC_CHECK_LIB(boost_system,main,[
CPPCMS_LIBS="-lboost_system $CPPCMS_LIBS"
],[AC_CHECK_LIB(boost_system-gcc-mt,main,[
CPPCMS_LIBS="-lboost_system-gcc-mt $CPPCMS_LIBS"
],[ echo "boost::system not found" ; exit -1])])

AC_CHECK_LIB(boost_thread,main,[
CPPCMS_LIBS="-lboost_thread $CPPCMS_LIBS"
],[AC_CHECK_LIB(boost_thread-gcc-mt,main,[
CPPCMS_LIBS="-lboost_thread-gcc-mt $CPPCMS_LIBS"
],[ echo "boost::thread not found" ; exit -1])])

AC_CHECK_LIB(boost_date_time,main,[
CPPCMS_LIBS="-lboost_date_time $CPPCMS_LIBS"
],[AC_CHECK_LIB(boost_date_time-gcc-mt,main,[
CPPCMS_LIBS="-lboost_date_time-gcc-mt $CPPCMS_LIBS"
],[ echo "boost::date_time not found" ; exit -1])])


CPPCMS_LIBS="$CPPCMS_LIBS $LIBS"
TCPSCALE_LIBS="$LIBS"


+ 1
- 0
cppcms_error.cpp View File

@@ -1,3 +1,4 @@
#define CPPCMS_SOURCE
#include "cppcms_error.h"
#include <iostream>
#include <string.h>


+ 2
- 1
cppcms_error.h View File

@@ -1,13 +1,14 @@
#ifndef CPPCMS_ERROR_H
#define CPPCMS_ERROR_H

#include "defs.h"
#include <string>
#include <stdexcept>

namespace cppcms {


class cppcms_error : public std::runtime_error {
class CPPCMS_API cppcms_error : public std::runtime_error {
std::string strerror(int err);
public:
cppcms_error(int err,std::string const &error);


+ 21
- 0
cppcms_error_category.cpp View File

@@ -0,0 +1,21 @@
#include "cppcms_error_category.h"

namespace cppcms {
namespace impl {
char const *error_category::name() const
{
return "cppcms::io";
}
std::string error_category::message(int cat) const
{
switch(cat) {
case errc::ok: return "ok";
case errc::protocol_violation: return "protocol violation";
default:
return "unknown";
}
}
const error_category cppcms_category;

} // impl
} // cppcms

+ 2
- 13
cppcms_error_category.h View File

@@ -13,19 +13,8 @@ namespace cppcms {
}
class error_category : public boost::system::error_category {
public:
virtual char const *name() const
{
return "cppcms::io";
}
virtual std::string message(int cat) const
{
switch(cat) {
case errc::ok: return "ok";
case errc::protocol_violation: return "protocol violation";
default:
return "unknown";
}
}
virtual char const *name() const;
virtual std::string message(int cat) const;
};

extern const error_category cppcms_category;


+ 14
- 0
defs.h View File

@@ -15,5 +15,19 @@
# define CPPCMS_API __attribute__((visibility("default")))
#endif

#if (defined(WIN32) || defined(_WIN32) || defined(__WIN32)) && !defined(__CYGWIN__)
#define CPPCMS_WIN_NATIVE
#endif
#if defined(__CYGWIN__)
#define CPPCMS_CYGWIN
#endif

#if defined(CPPCMS_WIN_NATIVE) || defined(CPPCMS_CYGWIN)
#define CPPCMS_WIN32
#endif

#if !defined(CPPCMS_WIN_NATIVE)
#define CPPCMS_POSIX
#endif

#endif /// CPPCMS_DEFS_H

+ 1
- 0
global_config.cpp View File

@@ -1,3 +1,4 @@
#define CPPCMS_SOURCE
#include "global_config.h"
#include "cppcms_error.h"
#include <map>


+ 23
- 166
hello_world.cpp View File

@@ -1,180 +1,37 @@
#include "application.h"
#include "manager.h"
#include "hello_world_view.h"
#include "regex.h"
using namespace cppcms;
#include "url_dispatcher.h"
#include "applications_pool.h"
#include "service.h"
#include "http_response.h"

class my_hello_world : public application {

class hello : public cppcms::application {
public:
my_hello_world(worker_thread &w) :
application(w)
hello(cppcms::service &srv) :
cppcms::application(srv)
{
using util::regex;
static const regex std("^/?$");
url.assign(std,&my_hello_world::std,this);
static const regex test("^/test$");
url.assign(test,&my_hello_world::test,this);
static const regex test2("^/test2$");
url.assign(test2,&my_hello_world::test2,this);
static const regex cache("^/cache$");
url.assign(cache,&my_hello_world::cache_test,this);
static const regex png("^/png$");
url.assign(png,&my_hello_world::png,this);
use_template("view2");
};
void test();
void png();
void test2();
void std();
void cache_test();
};

void my_hello_world::png()
{
ifstream file("test.png");
if(!file) {
cout<<"File test.png not found";
return ;
}
vector<char> buffer(1024);

set_header(new cgicc::HTTPContentHeader("image/png"));
set_user_io();
ostream &cout=cgi_conn->cout();

for(;;) {
file.read(&buffer.front(),1024);
cout.write(&buffer.front(),file.gcount());
if(file.eof())
break;
}
file.close();
}


void my_hello_world::test2()
{
if(!session.is_set("test")) {
session["test"]="1";
cout<<"Set 1";
}
else {
int state=session.get<int>("test");
switch(state) {
case 1:
if(!session.is_exposed("test")) {
cout<<"Expose 1";
session.expose("test");
}
else {
session["test"]="2";
cout<<"Change exposed to 2";
}
break;
case 2:
if(session.is_exposed("test")) {
session.hide("test");
cout<<"Hidden 2";
}
else {
session["test"]="3";
cout<<"Hidden 2 moved to 3 and exposed";
session.expose("test");
}
break;
case 3:
session.del("test");
cout<<"Remove 3 and remove from hidden";
break;
default:
cout<<"Error";
}
}

}

void my_hello_world::test()
{
if(!session.is_set("time")) {
cout<<"No Time\n";
dispatcher().assign(".*",&hello::hello_world,this);
}
else {
time_t given=session.get<time_t>("time");
cout<<asctime(gmtime(&given))<<"<br/>\n";
if(session.is_set("msg")) {
cout<<session["msg"]<<"<br/>";
}
if(given % 3 == 0) {
cout<<"SET LONG MESSAGE";
session["msg"]="Looooooooooooooooooooooooooooooong msg";
}
else {
cout<<"UNSET LONG MESSAGE";
session.del("msg");
}
cout<<"<br/>"<<endl;
if(session.is_set("msg")) {
int val=given % 2;
session.expose("msg",val);
cout<<(val ? "exposed" : "hidden")<<endl;
}
//session.clear();
}
session.set<time_t>("time",time(NULL));
}

void my_hello_world::std()
{
view::hello v(this);

if(env->getRequestMethod()=="POST") {
v.form.load(*cgi);
if(v.form.validate()) {
session["name"]=v.form.username.get();
v.username=v.form.username.get();
v.realname=v.form.name.get();
v.ok=v.form.ok.get();
v.password=v.form.p1.get();
v.form.clear();
}
void hello_world()
{
response().out() <<
"<html><body>\n"
"<h1>Hello World!</h1>\n"
"<body></html>\n";
}
};

v.title="Cool";
if(session.is_set("name"))
v.title+=":"+session["name"];

v.msg=gettext("Hello World");

for(int i=0;i<15;i++)
v.numbers.push_back(i);
v.lst.push_back(view::data("Hello",10));
render("hello",v);
}

void my_hello_world::cache_test()
{
string tmp;
bool from_cache=true;
if(!cache.fetch_frame("test",tmp,true)) {
tmp="test value";
from_cache=false;
cache.store_frame("test",tmp,5);
}
if(from_cache)
cout <<"Fetched ["<<tmp<<"] from cache";
else
cout <<"Fetched ["<<tmp<<"] from start";
}

int main(int argc,char ** argv)
int main(int argc,char **argv)
{
try {
manager app(argc,argv);
app.set_worker(new application_factory<my_hello_world>());
app.execute();
cppcms::service service(argc,argv);
service.applications_pool().mount(".*",cppcms::applications_factory<hello>());
service.run();
}
catch(std::exception const &e) {
cerr<<e.what()<<endl;
std::cerr<<e.what()<<std::endl;
return 1;
}
return 0;
}

+ 55
- 0
http_context.cpp View File

@@ -0,0 +1,55 @@
#define CPPCMS_SOURCE

#include "cgi_api.h"
#include "service.h"
#include "http_context.h"
#include "http_request.h"
#include "http_response.h"

namespace cppcms {
namespace http {

struct context::data {
http::request request;
http::response response;
data(context &cntx) :
request(cntx.connection()),
response(cntx)
{
}
};

context::context(impl::cgi::connection *conn) :
conn_(conn)
{
d.reset(new data(*this));
}

context::~context()
{
}


impl::cgi::connection &context::connection()
{
return *conn_;
}

http::request &context::request()
{
return d->request;
}

http::response &context::response()
{
return d->response;
}

cppcms_config const &context::settings()
{
return conn_->service().settings();
}


} // http
} // cppcms

+ 3
- 1
http_context.h View File

@@ -16,11 +16,13 @@ namespace cppcms {

class CPPCMS_API context : private util::noncopyable {
struct data;
util::hold_ptr<data> d_;
util::hold_ptr<data> d;
impl::cgi::connection *conn_;
public:
context(impl::cgi::connection *conn);
~context();

impl::cgi::connection &connection();
http::request &request();
http::response &response();
cppcms_config const &settings();


+ 1
- 0
http_cookie.cpp View File

@@ -1,3 +1,4 @@
#define CPPCMS_SOURCE
#include "http_cookie.h"
#include "http_protocol.h"
#include "cppcms_error.h"


+ 1
- 0
http_request.cpp View File

@@ -1,3 +1,4 @@
#define CPPCMS_SOURCE
#include "cgi_api.h"
#include "http_request.h"
#include "http_cookie.h"


+ 27
- 15
http_response.cpp View File

@@ -1,19 +1,22 @@
#define CPPCMS_SOURCE
#include <iostream>
#include <sstream>
#include <iterator>
#include <map>

#include "cgi_api.h"
#include "http_response.h"
#include "http_context.h"
#include "http_request.h"
#include "http_cookie.h"
#include "global_config.h"
#include "cppcms_error.h"
#include "util.h"
#include "service.h"
#include "config.h"
#include "util.h"

#include <iostream>
#include <sstream>
#include <iterator>
#include <map>

#include <boost/lexical_cast.hpp>
#include <boost/iostreams/stream.hpp>
#include <boost/iostreams/filtering_stream.hpp>
#include <boost/iostreams/filter/gzip.hpp>
#include <boost/iostreams/tee.hpp>
@@ -43,13 +46,13 @@ namespace {


namespace {
struct output_device : public boost::iostreams::sink {
class output_device : public boost::iostreams::sink {
impl::cgi::connection *conn_;
public:
output_device(impl::cgi::connection *conn) : conn_(conn) {}
std::streamsize write(char const *data,std::streamsize n)
{
size_t all=0;
std::streamsize all=0;
while(all < n)
all += conn_->write_some(data,n);
return all;
@@ -77,7 +80,7 @@ struct response::data {


response::response(context &context) :
d(new data(context.connection())),
d(new data(&context.connection())),
context_(context),
stream_(0),
io_mode_(normal),
@@ -91,6 +94,10 @@ response::response(context &context) :
}
}

response::~response()
{
}

void response::set_content_header(std::string const &content_type)
{
std::string charset=context_.settings().str("l10n.charset","");
@@ -190,7 +197,7 @@ void response::write_http_headers(std::ostream &stream)
out<<d->cookies[i]<<"\r\n";
}
out<<"\r\n";
out<<flush;
out<<std::flush;
}


@@ -207,11 +214,16 @@ std::ostream &response::out()
if(ostream_requested_)
return *stream_;

std::ostream &real_sink = io_mode_ == asynchronous ? d->buffered : d->output ;
std::ostream *real_sink = 0;

if(io_mode_ == asynchronous)
real_sink = &d->buffered;
else
real_sink = &d->output;

ostream_requested_=1;
write_http_headers(real_sink);
write_http_headers(*real_sink);
if(need_gzip()) {
gzip_params params;
@@ -234,9 +246,9 @@ std::ostream &response::out()
}
if(stream_)
d->filter.push(real_sink);
d->filter.push(*real_sink);
else
stream_=&real_sink;
stream_=real_sink;

return *stream_;
}
@@ -248,7 +260,7 @@ std::string response::get_async_chunk()
return result;
}

bool result::some_output_was_written()
bool response::some_output_was_written()
{
return ostream_requested_;
}


+ 0
- 2
http_response.h View File

@@ -62,8 +62,6 @@ namespace http {
// synchronous io
normal, // write request, use buffering, possible compression,
nogzip, // as normal but disable gzip
direct, // use direct connection for transferring huge
// amount of data, for example big csv, file download
asynchronous,
// the data is buffered and never transferred
// untill it is requested explicitly


+ 3
- 3
light.conf View File

@@ -63,8 +63,8 @@ server.bind = "127.0.0.1"

fastcgi.server = ( "/hello" => ( "localhost" => (
"check-local" => "disable",
# "host" => "127.0.0.1",
# "port" => 8000
"socket" => "/tmp/hello-fastcgi.socket"
"host" => "127.0.0.1",
"port" => 8000
# "socket" => "/tmp/hello-fastcgi.socket"
)))


+ 1
- 1
scgi_api.h View File

@@ -130,7 +130,7 @@ namespace cgi {

typedef scgi<boost::asio::ip::tcp> tcp_socket_scgi;
typedef tcp_socket_acceptor<tcp_socket_scgi> tcp_socket_scgi_acceptor;
#if !defined(_WIN32) && !defined(__CYGWIN__)
#if !defined(CPPCMS_WIN32)
typedef scgi<boost::asio::local::stream_protocol> unix_socket_scgi;
typedef unix_socket_acceptor<unix_socket_scgi> unix_socket_scgi_acceptor;
#endif


+ 14
- 16
service.cpp View File

@@ -11,7 +11,7 @@

#include "asio_config.h"

#if !defined(_WIN32) && !defined(__CYGWIN__)
#ifdef CPPCMS_POSIX
#include <sys/wait.h>
#endif

@@ -37,7 +37,7 @@ int service::threads_no()
}

namespace {
#if defined(__CYGWIN__) || defined(_WIN32)
#if defined(CPPCMS_WIN32)
void make_socket_pair(boost::asio::ip::tcp::socket &s1,boost::asio::ip::tcp::socket &s2)
{
boost::asio::ip::tcp::acceptor acceptor(s1.get_io_service(),
@@ -81,7 +81,7 @@ namespace {
#endif
} // anon

#ifdef _WIN32
#ifdef CPPCMS_WIN_NATIVE
void service::setup_exit_handling()
{
throw cppcms_error("TODO Setup exit handling");
@@ -90,18 +90,9 @@ void service::setup_exit_handling()
#else



void service::setup_exit_handling()
{

sigset_t set;
sigemptyset(&set);
sigaddset(&set,SIGINT);
sigaddset(&set,SIGTERM);
sigaddset(&set,SIGUSR1);

pthread_sigmask(SIG_BLOCK,&set,0);

make_socket_pair(impl_->sig_,impl_->breaker_);

static char c;
@@ -112,8 +103,10 @@ void service::setup_exit_handling()
notification_socket=impl_->sig_.native();

struct sigaction sa;

memset(&sa,0,sizeof(sa));
sa.sa_handler=handler;
sigaction(SIGINT,&sa,0);
sigaction(SIGTERM,&sa,0);
sigaction(SIGUSR1,&sa,0);
@@ -131,6 +124,7 @@ void service::run()
impl_->acceptor_->async_accept();

setup_exit_handling();

impl_->get_io_service().run();
}

@@ -139,14 +133,14 @@ int service::procs_no()
int procs=settings().integer("service.procs",0);
if(procs < 0)
procs = 0;
#if defined(_WIN32) || defined(__CYGWIN)
#ifdef CPPCMS_WIN32
if(procs > 0)
throw cppcms_error("Prefork is not supported under Windows");
#endif
return procs;
}

#if defined(_WIN32) || defined(__CYGWIN__)
#ifdef CPPCMS_WIN32
bool service::prefork()
{
procs_no();
@@ -228,9 +222,9 @@ void service::start_acceptor()
throw cppcms_error("Unknown service.api: " + api);
}
else {
#ifdef _WIN32
#ifdef CPPCMS_WIN_NATIVE
throw cppcms_error("Unix domain sockets are not supported under Windows... (isn't it obvious?)");
#elif defined(__CYGWIN__)
#elif defined CPPCMS_CYGWIN
throw cppcms_error("CppCMS uses native Win32 sockets under cygwin, so Unix sockets are not supported");
#else
if(api=="scgi")
@@ -267,10 +261,14 @@ cppcms::impl::service &service::impl()

void service::stop()
{
std::cout<<"Shutting down"<<std::endl;
if(impl_->acceptor_.get())
impl_->acceptor_->stop();
std::cout<<"Acceptor down"<<std::endl;
thread_pool().stop();
std::cout<<"Thread pool"<<std::endl;
impl_->get_io_service().stop();
std::cout<<"Io Service down"<<std::endl;
}

namespace impl {


+ 1
- 1
service_impl.h View File

@@ -34,7 +34,7 @@ namespace impl {
std::auto_ptr<thread_pool> thread_pool_;

boost::asio::io_service io_service_;
#if defined(__CYGWIN__) || defined(_WIN32)
#ifdef CPPCMS_WIN32
boost::asio::ip::tcp::socket sig_,breaker_;
#else
boost::asio::local::stream_protocol::socket sig_,breaker_;


+ 2
- 2
thread_pool.cpp View File

@@ -19,7 +19,7 @@ namespace impl {
thread_pool(int threads)
{
workers_.resize(threads);
#ifndef _WIN32
#if !defined(CPPCMS_WIN_NATIVE)
sigset_t set,old;
sigfillset(&set);
pthread_sigmask(SIG_BLOCK,&set,&old);
@@ -28,7 +28,7 @@ namespace impl {
workers_[i].reset(new boost::thread(boost::bind(&thread_pool::worker,this)));
}
#ifndef _WIN32
#if !defined(CPPCMS_WIN_NATIVE)
pthread_sigmask(SIG_SETMASK,&old,0);
#endif


+ 2
- 2
url_dispatcher.cpp View File

@@ -35,8 +35,8 @@ namespace cppcms {
struct mounted : public option {
mounted(std::string expr,int select,application *app) :
option(expr),
select_(select),
app_(app)
app_(app),
select_(select)
{
}



Loading…
Cancel
Save