tizen 2.4 release
[external/nghttp2.git] / examples / asio-sv3.cc
1 /*
2  * nghttp2 - HTTP/2 C Library
3  *
4  * Copyright (c) 2014 Tatsuhiro Tsujikawa
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining
7  * a copy of this software and associated documentation files (the
8  * "Software"), to deal in the Software without restriction, including
9  * without limitation the rights to use, copy, modify, merge, publish,
10  * distribute, sublicense, and/or sell copies of the Software, and to
11  * permit persons to whom the Software is furnished to do so, subject to
12  * the following conditions:
13  *
14  * The above copyright notice and this permission notice shall be
15  * included in all copies or substantial portions of the Software.
16  *
17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
21  * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
22  * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
23  * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24  */
25 // We wrote this code based on the original code which has the
26 // following license:
27 //
28 // main.cpp
29 // ~~~~~~~~
30 //
31 // Copyright (c) 2003-2013 Christopher M. Kohlhoff (chris at kohlhoff dot com)
32 //
33 // Distributed under the Boost Software License, Version 1.0. (See accompanying
34 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
35 //
36 #include <unistd.h>
37 #include <iostream>
38 #include <string>
39 #include <deque>
40
41 #include <nghttp2/asio_http2.h>
42
43 using namespace nghttp2::asio_http2;
44 using namespace nghttp2::asio_http2::server;
45
46 int main(int argc, char *argv[]) {
47   try {
48     // Check command line arguments.
49     if (argc < 4) {
50       std::cerr << "Usage: asio-sv3 <port> <threads> <tasks> "
51                 << " <private-key-file> <cert-file>\n";
52       return 1;
53     }
54
55     uint16_t port = std::stoi(argv[1]);
56     std::size_t num_threads = std::stoi(argv[2]);
57     std::size_t num_concurrent_tasks = std::stoi(argv[3]);
58
59     http2 server;
60
61     server.num_threads(num_threads);
62
63     if (argc >= 5) {
64       server.tls(argv[4], argv[5]);
65     }
66
67     server.num_concurrent_tasks(num_concurrent_tasks);
68
69     server.listen("*", port, [](const std::shared_ptr<request> &req,
70                                 const std::shared_ptr<response> &res) {
71       res->write_head(200);
72
73       auto msgq = std::make_shared<std::deque<std::string>>();
74
75       res->end([msgq](uint8_t * buf, std::size_t len)
76                    -> std::pair<ssize_t, bool> {
77         if (msgq->empty()) {
78           // if msgq is empty, tells the library that don't call
79           // this callback until we call res->resume().  This is
80           // done by returing std::make_pair(0, false).
81           return std::make_pair(0, false);
82         }
83         auto msg = std::move(msgq->front());
84         msgq->pop_front();
85
86         if (msg.empty()) {
87           // The empty message signals the end of response in
88           // this simple protocol.
89           return std::make_pair(0, true);
90         }
91
92         auto nwrite = std::min(len, msg.size());
93         std::copy(std::begin(msg), std::begin(msg) + nwrite, buf);
94         if (msg.size() > nwrite) {
95           msgq->push_front(msg.substr(nwrite));
96         }
97         return std::make_pair(nwrite, false);
98       });
99
100       req->run_task([res, msgq](channel &channel) {
101         // executed in different thread from request callback
102         // was called.
103
104         // Using res and msgq is not safe inside this callback.
105         // But using them in callback passed to channel::post is
106         // safe.
107
108         // We just emit simple message "message N\n" in every 1
109         // second and 3 times in total.
110         for (std::size_t i = 0; i < 3; ++i) {
111           msgq->push_back("message " + std::to_string(i + 1) + "\n");
112
113           channel.post([res]() {
114             // executed in same thread where
115             // request callback was called.
116
117             // Tells library we have new message.
118             res->resume();
119           });
120
121           sleep(1);
122         }
123
124         // Send empty message to signal the end of response
125         // body.
126         msgq->push_back("");
127
128         channel.post([res]() {
129           // executed in same thread where request
130           // callback was called.
131           res->resume();
132         });
133
134       });
135
136     });
137   } catch (std::exception &e) {
138     std::cerr << "exception: " << e.what() << "\n";
139   }
140
141   return 0;
142 }