• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 // Copyright (c) 2011 Thomas Heller
3 //
4 // Distributed under the Boost Software License, Version 1.0. (See accompanying
5 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6 //
7 
8 #include <cstdlib>
9 #include <iostream>
10 
11 #define BOOST_PHOENIX_NO_PREDEFINED_TERMINALS
12 
13 #include <boost/phoenix.hpp>
14 #include <boost/asio.hpp>
15 
16 namespace phx = boost::phoenix;
17 
18 using boost::phoenix::ref;
19 
20 BOOST_PHOENIX_ADAPT_FUNCTION(void, read, boost::asio::async_read, 4)
21 BOOST_PHOENIX_ADAPT_FUNCTION(void, write, boost::asio::async_write, 3)
22 BOOST_PHOENIX_ADAPT_FUNCTION(boost::asio::mutable_buffers_1, buffer, boost::asio::buffer, 2)
23 
24 template <typename Acceptor, typename Socket, typename Handler>
accept_impl(Acceptor & acceptor,Socket & socket,Handler const & handler)25 void accept_impl(Acceptor & acceptor, Socket & socket, Handler const & handler)
26 {
27     acceptor.async_accept(socket, handler);
28 }
29 BOOST_PHOENIX_ADAPT_FUNCTION(void, accept, accept_impl, 3)
30 
31 typedef phx::expression::local_variable<struct action_key>::type action;
32 
33 #include <boost/function.hpp>
34 
main(int argc,char * argv[])35 int main(int argc, char* argv[])
36 {
37   try
38   {
39     if (argc != 2)
40     {
41       std::cerr << "Usage: async_tcp_echo_server <port>\n";
42       return 1;
43     }
44 
45     phx::lambda_type lambda;
46     phx::arg_names::_1_type _1;
47 
48     boost::asio::io_service io_service;
49     boost::asio::ip::tcp::acceptor acceptor(io_service, boost::asio::ip::tcp::endpoint(boost::asio::ip::tcp::v4(), std::atoi(argv[1])));
50     boost::asio::ip::tcp::socket socket(io_service);
51     std::size_t const max_length = 1024;
52     char buf[max_length];
53 
54     std::cout << "server starting...\n";
55 
56     boost::function<void(boost::system::error_code const &)> accept_handler;
57     phx::expression::argument<1>::type _error;
58     phx::expression::argument<2>::type _length;
59     action _action;
60     BOOST_AUTO(
61         create_handler
62       , (lambda(_action = lambda[_1])
63         [
64             if_(!_error)
65             [
66                 bind(_action, ref(socket), ref(buf), _error, _length)
67             ]
68             .else_
69             [
70                 bind(&boost::asio::ip::tcp::socket::close, ref(socket))
71               , accept(ref(acceptor), ref(socket), phx::ref(accept_handler))
72             ]
73         ])
74     );
75     boost::function<void(boost::system::error_code const &, std::size_t)> read_handler;
76     boost::function<void(boost::system::error_code const &, std::size_t)> write_handler;
77 
78     accept_handler =
79         if_(!_error)
80         [
81             read(ref(socket), buffer(ref(buf), max_length), boost::asio::transfer_at_least(1), phx::ref(read_handler))
82         ];
83 
84     {
85         phx::expression::argument<1>::type _socket;
86         phx::expression::argument<2>::type _buf;
87         phx::expression::argument<3>::type _error;
88         phx::expression::argument<4>::type _length;
89         read_handler = create_handler(
90             write(_socket, buffer(_buf, _length), phx::ref(write_handler))
91         );
92 
93         write_handler = create_handler(
94             read(_socket, buffer(_buf, max_length), boost::asio::transfer_at_least(1), phx::ref(read_handler))
95         );
96     }
97 
98     acceptor.async_accept(
99         socket
100       , accept_handler
101     );
102 
103     io_service.run();
104   }
105   catch (std::exception& e)
106   {
107     std::cerr << "Exception: " << e.what() << "\n";
108   }
109 
110   return 0;
111 }
112