From: <den...@us...> - 2009-12-26 01:40:52
|
Revision: 21 http://dsim.svn.sourceforge.net/dsim/?rev=21&view=rev Author: denis_arnaud Date: 2009-12-26 01:40:41 +0000 (Sat, 26 Dec 2009) Log Message: ----------- [Test] Created a dedicated test suite for Boost tests. Modified Paths: -------------- trunk/dsim/Makefile.am trunk/dsim/configure.ac trunk/dsim/test/Makefile.am Added Paths: ----------- trunk/dsim/test/boost/ trunk/dsim/test/boost/Makefile.am trunk/dsim/test/boost/accumulators/ trunk/dsim/test/boost/accumulators/Makefile.am trunk/dsim/test/boost/accumulators/accu.cpp trunk/dsim/test/boost/asio/ trunk/dsim/test/boost/asio/Makefile.am trunk/dsim/test/boost/asio/daytime1.cpp trunk/dsim/test/boost/asio/daytime2.cpp trunk/dsim/test/boost/asio/daytime3.cpp trunk/dsim/test/boost/asio/daytime4.cpp trunk/dsim/test/boost/asio/daytime5.cpp trunk/dsim/test/boost/asio/daytime6.cpp trunk/dsim/test/boost/asio/daytime7.cpp trunk/dsim/test/boost/asio/httpd/ trunk/dsim/test/boost/asio/httpd/Makefile.am trunk/dsim/test/boost/asio/httpd/connection.cpp trunk/dsim/test/boost/asio/httpd/connection.hpp trunk/dsim/test/boost/asio/httpd/header.hpp trunk/dsim/test/boost/asio/httpd/mime_types.cpp trunk/dsim/test/boost/asio/httpd/mime_types.hpp trunk/dsim/test/boost/asio/httpd/posix_main.cpp trunk/dsim/test/boost/asio/httpd/reply.cpp trunk/dsim/test/boost/asio/httpd/reply.hpp trunk/dsim/test/boost/asio/httpd/request.hpp trunk/dsim/test/boost/asio/httpd/request_handler.cpp trunk/dsim/test/boost/asio/httpd/request_handler.hpp trunk/dsim/test/boost/asio/httpd/request_parser.cpp trunk/dsim/test/boost/asio/httpd/request_parser.hpp trunk/dsim/test/boost/asio/httpd/server.cpp trunk/dsim/test/boost/asio/httpd/server.hpp trunk/dsim/test/boost/asio/httpd/win_main.cpp trunk/dsim/test/boost/asio/logd/ trunk/dsim/test/boost/asio/logd/Makefile.am trunk/dsim/test/boost/asio/logd/log/ trunk/dsim/test/boost/asio/logd/logd.cpp trunk/dsim/test/boost/asio/logger/ trunk/dsim/test/boost/asio/logger/Makefile.am trunk/dsim/test/boost/asio/logger/basic_logger.hpp trunk/dsim/test/boost/asio/logger/daytime_client.cpp trunk/dsim/test/boost/asio/logger/logger.hpp trunk/dsim/test/boost/asio/logger/logger_service.cpp trunk/dsim/test/boost/asio/logger/logger_service.hpp trunk/dsim/test/boost/asio/logger/stream_socket_service.hpp trunk/dsim/test/boost/asio/timer1.cpp trunk/dsim/test/boost/asio/timer2.cpp trunk/dsim/test/boost/asio/timer3.cpp trunk/dsim/test/boost/asio/timer4.cpp trunk/dsim/test/boost/asio/timer5.cpp trunk/dsim/test/boost/mpi/ trunk/dsim/test/boost/mpi/Makefile.am trunk/dsim/test/boost/mpi/mpi.cpp trunk/dsim/test/boost/mpi/pympi.py trunk/dsim/test/boost/mpl/ trunk/dsim/test/boost/mpl/Makefile.am trunk/dsim/test/boost/mpl/mpl.cpp trunk/dsim/test/boost/mpl/test_mpl.sh trunk/dsim/test/boost/serialization/ trunk/dsim/test/boost/serialization/Makefile.am trunk/dsim/test/boost/serialization/serial1.cpp trunk/dsim/test/boost/signals/ trunk/dsim/test/boost/signals/Makefile.am trunk/dsim/test/boost/signals/multislots.cpp trunk/dsim/test/boost/spirit/ trunk/dsim/test/boost/spirit/Makefile.am trunk/dsim/test/boost/spirit/full_calculator.cpp trunk/dsim/test/boost/spirit/levenshtein.cpp trunk/dsim/test/boost/spirit/levenshtein_new.cpp trunk/dsim/test/boost/spirit/parameter_parser.cpp trunk/dsim/test/boost/spirit/schedule_parser.cpp trunk/dsim/test/boost/spirit/search_string_parser.cpp trunk/dsim/test/boost/spirit/test_full_calculator.sh trunk/dsim/test/boost/spirit/test_parameter_parser.sh trunk/dsim/test/boost/spirit/test_schedule_parser.sh trunk/dsim/test/boost/spirit/world_schedule.csv Modified: trunk/dsim/Makefile.am =================================================================== --- trunk/dsim/Makefile.am 2009-12-24 16:05:27 UTC (rev 20) +++ trunk/dsim/Makefile.am 2009-12-26 01:40:41 UTC (rev 21) @@ -25,7 +25,7 @@ EXTRA_DIST = # Build in these directories: -SUBDIRS = stdair trademgen airsched airinv simcrs rmol $(TEST_DIR) +SUBDIRS = stdair trademgen airsched airinv simcrs rmol dsim $(TEST_DIR) # Configuration helpers Modified: trunk/dsim/configure.ac =================================================================== --- trunk/dsim/configure.ac 2009-12-24 16:05:27 UTC (rev 20) +++ trunk/dsim/configure.ac 2009-12-26 01:40:41 UTC (rev 21) @@ -464,6 +464,17 @@ dsim/core/Makefile dsim/batches/Makefile test/Makefile + test/boost/Makefile + test/boost/accumulators/Makefile + test/boost/asio/Makefile + test/boost/asio/httpd/Makefile + test/boost/asio/logd/Makefile + test/boost/asio/logger/Makefile + test/boost/mpi/Makefile + test/boost/mpl/Makefile + test/boost/spirit/Makefile + test/boost/serialization/Makefile + test/boost/signals/Makefile ) AC_OUTPUT Modified: trunk/dsim/test/Makefile.am =================================================================== --- trunk/dsim/test/Makefile.am 2009-12-24 16:05:27 UTC (rev 20) +++ trunk/dsim/test/Makefile.am 2009-12-26 01:40:41 UTC (rev 21) @@ -4,7 +4,7 @@ MAINTAINERCLEANFILES = Makefile.in ## -SUBDIRS = +SUBDIRS = boost ## check_PROGRAMS = simulate Property changes on: trunk/dsim/test/boost ___________________________________________________________________ Added: svn:ignore + .deps .libs Makefile.in Makefile Added: trunk/dsim/test/boost/Makefile.am =================================================================== --- trunk/dsim/test/boost/Makefile.am (rev 0) +++ trunk/dsim/test/boost/Makefile.am 2009-12-26 01:40:41 UTC (rev 21) @@ -0,0 +1,9 @@ +## test/boost sub-directory +include $(top_srcdir)/Makefile.common + +## +SUBDIRS = accumulators asio mpi mpl serialization signals spirit + +MAINTAINERCLEANFILES = Makefile.in + +EXTRA_DIST = Property changes on: trunk/dsim/test/boost/accumulators ___________________________________________________________________ Added: svn:ignore + .deps .libs Makefile.in Makefile accu Added: trunk/dsim/test/boost/accumulators/Makefile.am =================================================================== --- trunk/dsim/test/boost/accumulators/Makefile.am (rev 0) +++ trunk/dsim/test/boost/accumulators/Makefile.am 2009-12-26 01:40:41 UTC (rev 21) @@ -0,0 +1,21 @@ +## test/architecture sub-directory +include $(top_srcdir)/Makefile.common + +MAINTAINERCLEANFILES = Makefile.in + +## +SUBDIRS = + +EXTRA_DIST = +## + +check_PROGRAMS = accu +#TESTS = $(check_PROGRAMS) +TESTS = +XFAIL_TESTS = #IndexBuildingTestSuite + +accu_SOURCES = accu.cpp +accu_CXXFLAGS= $(BOOST_CFLAGS) +accu_LDFLAGS = $(BOOST_LIBS) +accu_LDADD = + Added: trunk/dsim/test/boost/accumulators/accu.cpp =================================================================== --- trunk/dsim/test/boost/accumulators/accu.cpp (rev 0) +++ trunk/dsim/test/boost/accumulators/accu.cpp 2009-12-26 01:40:41 UTC (rev 21) @@ -0,0 +1,171 @@ +// STL +#include <iostream> +#include <algorithm> +// Boost +#include <boost/ref.hpp> +#include <boost/bind.hpp> +#include <boost/array.hpp> +#include <boost/foreach.hpp> +// Boost Accumulators +#include <boost/accumulators/accumulators.hpp> +#include <boost/accumulators/statistics.hpp> + +// using namespace boost; +namespace boostacc = boost::accumulators; + +// Helper that uses BOOST_FOREACH to display a range of doubles +template<typename Range> +void output_range(Range const &rng) { + bool first = true; + BOOST_FOREACH(double d, rng) { + if(!first) std::cout << ", "; + std::cout << d; + first = false; + } + std::cout << '\n'; +} + +/////////////////////////////////////////////////////////////////////////////// +// example1 +// +// Calculate some useful stats using accumulator_set<> and std::for_each() +// +void example1() { + boostacc::accumulator_set<double, + boostacc::stats<boostacc::tag::min, + boostacc::tag::mean(boostacc::immediate), + boostacc::tag::sum, + boostacc::tag::moment<2> > > acc; + + boost::array<double, 4> data = {0., 1., -1., 3.14159}; + + // std::for_each pushes each sample into the accumulator one at a + // time, and returns a copy of the accumulator. + acc = std::for_each(data.begin(), data.end(), acc); + + // The following would be equivalent, and could be more efficient + // because it doesn't pass and return the entire accumulator set + // by value. + //std::for_each(data.begin(), data.end(), bind<void>(ref(acc), _1)); + + std::cout << " min(acc) = " << (boostacc::min)(acc) << std::endl; + std::cout << " mean(acc) = " << boostacc::mean(acc) << std::endl; + + // since mean depends on count and sum, we can get their results, too. + std::cout << " count(acc) = " << boostacc::count(acc) << std::endl; + std::cout << " sum(acc) = " << boostacc::sum(acc) << std::endl; + std::cout << " moment<2>(acc) = " << boostacc::moment<2>(acc) << std::endl; +} + +/////////////////////////////////////////////////////////////////////////////// +// example2 +// +// Calculate some tail statistics. This demonstrates how to specify +// constructor and accumulator parameters. Note that the tail statistics +// return multiple values, which are returned in an iterator_range. +// +// It pushes data in and displays the intermediate results to demonstrate +// how the tail statistics are updated. +void example2() { + // An accumulator which tracks the right tail (largest N items) and + // some data that are covariate with them. N == 4. + boostacc::accumulator_set<double, + boostacc::stats< + boostacc::tag::tail_variate<double, + boostacc::tag::covariate1, boostacc::right> > > acc (boostacc::tag::tail<boostacc::right>::cache_size = 4); + + acc(2.1, boostacc::covariate1 = .21); + acc(1.1, boostacc::covariate1 = .11); + acc(2.1, boostacc::covariate1 = .21); + acc(1.1, boostacc::covariate1 = .11); + + std::cout << " tail = "; output_range(boostacc::tail(acc)); + std::cout << " tail_variate = "; output_range(boostacc::tail_variate(acc)); + std::cout << std::endl; + + acc(21.1, boostacc::covariate1 = 2.11); + acc(11.1, boostacc::covariate1 = 1.11); + acc(21.1, boostacc::covariate1 = 2.11); + acc(11.1, boostacc::covariate1 = 1.11); + + std::cout << " tail = "; output_range(boostacc::tail(acc)); + std::cout << " tail_variate = "; output_range(boostacc::tail_variate(acc)); + std::cout << std::endl; + + acc(42.1, boostacc::covariate1 = 4.21); + acc(41.1, boostacc::covariate1 = 4.11); + acc(42.1, boostacc::covariate1 = 4.21); + acc(41.1, boostacc::covariate1 = 4.11); + + std::cout << " tail = "; output_range(boostacc::tail(acc)); + std::cout << " tail_variate = "; output_range(boostacc::tail_variate(acc)); + std::cout << std::endl; + + acc(32.1, boostacc::covariate1 = 3.21); + acc(31.1, boostacc::covariate1 = 3.11); + acc(32.1, boostacc::covariate1 = 3.21); + acc(31.1, boostacc::covariate1 = 3.11); + + std::cout << " tail = "; output_range(boostacc::tail(acc)); + std::cout << " tail_variate = "; output_range(boostacc::tail_variate(acc)); +} + +/////////////////////////////////////////////////////////////////////////////// +// example3 +// +// Demonstrate how to calculate weighted statistics. This example demonstrates +// both a simple weighted statistical calculation, and a more complicated +// calculation where the weight statistics are calculated and stored in an +// external weight accumulataor. +void example3() { + // weight == double + double w = 1.; + + // Simple weighted calculation + { + // stats that depend on the weight are made external + boostacc::accumulator_set<double, + boostacc::stats<boostacc::tag::mean>, double> acc; + + acc(0., boostacc::weight = w); + acc(1., boostacc::weight = w); + acc(-1., boostacc::weight = w); + acc(3.14159, boostacc::weight = w); + + std::cout << " mean(acc) = " << boostacc::mean(acc) << std::endl; + } + + // Weighted calculation with an external weight accumulator + { + // stats that depend on the weight are made external + boostacc::accumulator_set<double, boostacc::stats<boostacc::tag::mean>, + boostacc::external<double> > acc; + + // Here's an external weight accumulator + boostacc::accumulator_set<void, boostacc::stats<boostacc::tag::sum_of_weights>, double> weight_acc; + + weight_acc(boostacc::weight = w); acc(0., boostacc::weight = w); + weight_acc(boostacc::weight = w); acc(1., boostacc::weight = w); + weight_acc(boostacc::weight = w); acc(-1., boostacc::weight = w); + weight_acc(boostacc::weight = w); acc(3.14159, boostacc::weight = w); + + std::cout << " mean(acc) = " + << boostacc::mean(acc, boostacc::weights = weight_acc) + << std::endl; + } +} + +/////////////////////////////////////////////////////////////////////////////// +// main +int main (int argc, char* argv[]) { + std::cout << "Example 1:" << std::endl; + example1(); + + std::cout << std::endl << "Example 2:" << std::endl; + example2(); + + std::cout << std::endl << "Example 3:" << std::endl; + example3(); + + return 0; +} Property changes on: trunk/dsim/test/boost/asio ___________________________________________________________________ Added: svn:ignore + .deps .libs Makefile.in Makefile daytime1 daytime2 daytime3 daytime4 daytime5 daytime6 daytime7 timer1 timer2 timer3 timer4 timer5 Added: trunk/dsim/test/boost/asio/Makefile.am =================================================================== --- trunk/dsim/test/boost/asio/Makefile.am (rev 0) +++ trunk/dsim/test/boost/asio/Makefile.am 2009-12-26 01:40:41 UTC (rev 21) @@ -0,0 +1,72 @@ +## test/asio sub-directory +include $(top_srcdir)/Makefile.common + +## +SUBDIRS = logger logd httpd + +MAINTAINERCLEANFILES = Makefile.in + +check_PROGRAMS = timer1 timer2 timer3 timer4 timer5 \ + daytime1 daytime2 daytime3 daytime4 daytime5 daytime6 daytime7 + +timer1_SOURCES = timer1.cpp +timer1_CXXFLAGS = $(BOOST_CFLAGS) $(BOOST_CFLAGS) +timer1_LDFLAGS = $(BOOST_LIBS) $(BOOST_DATE_TIME_LIB) $(BOOST_ASIO_LIB) +timer1_LDADD = + +timer2_SOURCES = timer2.cpp +timer2_CXXFLAGS = $(BOOST_CFLAGS) $(BOOST_CFLAGS) +timer2_LDFLAGS = $(BOOST_LIBS) $(BOOST_DATE_TIME_LIB) $(BOOST_ASIO_LIB) +timer2_LDADD = + +timer3_SOURCES = timer3.cpp +timer3_CXXFLAGS = $(BOOST_CFLAGS) $(BOOST_CFLAGS) +timer3_LDFLAGS = $(BOOST_LIBS) $(BOOST_DATE_TIME_LIB) $(BOOST_ASIO_LIB) +timer3_LDADD = + +timer4_SOURCES = timer4.cpp +timer4_CXXFLAGS = $(BOOST_CFLAGS) $(BOOST_CFLAGS) +timer4_LDFLAGS = $(BOOST_LIBS) $(BOOST_DATE_TIME_LIB) $(BOOST_ASIO_LIB) +timer4_LDADD = + +timer5_SOURCES = timer5.cpp +timer5_CXXFLAGS = $(BOOST_CFLAGS) $(BOOST_CFLAGS) +timer5_LDFLAGS = $(BOOST_LIBS) $(BOOST_DATE_TIME_LIB) $(BOOST_ASIO_LIB) +timer5_LDADD = + +daytime1_SOURCES = daytime1.cpp +daytime1_CXXFLAGS = $(BOOST_CFLAGS) $(BOOST_CFLAGS) +daytime1_LDFLAGS = $(BOOST_LIBS) $(BOOST_DATE_TIME_LIB) $(BOOST_ASIO_LIB) +daytime1_LDADD = + +daytime2_SOURCES = daytime2.cpp +daytime2_CXXFLAGS = $(BOOST_CFLAGS) $(BOOST_CFLAGS) +daytime2_LDFLAGS = $(BOOST_LIBS) $(BOOST_DATE_TIME_LIB) $(BOOST_ASIO_LIB) +daytime2_LDADD = + +daytime3_SOURCES = daytime3.cpp +daytime3_CXXFLAGS = $(BOOST_CFLAGS) $(BOOST_CFLAGS) +daytime3_LDFLAGS = $(BOOST_LIBS) $(BOOST_DATE_TIME_LIB) $(BOOST_ASIO_LIB) +daytime3_LDADD = + +daytime4_SOURCES = daytime4.cpp +daytime4_CXXFLAGS = $(BOOST_CFLAGS) $(BOOST_CFLAGS) +daytime4_LDFLAGS = $(BOOST_LIBS) $(BOOST_DATE_TIME_LIB) $(BOOST_ASIO_LIB) +daytime4_LDADD = + +daytime5_SOURCES = daytime5.cpp +daytime5_CXXFLAGS = $(BOOST_CFLAGS) $(BOOST_CFLAGS) +daytime5_LDFLAGS = $(BOOST_LIBS) $(BOOST_DATE_TIME_LIB) $(BOOST_ASIO_LIB) +daytime5_LDADD = + +daytime6_SOURCES = daytime6.cpp +daytime6_CXXFLAGS = $(BOOST_CFLAGS) $(BOOST_CFLAGS) +daytime6_LDFLAGS = $(BOOST_LIBS) $(BOOST_DATE_TIME_LIB) $(BOOST_ASIO_LIB) +daytime6_LDADD = + +daytime7_SOURCES = daytime7.cpp +daytime7_CXXFLAGS = $(BOOST_CFLAGS) $(BOOST_CFLAGS) +daytime7_LDFLAGS = $(BOOST_LIBS) $(BOOST_DATE_TIME_LIB) $(BOOST_ASIO_LIB) +daytime7_LDADD = + +EXTRA_DIST = Added: trunk/dsim/test/boost/asio/daytime1.cpp =================================================================== --- trunk/dsim/test/boost/asio/daytime1.cpp (rev 0) +++ trunk/dsim/test/boost/asio/daytime1.cpp 2009-12-26 01:40:41 UTC (rev 21) @@ -0,0 +1,82 @@ +// Boost.ASIO Tutorial - Daytime1: +// http://www.boost.org/doc/libs/1_40_0/doc/html/boost_asio/tutorial/tutdaytime1.html +// STL +#include <iostream> +#include <string> +// Boost.ASIO +#include <boost/asio.hpp> +#include <boost/array.hpp> + +// /////////// M A I N //////////////// +int main (int argc, char* argv[]) { + + // Host name + std::string lHostname = "localhost"; + + // Service name (as specified within /etc/services) + // The "aria" service corresponds to the port 2624 + const std::string lServiceName = "aria"; + + try { + + if (argc >= 2) { + lHostname = argv[1]; + } + + boost::asio::io_service lIOService; + + boost::asio::ip::tcp::resolver lResolver (lIOService); + + boost::asio::ip::tcp::resolver::query lQuery (lHostname, lServiceName); + + boost::asio::ip::tcp::resolver::iterator itEndPoint = + lResolver.resolve (lQuery); + boost::asio::ip::tcp::resolver::iterator lEnd; + + boost::asio::ip::tcp::socket lSocket (lIOService); + boost::system::error_code lError = boost::asio::error::host_not_found; + + while (lError && itEndPoint != lEnd) { + const boost::asio::ip::tcp::endpoint lEndPoint = *itEndPoint; + + // DEBUG + std::cout << "Testing end point: " << std::endl; + + lSocket.close(); + lSocket.connect (lEndPoint, lError); + ++itEndPoint; + } + + if (lError) { + throw boost::system::system_error (lError); + } + assert (!lError); + + // DEBUG + const boost::asio::ip::tcp::endpoint lValidEndPoint; + std::cout << "Valid end point: " << lValidEndPoint << std::endl; + + for (;;) { + boost::array<char, 128> lBuffer; + boost::system::error_code lError; + + size_t lLength = lSocket.read_some (boost::asio::buffer (lBuffer), lError); + + if (lError == boost::asio::error::eof) { + // Connection closed cleanly by peer. + break; + + } else if (lError) { + // Some other error. + throw boost::system::system_error (lError); + } + + std::cout.write (lBuffer.data(), lLength); + } + + } catch (std::exception& lException) { + std::cerr << lException.what() << std::endl; + } + + return 0; +} Added: trunk/dsim/test/boost/asio/daytime2.cpp =================================================================== --- trunk/dsim/test/boost/asio/daytime2.cpp (rev 0) +++ trunk/dsim/test/boost/asio/daytime2.cpp 2009-12-26 01:40:41 UTC (rev 21) @@ -0,0 +1,46 @@ +// Boost.ASIO Tutorial - Daytime2: +// http://www.boost.org/doc/libs/1_40_0/doc/html/boost_asio/tutorial/tutdaytime2.html +// STL +#include <iostream> +#include <string> +#include <ctime> +// Boost.ASIO +#include <iostream> +#include <boost/asio.hpp> +#include <boost/date_time/posix_time/posix_time.hpp> + +// ////////////////////////////////////////////////////////// +std::string make_daytime_string() { + const std::time_t now = std::time(0); + return std::ctime (&now); +} + +// //////////////////// M A I N ///////////////////////////// +int main (int argc, char* argv[]) { + + try { + + boost::asio::io_service lIOService; + + // Create a listener for IP/TCP v4, listening on port 2624 (corresponding + // to the "aria" service, as specified within the /etc/services file) + boost::asio::ip::tcp::acceptor lAcceptor (lIOService, + boost::asio::ip::tcp::endpoint (boost::asio::ip::tcp::v4(), 2624)); + + for (;;) { + boost::asio::ip::tcp::socket lSocket (lIOService); + lAcceptor.accept (lSocket); + const std::string lMessage = make_daytime_string(); + + boost::system::error_code lIgnoredError; + boost::asio::write (lSocket, boost::asio::buffer (lMessage), + boost::asio::transfer_all(), lIgnoredError); + } + + } catch (std::exception& lException) { + std::cerr << lException.what() << std::endl; + } + + return 0; +} + Added: trunk/dsim/test/boost/asio/daytime3.cpp =================================================================== --- trunk/dsim/test/boost/asio/daytime3.cpp (rev 0) +++ trunk/dsim/test/boost/asio/daytime3.cpp 2009-12-26 01:40:41 UTC (rev 21) @@ -0,0 +1,145 @@ +// Boost.ASIO Tutorial - Daytime3: +// http://www.boost.org/doc/libs/1_40_0/doc/html/boost_asio/tutorial/tutdaytime3.html +// STL +#include <cassert> +#include <ctime> +#include <iostream> +#include <string> +// Boost.ASIO +#include <iostream> +#include <boost/asio.hpp> +#include <boost/bind.hpp> +#include <boost/shared_ptr.hpp> +#include <boost/enable_shared_from_this.hpp> +#include <boost/date_time/posix_time/posix_time.hpp> + +// ////////////////////////////////////////////////////////// +std::string make_daytime_string() { + const std::time_t now = std::time(0); + return std::ctime (&now); +} + +// ////////////////////////////////////////////////////////// +/** Class handling TCP connections for a given server. */ +class TCPConnection : + public boost::enable_shared_from_this<TCPConnection> { +public: + /** Pointer on a TCP connection. */ + typedef boost::shared_ptr<TCPConnection> Pointer_T; + + /** Create a TCP connection, from a given Boost.ASIO service. */ + static Pointer_T create (boost::asio::io_service& ioIOService) { + TCPConnection* oConnectionPtr = new TCPConnection (ioIOService); + assert (oConnectionPtr != NULL); + return Pointer_T (oConnectionPtr); + } + + /** Get the underlying TCP socket. */ + boost::asio::ip::tcp::socket& socket() { + return _socket; + } + + /** Process the incoming client request, by giving it back the time of day. */ + void start() { + + _message = make_daytime_string(); + + boost::system::error_code lIgnoredError; + boost::asio::async_write (_socket, boost::asio::buffer (_message), + boost::bind (&TCPConnection::handleWrite, + shared_from_this(), + boost::asio::placeholders::error, + boost::asio::placeholders::bytes_transferred)); + } + + +private: + // //////////// Constructors & Destructors ///////////// + /** Constructor. */ + TCPConnection (boost::asio::io_service& ioIOService) + : _socket (ioIOService) { + } + + void handleWrite (const boost::system::error_code& iErrorCode, + const size_t iTransferredBytes) { + } + + +private: + // ///////////////// Technical Methods /////////////////// + + +private: + // /////////// Attributes ///////////// + /** Time of day. */ + std::string _message; + + /** TCP/IP socket. */ + boost::asio::ip::tcp::socket _socket; +}; + + +/** Class starting a TCP server, and handling incoming requests. */ +class TCPServer { +public: + // //////////// Constructors & Destructors ///////////// + /** Constructor. + <br>Create a listener for IP/TCP v4, listening on port 2624 (corresponding + to the "aria" service, as specified within the /etc/services file) */ + TCPServer (boost::asio::io_service& ioIOService) + : _acceptor (ioIOService, + boost::asio::ip::tcp::endpoint (boost::asio::ip::tcp::v4(), + 2624)) { + startAccept(); + } + + +private: + // ///////////////// Technical Methods /////////////////// + /** Accept (socket) connection from any client. */ + void startAccept() { + TCPConnection::Pointer_T lConnection = + TCPConnection::create (_acceptor.io_service()); + + boost::asio::ip::tcp::socket& lSocket = lConnection->socket(); + _acceptor.async_accept (lSocket, + boost::bind (&TCPServer::handleAccept, this, + lConnection, + boost::asio::placeholders::error)); + } + + /** Process the (socket) connection from any client. */ + void handleAccept (TCPConnection::Pointer_T ioConnection, + const boost::system::error_code& iError) { + + if (!iError) { + ioConnection->start(); + startAccept(); + } + } + + +private: + // /////////// Attributes ///////////// + /** Connection acceptor. */ + boost::asio::ip::tcp::acceptor _acceptor; +}; + + +// //////////////////// M A I N ///////////////////////////// +int main (int argc, char* argv[]) { + + try { + + boost::asio::io_service lIOService; + TCPServer lServer (lIOService); + + lIOService.run(); + + } catch (std::exception& lException) { + std::cerr << lException.what() << std::endl; + } + + return 0; +} + Added: trunk/dsim/test/boost/asio/daytime4.cpp =================================================================== --- trunk/dsim/test/boost/asio/daytime4.cpp (rev 0) +++ trunk/dsim/test/boost/asio/daytime4.cpp 2009-12-26 01:40:41 UTC (rev 21) @@ -0,0 +1,17 @@ +// Boost.ASIO Tutorial - Daytime4: +// http://www.boost.org/doc/libs/1_40_0/doc/html/boost_asio/tutorial/tutdaytime4.html +// STL +#include <iostream> +// Boost.ASIO +#include <boost/asio.hpp> +#include <boost/date_time/posix_time/posix_time.hpp> + +// /////////// M A I N //////////////// +int main (int argc, char* argv[]) { + + boost::asio::io_service lIOService; + + std::cout << "We have waited 1 second" << std::endl; + + return 0; +} Added: trunk/dsim/test/boost/asio/daytime5.cpp =================================================================== --- trunk/dsim/test/boost/asio/daytime5.cpp (rev 0) +++ trunk/dsim/test/boost/asio/daytime5.cpp 2009-12-26 01:40:41 UTC (rev 21) @@ -0,0 +1,17 @@ +// Boost.ASIO Tutorial - Daytime5: +// http://www.boost.org/doc/libs/1_40_0/doc/html/boost_asio/tutorial/tutdaytime5.html +// STL +#include <iostream> +// Boost.ASIO +#include <boost/asio.hpp> +#include <boost/date_time/posix_time/posix_time.hpp> + +// /////////// M A I N //////////////// +int main (int argc, char* argv[]) { + + boost::asio::io_service lIOService; + + std::cout << "We have waited 1 second" << std::endl; + + return 0; +} Added: trunk/dsim/test/boost/asio/daytime6.cpp =================================================================== --- trunk/dsim/test/boost/asio/daytime6.cpp (rev 0) +++ trunk/dsim/test/boost/asio/daytime6.cpp 2009-12-26 01:40:41 UTC (rev 21) @@ -0,0 +1,17 @@ +// Boost.ASIO Tutorial - Daytime6: +// http://www.boost.org/doc/libs/1_40_0/doc/html/boost_asio/tutorial/tutdaytime6.html +// STL +#include <iostream> +// Boost.ASIO +#include <boost/asio.hpp> +#include <boost/date_time/posix_time/posix_time.hpp> + +// /////////// M A I N //////////////// +int main (int argc, char* argv[]) { + + boost::asio::io_service lIOService; + + std::cout << "We have waited 1 second" << std::endl; + + return 0; +} Added: trunk/dsim/test/boost/asio/daytime7.cpp =================================================================== --- trunk/dsim/test/boost/asio/daytime7.cpp (rev 0) +++ trunk/dsim/test/boost/asio/daytime7.cpp 2009-12-26 01:40:41 UTC (rev 21) @@ -0,0 +1,17 @@ +// Boost.ASIO Tutorial - Daytime7: +// http://www.boost.org/doc/libs/1_40_0/doc/html/boost_asio/tutorial/tutdaytime7.html +// STL +#include <iostream> +// Boost.ASIO +#include <boost/asio.hpp> +#include <boost/date_time/posix_time/posix_time.hpp> + +// /////////// M A I N //////////////// +int main (int argc, char* argv[]) { + + boost::asio::io_service lIOService; + + std::cout << "We have waited 1 second" << std::endl; + + return 0; +} Property changes on: trunk/dsim/test/boost/asio/httpd ___________________________________________________________________ Added: svn:ignore + .deps .libs Makefile.in Makefile httpd_server Added: trunk/dsim/test/boost/asio/httpd/Makefile.am =================================================================== --- trunk/dsim/test/boost/asio/httpd/Makefile.am (rev 0) +++ trunk/dsim/test/boost/asio/httpd/Makefile.am 2009-12-26 01:40:41 UTC (rev 21) @@ -0,0 +1,17 @@ +## test/asio/httpd sub-directory +include $(top_srcdir)/Makefile.common + +MAINTAINERCLEANFILES = Makefile.in + +check_PROGRAMS = httpd_server + +httpd_server_SOURCES = \ + header.hpp connection.hpp mime_types.hpp reply.hpp request.hpp \ + request_handler.hpp request_parser.hpp server.hpp \ + mime_types.cpp connection.cpp posix_main.cpp reply.cpp request_handler.cpp \ + request_parser.cpp server.cpp win_main.cpp +httpd_server_CXXFLAGS = $(BOOST_CFLAGS) $(BOOST_CFLAGS) +httpd_server_LDFLAGS = $(BOOST_LIBS) $(BOOST_DATE_TIME_LIB) $(BOOST_ASIO_LIB) +httpd_server_LDADD = + +EXTRA_DIST = Added: trunk/dsim/test/boost/asio/httpd/connection.cpp =================================================================== --- trunk/dsim/test/boost/asio/httpd/connection.cpp (rev 0) +++ trunk/dsim/test/boost/asio/httpd/connection.cpp 2009-12-26 01:40:41 UTC (rev 21) @@ -0,0 +1,87 @@ +// +// connection.cpp +// ~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#include "connection.hpp" +#include <vector> +#include <boost/bind.hpp> +#include "request_handler.hpp" + +namespace http { + + namespace server3 { + + connection::connection(boost::asio::io_service& io_service, + request_handler& handler) + : strand_(io_service), + socket_(io_service), + request_handler_(handler) { + } + + boost::asio::ip::tcp::socket& connection::socket() { + return socket_; + } + + void connection::start() { + socket_.async_read_some(boost::asio::buffer(buffer_), + strand_.wrap( + boost::bind(&connection::handle_read, shared_from_this(), + boost::asio::placeholders::error, + boost::asio::placeholders::bytes_transferred))); + } + + void connection::handle_read(const boost::system::error_code& e, + std::size_t bytes_transferred) { + if (!e) { + boost::tribool result; + boost::tie(result, boost::tuples::ignore) = request_parser_.parse( + request_, buffer_.data(), buffer_.data() + bytes_transferred); + + if (result) { + request_handler_.handle_request(request_, reply_); + boost::asio::async_write(socket_, reply_.to_buffers(), + strand_.wrap( + boost::bind(&connection::handle_write, shared_from_this(), + boost::asio::placeholders::error))); + } else if (!result) { + reply_ = reply::stock_reply(reply::bad_request); + boost::asio::async_write(socket_, reply_.to_buffers(), + strand_.wrap( + boost::bind(&connection::handle_write, shared_from_this(), + boost::asio::placeholders::error))); + } else { + socket_.async_read_some(boost::asio::buffer(buffer_), + strand_.wrap( + boost::bind(&connection::handle_read, shared_from_this(), + boost::asio::placeholders::error, + boost::asio::placeholders::bytes_transferred))); + } + } + + // If an error occurs then no new asynchronous operations are started. This + // means that all shared_ptr references to the connection object will + // disappear and the object will be destroyed automatically after this + // handler returns. The connection class's destructor closes the socket. + } + + void connection::handle_write(const boost::system::error_code& e) { + if (!e) { + // Initiate graceful connection closure. + boost::system::error_code ignored_ec; + socket_.shutdown(boost::asio::ip::tcp::socket::shutdown_both, ignored_ec); + } + + // No new asynchronous operations are started. This means that all shared_ptr + // references to the connection object will disappear and the object will be + // destroyed automatically after this handler returns. The connection class's + // destructor closes the socket. + } + + } // namespace server3 +} // namespace http Added: trunk/dsim/test/boost/asio/httpd/connection.hpp =================================================================== --- trunk/dsim/test/boost/asio/httpd/connection.hpp (rev 0) +++ trunk/dsim/test/boost/asio/httpd/connection.hpp 2009-12-26 01:40:41 UTC (rev 21) @@ -0,0 +1,77 @@ +// +// connection.hpp +// ~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef HTTP_SERVER3_CONNECTION_HPP +#define HTTP_SERVER3_CONNECTION_HPP + +#include <boost/asio.hpp> +#include <boost/array.hpp> +#include <boost/noncopyable.hpp> +#include <boost/shared_ptr.hpp> +#include <boost/enable_shared_from_this.hpp> +#include "reply.hpp" +#include "request.hpp" +#include "request_handler.hpp" +#include "request_parser.hpp" + +namespace http { + + namespace server3 { + + /// Represents a single connection from a client. + class connection + : public boost::enable_shared_from_this<connection>, + private boost::noncopyable { + public: + /// Construct a connection with the given io_service. + explicit connection(boost::asio::io_service& io_service, + request_handler& handler); + + /// Get the socket associated with the connection. + boost::asio::ip::tcp::socket& socket(); + + /// Start the first asynchronous operation for the connection. + void start(); + + private: + /// Handle completion of a read operation. + void handle_read(const boost::system::error_code& e, + std::size_t bytes_transferred); + + /// Handle completion of a write operation. + void handle_write(const boost::system::error_code& e); + + /// Strand to ensure the connection's handlers are not called concurrently. + boost::asio::io_service::strand strand_; + + /// Socket for the connection. + boost::asio::ip::tcp::socket socket_; + + /// The handler used to process the incoming request. + request_handler& request_handler_; + + /// Buffer for incoming data. + boost::array<char, 8192> buffer_; + + /// The incoming request. + request request_; + + /// The parser for the incoming request. + request_parser request_parser_; + + /// The reply to be sent back to the client. + reply reply_; + }; + + typedef boost::shared_ptr<connection> connection_ptr; + + } // namespace server3 +} // namespace http +#endif // HTTP_SERVER3_CONNECTION_HPP Added: trunk/dsim/test/boost/asio/httpd/header.hpp =================================================================== --- trunk/dsim/test/boost/asio/httpd/header.hpp (rev 0) +++ trunk/dsim/test/boost/asio/httpd/header.hpp 2009-12-26 01:40:41 UTC (rev 21) @@ -0,0 +1,27 @@ +// +// header.hpp +// ~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef HTTP_SERVER3_HEADER_HPP +#define HTTP_SERVER3_HEADER_HPP + +#include <string> + +namespace http { + + namespace server3 { + + struct header { + std::string name; + std::string value; + }; + + } // namespace server3 +} // namespace http +#endif // HTTP_SERVER3_HEADER_HPP Added: trunk/dsim/test/boost/asio/httpd/mime_types.cpp =================================================================== --- trunk/dsim/test/boost/asio/httpd/mime_types.cpp (rev 0) +++ trunk/dsim/test/boost/asio/httpd/mime_types.cpp 2009-12-26 01:40:41 UTC (rev 21) @@ -0,0 +1,43 @@ +// +// mime_types.cpp +// ~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#include "mime_types.hpp" + +namespace http { + + namespace server3 { + + namespace mime_types { + + struct mapping { + const char* extension; + const char* mime_type; + } mappings[] = { + { "gif", "image/gif" }, + { "htm", "text/html" }, + { "html", "text/html" }, + { "jpg", "image/jpeg" }, + { "png", "image/png" }, + { 0, 0 } // Marks end of list. + }; + + std::string extension_to_type(const std::string& extension) { + for (mapping* m = mappings; m->extension; ++m) { + if (m->extension == extension) { + return m->mime_type; + } + } + + return "text/plain"; + } + + } // namespace mime_types + } // namespace server3 +} // namespace http Added: trunk/dsim/test/boost/asio/httpd/mime_types.hpp =================================================================== --- trunk/dsim/test/boost/asio/httpd/mime_types.hpp (rev 0) +++ trunk/dsim/test/boost/asio/httpd/mime_types.hpp 2009-12-26 01:40:41 UTC (rev 21) @@ -0,0 +1,29 @@ +// +// mime_types.hpp +// ~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef HTTP_SERVER3_MIME_TYPES_HPP +#define HTTP_SERVER3_MIME_TYPES_HPP + +#include <string> + +namespace http { + + namespace server3 { + + namespace mime_types { + + /// Convert a file extension into a MIME type. + std::string extension_to_type(const std::string& extension); + + } // namespace mime_types + } // namespace server3 +} // namespace http + +#endif // HTTP_SERVER3_MIME_TYPES_HPP Added: trunk/dsim/test/boost/asio/httpd/posix_main.cpp =================================================================== --- trunk/dsim/test/boost/asio/httpd/posix_main.cpp (rev 0) +++ trunk/dsim/test/boost/asio/httpd/posix_main.cpp 2009-12-26 01:40:41 UTC (rev 21) @@ -0,0 +1,73 @@ +// +// posix_main.cpp +// ~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#include <iostream> +#include <string> +#include <boost/asio.hpp> +#include <boost/thread.hpp> +#include <boost/bind.hpp> +#include <boost/lexical_cast.hpp> +#include "server.hpp" + +#if !defined(_WIN32) + +#include <pthread.h> +#include <signal.h> + +int main(int argc, char* argv[]) { + + try { + + // Check command line arguments. + if (argc != 5) { + std::cerr << "Usage: http_server <address> <port> <threads> <doc_root>\n"; + std::cerr << " For IPv4, try:\n"; + std::cerr << " receiver 0.0.0.0 80 1 .\n"; + std::cerr << " For IPv6, try:\n"; + std::cerr << " receiver 0::0 80 1 .\n"; + return 1; + } + + // Block all signals for background thread. + sigset_t new_mask; + sigfillset(&new_mask); + sigset_t old_mask; + pthread_sigmask(SIG_BLOCK, &new_mask, &old_mask); + + // Run server in background thread. + std::size_t num_threads = boost::lexical_cast<std::size_t>(argv[3]); + http::server3::server s(argv[1], argv[2], argv[4], num_threads); + boost::thread t(boost::bind(&http::server3::server::run, &s)); + + // Restore previous signals. + pthread_sigmask(SIG_SETMASK, &old_mask, 0); + + // Wait for signal indicating time to shut down. + sigset_t wait_mask; + sigemptyset(&wait_mask); + sigaddset(&wait_mask, SIGINT); + sigaddset(&wait_mask, SIGQUIT); + sigaddset(&wait_mask, SIGTERM); + pthread_sigmask(SIG_BLOCK, &wait_mask, 0); + int sig = 0; + sigwait(&wait_mask, &sig); + + // Stop the server. + s.stop(); + t.join(); + + } catch (std::exception& e) { + std::cerr << "exception: " << e.what() << "\n"; + } + + return 0; +} + +#endif // !defined(_WIN32) Added: trunk/dsim/test/boost/asio/httpd/reply.cpp =================================================================== --- trunk/dsim/test/boost/asio/httpd/reply.cpp (rev 0) +++ trunk/dsim/test/boost/asio/httpd/reply.cpp 2009-12-26 01:40:41 UTC (rev 21) @@ -0,0 +1,253 @@ +// +// reply.cpp +// ~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#include "reply.hpp" +#include <string> +#include <boost/lexical_cast.hpp> + +namespace http { + + namespace server3 { + + namespace status_strings { + + const std::string ok = + "HTTP/1.0 200 OK\r\n"; + const std::string created = + "HTTP/1.0 201 Created\r\n"; + const std::string accepted = + "HTTP/1.0 202 Accepted\r\n"; + const std::string no_content = + "HTTP/1.0 204 No Content\r\n"; + const std::string multiple_choices = + "HTTP/1.0 300 Multiple Choices\r\n"; + const std::string moved_permanently = + "HTTP/1.0 301 Moved Permanently\r\n"; + const std::string moved_temporarily = + "HTTP/1.0 302 Moved Temporarily\r\n"; + const std::string not_modified = + "HTTP/1.0 304 Not Modified\r\n"; + const std::string bad_request = + "HTTP/1.0 400 Bad Request\r\n"; + const std::string unauthorized = + "HTTP/1.0 401 Unauthorized\r\n"; + const std::string forbidden = + "HTTP/1.0 403 Forbidden\r\n"; + const std::string not_found = + "HTTP/1.0 404 Not Found\r\n"; + const std::string internal_server_error = + "HTTP/1.0 500 Internal Server Error\r\n"; + const std::string not_implemented = + "HTTP/1.0 501 Not Implemented\r\n"; + const std::string bad_gateway = + "HTTP/1.0 502 Bad Gateway\r\n"; + const std::string service_unavailable = + "HTTP/1.0 503 Service Unavailable\r\n"; + + boost::asio::const_buffer to_buffer(reply::status_type status) { + switch (status) { + case reply::ok: + return boost::asio::buffer(ok); + case reply::created: + return boost::asio::buffer(created); + case reply::accepted: + return boost::asio::buffer(accepted); + case reply::no_content: + return boost::asio::buffer(no_content); + case reply::multiple_choices: + return boost::asio::buffer(multiple_choices); + case reply::moved_permanently: + return boost::asio::buffer(moved_permanently); + case reply::moved_temporarily: + return boost::asio::buffer(moved_temporarily); + case reply::not_modified: + return boost::asio::buffer(not_modified); + case reply::bad_request: + return boost::asio::buffer(bad_request); + case reply::unauthorized: + return boost::asio::buffer(unauthorized); + case reply::forbidden: + return boost::asio::buffer(forbidden); + case reply::not_found: + return boost::asio::buffer(not_found); + case reply::internal_server_error: + return boost::asio::buffer(internal_server_error); + case reply::not_implemented: + return boost::asio::buffer(not_implemented); + case reply::bad_gateway: + return boost::asio::buffer(bad_gateway); + case reply::service_unavailable: + return boost::asio::buffer(service_unavailable); + default: + return boost::asio::buffer(internal_server_error); + } + } + + } // namespace status_strings + + namespace misc_strings { + + const char name_value_separator[] = { ':', ' ' }; + const char crlf[] = { '\r', '\n' }; + + } // namespace misc_strings + + std::vector<boost::asio::const_buffer> reply::to_buffers() { + + std::vector<boost::asio::const_buffer> buffers; + + buffers.push_back(status_strings::to_buffer(status)); + for (std::size_t i = 0; i < headers.size(); ++i) { + header& h = headers[i]; + buffers.push_back(boost::asio::buffer(h.name)); + buffers.push_back(boost::asio::buffer(misc_strings::name_value_separator)); + buffers.push_back(boost::asio::buffer(h.value)); + buffers.push_back(boost::asio::buffer(misc_strings::crlf)); + } + + buffers.push_back(boost::asio::buffer(misc_strings::crlf)); + buffers.push_back(boost::asio::buffer(content)); + return buffers; + } + + namespace stock_replies { + + const char ok[] = ""; + const char created[] = + "<html>" + "<head><title>Created</title></head>" + "<body><h1>201 Created</h1></body>" + "</html>"; + const char accepted[] = + "<html>" + "<head><title>Accepted</title></head>" + "<body><h1>202 Accepted</h1></body>" + "</html>"; + const char no_content[] = + "<html>" + "<head><title>No Content</title></head>" + "<body><h1>204 Content</h1></body>" + "</html>"; + const char multiple_choices[] = + "<html>" + "<head><title>Multiple Choices</title></head>" + "<body><h1>300 Multiple Choices</h1></body>" + "</html>"; + const char moved_permanently[] = + "<html>" + "<head><title>Moved Permanently</title></head>" + "<body><h1>301 Moved Permanently</h1></body>" + "</html>"; + const char moved_temporarily[] = + "<html>" + "<head><title>Moved Temporarily</title></head>" + "<body><h1>302 Moved Temporarily</h1></body>" + "</html>"; + const char not_modified[] = + "<html>" + "<head><title>Not Modified</title></head>" + "<body><h1>304 Not Modified</h1></body>" + "</html>"; + const char bad_request[] = + "<html>" + "<head><title>Bad Request</title></head>" + "<body><h1>400 Bad Request</h1></body>" + "</html>"; + const char unauthorized[] = + "<html>" + "<head><title>Unauthorized</title></head>" + "<body><h1>401 Unauthorized</h1></body>" + "</html>"; + const char forbidden[] = + "<html>" + "<head><title>Forbidden</title></head>" + "<body><h1>403 Forbidden</h1></body>" + "</html>"; + const char not_found[] = + "<html>" + "<head><title>Not Found</title></head>" + "<body><h1>404 Not Found</h1></body>" + "</html>"; + const char internal_server_error[] = + "<html>" + "<head><title>Internal Server Error</title></head>" + "<body><h1>500 Internal Server Error</h1></body>" + "</html>"; + const char not_implemented[] = + "<html>" + "<head><title>Not Implemented</title></head>" + "<body><h1>501 Not Implemented</h1></body>" + "</html>"; + const char bad_gateway[] = + "<html>" + "<head><title>Bad Gateway</title></head>" + "<body><h1>502 Bad Gateway</h1></body>" + "</html>"; + const char service_unavailable[] = + "<html>" + "<head><title>Service Unavailable</title></head>" + "<body><h1>503 Service Unavailable</h1></body>" + "</html>"; + + std::string to_string(reply::status_type status) { + switch (status) { + case reply::ok: + return ok; + case reply::created: + return created; + case reply::accepted: + return accepted; + case reply::no_content: + return no_content; + case reply::multiple_choices: + return multiple_choices; + case reply::moved_permanently: + return moved_permanently; + case reply::moved_temporarily: + return moved_temporarily; + case reply::not_modified: + return not_modified; + case reply::bad_request: + return bad_request; + case reply::unauthorized: + return unauthorized; + case reply::forbidden: + return forbidden; + case reply::not_found: + return not_found; + case reply::internal_server_error: + return internal_server_error; + case reply::not_implemented: + return not_implemented; + case reply::bad_gateway: + return bad_gateway; + case reply::service_unavailable: + return service_unavailable; + default: + return internal_server_error; + } + } + + } // namespace stock_replies + + reply reply::stock_reply(reply::status_type status) { + reply rep; + rep.status = status; + rep.content = stock_replies::to_string(status); + rep.headers.resize(2); + rep.headers[0].name = "Content-Length"; + rep.headers[0].value = boost::lexical_cast<std::string>(rep.content.size()); + rep.headers[1].name = "Content-Type"; + rep.headers[1].value = "text/html"; + return rep; + } + + } // namespace server3 +} // namespace http Added: trunk/dsim/test/boost/asio/httpd/reply.hpp =================================================================== --- trunk/dsim/test/boost/asio/httpd/reply.hpp (rev 0) +++ trunk/dsim/test/boost/asio/httpd/reply.hpp 2009-12-26 01:40:41 UTC (rev 21) @@ -0,0 +1,63 @@ +// +// reply.hpp +// ~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef HTTP_SERVER3_REPLY_HPP +#define HTTP_SERVER3_REPLY_HPP + +#include <string> +#include <vector> +#include <boost/asio.hpp> +#include "header.hpp" + +namespace http { + + namespace server3 { + + /// A reply to be sent to a client. + struct reply { + + /// The status of the reply. + enum status_type { + ok = 200, + created = 201, + accepted = 202, + no_content = 204, + multiple_choices = 300, + moved_permanently = 301, + moved_temporarily = 302, + not_modified = 304, + bad_request = 400, + unauthorized = 401, + forbidden = 403, + not_found = 404, + internal_server_error = 500, + not_implemented = 501, + bad_gateway = 502, + service_unavailable = 503 + } status; + + /// The headers to be included in the reply. + std::vector<header> headers; + + /// The content to be sent in the reply. + std::string content; + + /// Convert the reply into a vector of buffers. The buffers do not own the + /// underlying memory blocks, therefore the reply object must remain valid and + /// not be changed until the write operation has completed. + std::vector<boost::asio::const_buffer> to_buffers(); + + /// Get a stock reply. + static reply stock_reply(status_type status); + }; + + } // namespace server3 +} // namespace http +#endif // HTTP_SERVER3_REPLY_HPP Added: trunk/dsim/test/boost/asio/httpd/request.hpp =================================================================== --- trunk/dsim/test/boost/asio/httpd/request.hpp (rev 0) +++ trunk/dsim/test/boost/asio/httpd/request.hpp 2009-12-26 01:40:41 UTC (rev 21) @@ -0,0 +1,33 @@ +// +// request.hpp +// ~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef HTTP_SERVER3_REQUEST_HPP +#define HTTP_SERVER3_REQUEST_HPP + +#include <string> +#include <vector> +#include "header.hpp" + +namespace http { + + namespace server3 { + + /// A request received from a client. + struct request { + std::string method; + std::string uri; + int http_version_major; + int http_version_minor; + std::vector<header> headers; + }; + + } // namespace server3 +} // namespace http +#endif // HTTP_SERVER3_REQUEST_HPP Added: trunk/dsim/test/boost/asio/httpd/request_handler.cpp =================================================================== --- trunk/dsim/test/boost/asio/httpd/request_handler.cpp (rev 0) +++ trunk/dsim/test/boost/asio/httpd/request_handler.cpp 2009-12-26 01:40:41 UTC (rev 21) @@ -0,0 +1,115 @@ +// +// request_handler.cpp +// ~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#include "request_handler.hpp" +#include <fstream> +#include <sstream> +#include <string> +#include <boost/lexical_cast.hpp> +#include "mime_types.hpp" +#include "reply.hpp" +#include "request.hpp" + +namespace http { + + namespace server3 { + + request_handler::request_handler(const std::string& doc_root) + : doc_root_(doc_root) { + } + + void request_handler::handle_request(const request& req, reply& rep) { + // Decode url to path. + std::string request_path; + + if (!url_decode(req.uri, request_path)) { + rep = reply::stock_reply(reply::bad_request); + return; + } + + // Request path must be absolute and not contain "..". + if (request_path.empty() || request_path[0] != '/' + || request_path.find("..") != std::string::npos) { + rep = reply::stock_reply(reply::bad_request); + return; + } + + // If path ends in slash (i.e. is a directory) then add "index.html". + if (request_path[request_path.size() - 1] == '/') { + request_path += "index.html"; + } + + // Determine the file extension. + std::size_t last_slash_pos = request_path.find_last_of("/"); + std::size_t last_dot_pos = request_path.find_last_of("."); + std::string extension; + + if (last_dot_pos != std::string::npos && last_dot_pos > last_slash_pos) { + extension = request_path.substr(last_dot_pos + 1); + } + + // Open the file to send back. + std::string full_path = doc_root_ + request_path; + std::ifstream is (full_path.c_str(), std::ios::in | std::ios::binary); + + if (!is) { + rep = reply::stock_reply(reply::not_found); + return; + } + + // Fill out the reply to be sent to the client. + rep.status = reply::ok; + char buf[512]; + while (is.read(buf, sizeof(buf)).gcount() > 0) + rep.content.append(buf, is.gcount()); + rep.headers.resize(2); + rep.headers[0].name = "Content-Length"; + rep.headers[0].value = boost::lexical_cast<std::string>(rep.content.size()); + rep.headers[1].name = "Content-Type"; + rep.headers[1].value = mime_types::extension_to_type(extension); + } + + bool request_handler::url_decode(const std::string& in, std::string& out) { + out.clear(); + out.reserve(in.size()); + + for (std::size_t i = 0; i < in.size(); ++i) { + + if (in[i] == '%') { + + if (i + 3 <= in.size()) { + int value = 0; + std::istringstream is(in.substr(i + 1, 2)); + + if (is >> std::hex >> value) { + out += static_cast<char>(value); + i += 2; + + } else { + return false; + } + + } else { + return false; + } + + } else if (in[i] == '+') { + out += ' '; + + } else { + out += in[i]; + } + } + + return true; + } + + } // namespace server3 +} // namespace http Added: trunk/dsim/test/boost/asio/httpd/request_handler.hpp =================================================================== --- trunk/dsim/test/boost/asio/httpd/request_handler.hpp (rev 0) +++ trunk/dsim/test/boost/asio/httpd/request_handler.hpp 2009-12-26 01:40:41 UTC (rev 21) @@ -0,0 +1,45 @@ +// +// request_handler.hpp +// ~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef HTTP_SERVER3_REQUEST_HANDLER_HPP +#define HTTP_SERVER3_REQUEST_HANDLER_HPP + +#include <string> +#include <boost/noncopyable.hpp> + +namespace http { + + namespace server3 { + + struct reply; + struct request; + + /// The common handler for all incoming requests. + class request_handler + : private boost::noncopyable { + public: + /// Construct with a directory containing files to be served. + explicit request_handler(const std::string& doc_root); + + /// Handle a request and produce a reply. + void handle_request(const request& req, reply& rep); + + private: + /// The directory containing the files to be served. + std::string doc_root_; + + /// Perform URL-decoding on a string. Returns false if the encoding was + /// invalid. + static bool url_decode(const std::string& in, std::string& out); + }; + + } // namespace server3 +} // namespace http +#endif // HTTP_SERVER3_REQUEST_HANDLER_HPP Added: trunk/dsim/test/boost/asio/httpd/request_parser.cpp =================================================================== --- trunk/dsim/test/boost/asio/httpd/request_parser.cpp (rev 0) +++ trunk/dsim/test/boost/asio/httpd/request_parser.cpp 2009-12-26 01:40:41 UTC (rev 21) @@ -0,0 +1,291 @@ +// +// request_parser.cpp +// ~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#include "request_parser.hpp" +#include "request.hpp" + +namespace http { + + namespace server3 { + + request_parser::request_parser() + : state_(method_start) { + } + + void request_parser::reset() { + state_ = method_start; + } + + boost::tribool request_parser::consume(request& req, char input) { + + switch (state_) { + + case method_start: + if (!is_char(input) || is_ctl(input) || is_tspecial(input)) { + return false; + + } else { + state_ = method; + req.method.push_back(input); + return boost::indeterminate; + } + + case method: + if (input == ' ') { + state_ = uri; + return boost::indeterminate; + + } else if (!is_char(input) || is_ctl(input) || is_tspecial(input)) { + return false; + + } else { + ... [truncated message content] |