1 //
2 // stream_server.cpp
3 // ~~~~~~~~~~~~~~~~~
4 //
5 // Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com)
6 //
7 // Distributed under the Boost Software License, Version 1.0. (See accompanying
8 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
9 //
10 
11 #include <cstdio>
12 #include <iostream>
13 #include <boost/array.hpp>
14 #include <boost/bind.hpp>
15 #include <boost/enable_shared_from_this.hpp>
16 #include <boost/shared_ptr.hpp>
17 #include "asio.hpp"
18 
19 #if defined(ASIO_HAS_LOCAL_SOCKETS)
20 
21 using asio::local::stream_protocol;
22 
23 class session
24   : public boost::enable_shared_from_this<session>
25 {
26 public:
session(asio::io_context & io_context)27   session(asio::io_context& io_context)
28     : socket_(io_context)
29   {
30   }
31 
socket()32   stream_protocol::socket& socket()
33   {
34     return socket_;
35   }
36 
start()37   void start()
38   {
39     socket_.async_read_some(asio::buffer(data_),
40         boost::bind(&session::handle_read,
41           shared_from_this(),
42           asio::placeholders::error,
43           asio::placeholders::bytes_transferred));
44   }
45 
handle_read(const asio::error_code & error,size_t bytes_transferred)46   void handle_read(const asio::error_code& error,
47       size_t bytes_transferred)
48   {
49     if (!error)
50     {
51       asio::async_write(socket_,
52           asio::buffer(data_, bytes_transferred),
53           boost::bind(&session::handle_write,
54             shared_from_this(),
55             asio::placeholders::error));
56     }
57   }
58 
handle_write(const asio::error_code & error)59   void handle_write(const asio::error_code& error)
60   {
61     if (!error)
62     {
63       socket_.async_read_some(asio::buffer(data_),
64           boost::bind(&session::handle_read,
65             shared_from_this(),
66             asio::placeholders::error,
67             asio::placeholders::bytes_transferred));
68     }
69   }
70 
71 private:
72   // The socket used to communicate with the client.
73   stream_protocol::socket socket_;
74 
75   // Buffer used to store data received from the client.
76   boost::array<char, 1024> data_;
77 };
78 
79 typedef boost::shared_ptr<session> session_ptr;
80 
81 class server
82 {
83 public:
server(asio::io_context & io_context,const std::string & file)84   server(asio::io_context& io_context, const std::string& file)
85     : io_context_(io_context),
86       acceptor_(io_context, stream_protocol::endpoint(file))
87   {
88     session_ptr new_session(new session(io_context_));
89     acceptor_.async_accept(new_session->socket(),
90         boost::bind(&server::handle_accept, this, new_session,
91           asio::placeholders::error));
92   }
93 
handle_accept(session_ptr new_session,const asio::error_code & error)94   void handle_accept(session_ptr new_session,
95       const asio::error_code& error)
96   {
97     if (!error)
98     {
99       new_session->start();
100     }
101 
102     new_session.reset(new session(io_context_));
103     acceptor_.async_accept(new_session->socket(),
104         boost::bind(&server::handle_accept, this, new_session,
105           asio::placeholders::error));
106   }
107 
108 private:
109   asio::io_context& io_context_;
110   stream_protocol::acceptor acceptor_;
111 };
112 
main(int argc,char * argv[])113 int main(int argc, char* argv[])
114 {
115   try
116   {
117     if (argc != 2)
118     {
119       std::cerr << "Usage: stream_server <file>\n";
120       std::cerr << "*** WARNING: existing file is removed ***\n";
121       return 1;
122     }
123 
124     asio::io_context io_context;
125 
126     std::remove(argv[1]);
127     server s(io_context, argv[1]);
128 
129     io_context.run();
130   }
131   catch (std::exception& e)
132   {
133     std::cerr << "Exception: " << e.what() << "\n";
134   }
135 
136   return 0;
137 }
138 
139 #else // defined(ASIO_HAS_LOCAL_SOCKETS)
140 # error Local sockets not available on this platform.
141 #endif // defined(ASIO_HAS_LOCAL_SOCKETS)
142