blob: fec4ccf4fa1c1f38891feeee10ccd4403f9e3d03 [file] [log] [blame]
Austin Schuh9d823002019-04-14 12:53:17 -07001// Copyright (c) 2013-2017, Matt Godbolt
Austin Schuh24adb6b2015-09-06 17:37:40 -07002// All rights reserved.
Austin Schuh9d823002019-04-14 12:53:17 -07003//
4// Redistribution and use in source and binary forms, with or without
Austin Schuh24adb6b2015-09-06 17:37:40 -07005// modification, are permitted provided that the following conditions are met:
Austin Schuh9d823002019-04-14 12:53:17 -07006//
7// Redistributions of source code must retain the above copyright notice, this
Austin Schuh24adb6b2015-09-06 17:37:40 -07008// list of conditions and the following disclaimer.
Austin Schuh9d823002019-04-14 12:53:17 -07009//
10// Redistributions in binary form must reproduce the above copyright notice,
11// this list of conditions and the following disclaimer in the documentation
Austin Schuh24adb6b2015-09-06 17:37:40 -070012// and/or other materials provided with the distribution.
Austin Schuh9d823002019-04-14 12:53:17 -070013//
14// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
15// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
18// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
19// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
20// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
21// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
22// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
23// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
Austin Schuh24adb6b2015-09-06 17:37:40 -070024// POSSIBILITY OF SUCH DAMAGE.
25
26// An extraordinarily simple test which presents a web page with some buttons.
27// Clicking on the numbered button increments the number, which is visible to
28// other connected clients. WebSockets are used to do this: by the rather
29// suspicious means of sending raw JavaScript commands to be executed on other
30// clients.
31
32#include "seasocks/PrintfLogger.h"
33#include "seasocks/Server.h"
34#include "seasocks/StringUtil.h"
35#include "seasocks/WebSocket.h"
36#include "seasocks/util/Json.h"
37
38#include <cstring>
39#include <iostream>
40#include <memory>
41#include <set>
42#include <sstream>
43#include <string>
44
45using namespace seasocks;
Austin Schuh24adb6b2015-09-06 17:37:40 -070046
Austin Schuh9d823002019-04-14 12:53:17 -070047class MyHandler : public WebSocket::Handler {
Austin Schuh24adb6b2015-09-06 17:37:40 -070048public:
Austin Schuh9d823002019-04-14 12:53:17 -070049 explicit MyHandler(Server* server)
50 : _server(server), _currentValue(0) {
Austin Schuh24adb6b2015-09-06 17:37:40 -070051 setValue(1);
52 }
53
Austin Schuh9d823002019-04-14 12:53:17 -070054 virtual void onConnect(WebSocket* connection) override {
Austin Schuh24adb6b2015-09-06 17:37:40 -070055 _connections.insert(connection);
56 connection->send(_currentSetValue.c_str());
Austin Schuh9d823002019-04-14 12:53:17 -070057 std::cout << "Connected: " << connection->getRequestUri()
58 << " : " << formatAddress(connection->getRemoteAddress())
59 << "\nCredentials: " << *(connection->credentials()) << "\n";
Austin Schuh24adb6b2015-09-06 17:37:40 -070060 }
61
Austin Schuh9d823002019-04-14 12:53:17 -070062 virtual void onData(WebSocket* connection, const char* data) override {
Austin Schuh24adb6b2015-09-06 17:37:40 -070063 if (0 == strcmp("die", data)) {
64 _server->terminate();
65 return;
66 }
67 if (0 == strcmp("close", data)) {
Austin Schuh9d823002019-04-14 12:53:17 -070068 std::cout << "Closing..\n";
Austin Schuh24adb6b2015-09-06 17:37:40 -070069 connection->close();
Austin Schuh9d823002019-04-14 12:53:17 -070070 std::cout << "Closed.\n";
Austin Schuh24adb6b2015-09-06 17:37:40 -070071 return;
72 }
73
Austin Schuh9d823002019-04-14 12:53:17 -070074 const int value = std::stoi(data) + 1;
Austin Schuh24adb6b2015-09-06 17:37:40 -070075 if (value > _currentValue) {
76 setValue(value);
Austin Schuh9d823002019-04-14 12:53:17 -070077 for (auto c : _connections) {
78 c->send(_currentSetValue.c_str());
Austin Schuh24adb6b2015-09-06 17:37:40 -070079 }
80 }
81 }
82
Austin Schuh9d823002019-04-14 12:53:17 -070083 virtual void onDisconnect(WebSocket* connection) override {
Austin Schuh24adb6b2015-09-06 17:37:40 -070084 _connections.erase(connection);
Austin Schuh9d823002019-04-14 12:53:17 -070085 std::cout << "Disconnected: " << connection->getRequestUri()
86 << " : " << formatAddress(connection->getRemoteAddress()) << "\n";
Austin Schuh24adb6b2015-09-06 17:37:40 -070087 }
88
89private:
Austin Schuh9d823002019-04-14 12:53:17 -070090 std::set<WebSocket*> _connections;
Austin Schuh24adb6b2015-09-06 17:37:40 -070091 Server* _server;
92 int _currentValue;
Austin Schuh9d823002019-04-14 12:53:17 -070093 std::string _currentSetValue;
Austin Schuh24adb6b2015-09-06 17:37:40 -070094
95 void setValue(int value) {
96 _currentValue = value;
97 _currentSetValue = makeExecString("set", _currentValue);
98 }
99};
100
Austin Schuh9d823002019-04-14 12:53:17 -0700101int main(int /*argc*/, const char* /*argv*/[]) {
102 auto logger = std::make_shared<PrintfLogger>(Logger::Level::Debug);
Austin Schuh24adb6b2015-09-06 17:37:40 -0700103
104 Server server(logger);
105
Austin Schuh9d823002019-04-14 12:53:17 -0700106 auto handler = std::make_shared<MyHandler>(&server);
Austin Schuh24adb6b2015-09-06 17:37:40 -0700107 server.addWebSocketHandler("/ws", handler);
108 server.serve("src/ws_test_web", 9090);
109 return 0;
110}