fixed adding file problem
[c11concurrency-benchmarks.git] / gdax-orderbook-hpp / demo / dependencies / websocketpp-0.7.0 / examples / telemetry_server / telemetry_server.cpp
diff --git a/gdax-orderbook-hpp/demo/dependencies/websocketpp-0.7.0/examples/telemetry_server/telemetry_server.cpp b/gdax-orderbook-hpp/demo/dependencies/websocketpp-0.7.0/examples/telemetry_server/telemetry_server.cpp
new file mode 100644 (file)
index 0000000..3f8e604
--- /dev/null
@@ -0,0 +1,203 @@
+#include <websocketpp/config/asio_no_tls.hpp>
+
+#include <websocketpp/server.hpp>
+
+#include <fstream>
+#include <iostream>
+#include <set>
+#include <streambuf>
+#include <string>
+
+/**
+ * The telemetry server accepts connections and sends a message every second to
+ * each client containing an integer count. This example can be used as the
+ * basis for programs that expose a stream of telemetry data for logging,
+ * dashboards, etc.
+ *
+ * This example uses the timer based concurrency method and is self contained
+ * and singled threaded. Refer to telemetry client for an example of a similar
+ * telemetry setup using threads rather than timers.
+ *
+ * This example also includes an example simple HTTP server that serves a web
+ * dashboard displaying the count. This simple design is suitable for use 
+ * delivering a small number of files to a small number of clients. It is ideal
+ * for cases like embedded dashboards that don't want the complexity of an extra
+ * HTTP server to serve static files.
+ *
+ * This design *will* fall over under high traffic or DoS conditions. In such
+ * cases you are much better off proxying to a real HTTP server for the http
+ * requests.
+ */
+class telemetry_server {
+public:
+    typedef websocketpp::connection_hdl connection_hdl;
+    typedef websocketpp::server<websocketpp::config::asio> server;
+
+    telemetry_server() : m_count(0) {
+        // set up access channels to only log interesting things
+        m_endpoint.clear_access_channels(websocketpp::log::alevel::all);
+        m_endpoint.set_access_channels(websocketpp::log::alevel::access_core);
+        m_endpoint.set_access_channels(websocketpp::log::alevel::app);
+
+        // Initialize the Asio transport policy
+        m_endpoint.init_asio();
+
+        // Bind the handlers we are using
+        using websocketpp::lib::placeholders::_1;
+        using websocketpp::lib::bind;
+        m_endpoint.set_open_handler(bind(&telemetry_server::on_open,this,_1));
+        m_endpoint.set_close_handler(bind(&telemetry_server::on_close,this,_1));
+        m_endpoint.set_http_handler(bind(&telemetry_server::on_http,this,_1));
+    }
+
+    void run(std::string docroot, uint16_t port) {
+        std::stringstream ss;
+        ss << "Running telemetry server on port "<< port <<" using docroot=" << docroot;
+        m_endpoint.get_alog().write(websocketpp::log::alevel::app,ss.str());
+        
+        m_docroot = docroot;
+        
+        // listen on specified port
+        m_endpoint.listen(port);
+
+        // Start the server accept loop
+        m_endpoint.start_accept();
+
+        // Set the initial timer to start telemetry
+        set_timer();
+
+        // Start the ASIO io_service run loop
+        try {
+            m_endpoint.run();
+        } catch (websocketpp::exception const & e) {
+            std::cout << e.what() << std::endl;
+        }
+    }
+
+    void set_timer() {
+        m_timer = m_endpoint.set_timer(
+            1000,
+            websocketpp::lib::bind(
+                &telemetry_server::on_timer,
+                this,
+                websocketpp::lib::placeholders::_1
+            )
+        );
+    }
+
+    void on_timer(websocketpp::lib::error_code const & ec) {
+        if (ec) {
+            // there was an error, stop telemetry
+            m_endpoint.get_alog().write(websocketpp::log::alevel::app,
+                    "Timer Error: "+ec.message());
+            return;
+        }
+        
+        std::stringstream val;
+        val << "count is " << m_count++;
+        
+        // Broadcast count to all connections
+        con_list::iterator it;
+        for (it = m_connections.begin(); it != m_connections.end(); ++it) {
+            m_endpoint.send(*it,val.str(),websocketpp::frame::opcode::text);
+        }
+        
+        // set timer for next telemetry check
+        set_timer();
+    }
+
+    void on_http(connection_hdl hdl) {
+        // Upgrade our connection handle to a full connection_ptr
+        server::connection_ptr con = m_endpoint.get_con_from_hdl(hdl);
+    
+        std::ifstream file;
+        std::string filename = con->get_resource();
+        std::string response;
+    
+        m_endpoint.get_alog().write(websocketpp::log::alevel::app,
+            "http request1: "+filename);
+    
+        if (filename == "/") {
+            filename = m_docroot+"index.html";
+        } else {
+            filename = m_docroot+filename.substr(1);
+        }
+        
+        m_endpoint.get_alog().write(websocketpp::log::alevel::app,
+            "http request2: "+filename);
+    
+        file.open(filename.c_str(), std::ios::in);
+        if (!file) {
+            // 404 error
+            std::stringstream ss;
+        
+            ss << "<!doctype html><html><head>"
+               << "<title>Error 404 (Resource not found)</title><body>"
+               << "<h1>Error 404</h1>"
+               << "<p>The requested URL " << filename << " was not found on this server.</p>"
+               << "</body></head></html>";
+        
+            con->set_body(ss.str());
+            con->set_status(websocketpp::http::status_code::not_found);
+            return;
+        }
+    
+        file.seekg(0, std::ios::end);
+        response.reserve(file.tellg());
+        file.seekg(0, std::ios::beg);
+    
+        response.assign((std::istreambuf_iterator<char>(file)),
+                        std::istreambuf_iterator<char>());
+    
+        con->set_body(response);
+        con->set_status(websocketpp::http::status_code::ok);
+    }
+
+    void on_open(connection_hdl hdl) {
+        m_connections.insert(hdl);
+    }
+
+    void on_close(connection_hdl hdl) {
+        m_connections.erase(hdl);
+    }
+private:
+    typedef std::set<connection_hdl,std::owner_less<connection_hdl>> con_list;
+    
+    server m_endpoint;
+    con_list m_connections;
+    server::timer_ptr m_timer;
+    
+    std::string m_docroot;
+    
+    // Telemetry data
+    uint64_t m_count;
+};
+
+int main(int argc, char* argv[]) {
+    telemetry_server s;
+
+    std::string docroot;
+    uint16_t port = 9002;
+
+    if (argc == 1) {
+        std::cout << "Usage: telemetry_server [documentroot] [port]" << std::endl;
+        return 1;
+    }
+    
+    if (argc >= 2) {
+        docroot = std::string(argv[1]);
+    }
+        
+    if (argc >= 3) {
+        int i = atoi(argv[2]);
+        if (i <= 0 || i > 65535) {
+            std::cout << "invalid port" << std::endl;
+            return 1;
+        }
+        
+        port = uint16_t(i);
+    }
+
+    s.run(docroot, port);
+    return 0;
+}