aboutsummaryrefslogtreecommitdiffstats
path: root/vespalib
diff options
context:
space:
mode:
authorHåvard Pettersen <havardpe@oath.com>2021-12-16 15:28:06 +0000
committerHåvard Pettersen <havardpe@oath.com>2021-12-16 15:38:14 +0000
commite6cf9db3f8815a1823dbf9233b70a10f8b1476c7 (patch)
treeb98a20c4df52ec49fd566492f7928061162dbd04 /vespalib
parent9dd324c8de1a1662b2ee9e4bba2e0e273509d6df (diff)
remove experimental websocket code
Diffstat (limited to 'vespalib')
-rw-r--r--vespalib/CMakeLists.txt2
-rw-r--r--vespalib/src/tests/websocket/.gitignore3
-rw-r--r--vespalib/src/tests/websocket/CMakeLists.txt14
-rw-r--r--vespalib/src/tests/websocket/favicon.icobin32038 -> 0 bytes
-rw-r--r--vespalib/src/tests/websocket/index.html5
-rw-r--r--vespalib/src/tests/websocket/test.html70
-rw-r--r--vespalib/src/tests/websocket/websocket_server.cpp51
-rw-r--r--vespalib/src/tests/websocket/websocket_test.cpp117
-rw-r--r--vespalib/src/vespa/vespalib/CMakeLists.txt1
-rw-r--r--vespalib/src/vespa/vespalib/websocket/CMakeLists.txt13
-rw-r--r--vespalib/src/vespa/vespalib/websocket/README22
-rw-r--r--vespalib/src/vespa/vespalib/websocket/acceptor.cpp34
-rw-r--r--vespalib/src/vespa/vespalib/websocket/acceptor.h29
-rw-r--r--vespalib/src/vespa/vespalib/websocket/buffer.cpp18
-rw-r--r--vespalib/src/vespa/vespalib/websocket/buffer.h46
-rw-r--r--vespalib/src/vespa/vespalib/websocket/connection.cpp207
-rw-r--r--vespalib/src/vespa/vespalib/websocket/connection.h54
-rw-r--r--vespalib/src/vespa/vespalib/websocket/frame.cpp7
-rw-r--r--vespalib/src/vespa/vespalib/websocket/frame.h22
-rw-r--r--vespalib/src/vespa/vespalib/websocket/handler.cpp15
-rw-r--r--vespalib/src/vespa/vespalib/websocket/handler.h22
-rw-r--r--vespalib/src/vespa/vespalib/websocket/key.cpp48
-rw-r--r--vespalib/src/vespa/vespalib/websocket/key.h27
-rw-r--r--vespalib/src/vespa/vespalib/websocket/request.cpp142
-rw-r--r--vespalib/src/vespa/vespalib/websocket/request.h38
-rw-r--r--vespalib/src/vespa/vespalib/websocket/websocket_server.cpp164
-rw-r--r--vespalib/src/vespa/vespalib/websocket/websocket_server.h38
27 files changed, 0 insertions, 1209 deletions
diff --git a/vespalib/CMakeLists.txt b/vespalib/CMakeLists.txt
index 400c1ec5d1a..9f98d23d6a9 100644
--- a/vespalib/CMakeLists.txt
+++ b/vespalib/CMakeLists.txt
@@ -153,7 +153,6 @@ vespa_define_module(
src/tests/visit_ranges
src/tests/invokeservice
src/tests/wakeup
- src/tests/websocket
src/tests/zcurve
LIBS
@@ -181,5 +180,4 @@ vespa_define_module(
src/vespa/vespalib/time
src/vespa/vespalib/trace
src/vespa/vespalib/util
- src/vespa/vespalib/websocket
)
diff --git a/vespalib/src/tests/websocket/.gitignore b/vespalib/src/tests/websocket/.gitignore
deleted file mode 100644
index 379d76b3ece..00000000000
--- a/vespalib/src/tests/websocket/.gitignore
+++ /dev/null
@@ -1,3 +0,0 @@
-/websocket_server
-vespalib_websocket_test_app
-vespalib_websocket_server_app
diff --git a/vespalib/src/tests/websocket/CMakeLists.txt b/vespalib/src/tests/websocket/CMakeLists.txt
deleted file mode 100644
index 8581523a98e..00000000000
--- a/vespalib/src/tests/websocket/CMakeLists.txt
+++ /dev/null
@@ -1,14 +0,0 @@
-# Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
-vespa_add_executable(vespalib_websocket_test_app TEST
- SOURCES
- websocket_test.cpp
- DEPENDS
- vespalib
-)
-vespa_add_test(NAME vespalib_websocket_test_app COMMAND vespalib_websocket_test_app)
-vespa_add_executable(vespalib_websocket_server_app
- SOURCES
- websocket_server.cpp
- DEPENDS
- vespalib
-)
diff --git a/vespalib/src/tests/websocket/favicon.ico b/vespalib/src/tests/websocket/favicon.ico
deleted file mode 100644
index 22f61482bd0..00000000000
--- a/vespalib/src/tests/websocket/favicon.ico
+++ /dev/null
Binary files differ
diff --git a/vespalib/src/tests/websocket/index.html b/vespalib/src/tests/websocket/index.html
deleted file mode 100644
index 144d42be14d..00000000000
--- a/vespalib/src/tests/websocket/index.html
+++ /dev/null
@@ -1,5 +0,0 @@
-<!-- Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -->
-<html>
-<h1>Websocket server</h1>
-<a href="test.html">run test</a>
-</html>
diff --git a/vespalib/src/tests/websocket/test.html b/vespalib/src/tests/websocket/test.html
deleted file mode 100644
index f898cfb8da3..00000000000
--- a/vespalib/src/tests/websocket/test.html
+++ /dev/null
@@ -1,70 +0,0 @@
-<!DOCTYPE html>
-<!-- Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -->
-
-<meta charset="utf-8" />
-
-<title>WebSocket Test</title>
-
-<script language="javascript" type="text/javascript">
-
- var wsUri = "ws://[SELF]/echo";
- var output;
-
- function init()
- {
- output = document.getElementById("output");
- testWebSocket();
- }
-
- function testWebSocket()
- {
- websocket = new WebSocket(wsUri);
- websocket.onopen = function(evt) { onOpen(evt) };
- websocket.onclose = function(evt) { onClose(evt) };
- websocket.onmessage = function(evt) { onMessage(evt) };
- websocket.onerror = function(evt) { onError(evt) };
- }
-
- function onOpen(evt)
- {
- writeToScreen("CONNECTED");
- doSend("WebSocket rocks");
- }
-
- function onClose(evt)
- {
- writeToScreen("DISCONNECTED");
- }
-
- function onMessage(evt)
- {
- writeToScreen('<span style="color: blue;">RESPONSE: ' + evt.data+'</span>');
- websocket.close();
- }
-
- function onError(evt)
- {
- writeToScreen('<span style="color: red;">ERROR:</span> ' + evt.data);
- }
-
- function doSend(message)
- {
- writeToScreen("SENT: " + message);
- websocket.send(message);
- }
-
- function writeToScreen(message)
- {
- var pre = document.createElement("p");
- pre.style.wordWrap = "break-word";
- pre.innerHTML = message;
- output.appendChild(pre);
- }
-
- window.addEventListener("load", init, false);
-
-</script>
-
-<h2>WebSocket Test</h2>
-
-<div id="output"></div>
diff --git a/vespalib/src/tests/websocket/websocket_server.cpp b/vespalib/src/tests/websocket/websocket_server.cpp
deleted file mode 100644
index 7a9cf46cb5f..00000000000
--- a/vespalib/src/tests/websocket/websocket_server.cpp
+++ /dev/null
@@ -1,51 +0,0 @@
-// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
-#include <vespa/vespalib/testkit/test_kit.h>
-#include <vespa/vespalib/websocket/websocket_server.h>
-#include <vespa/vespalib/util/host_name.h>
-#include <vespa/vespalib/util/signalhandler.h>
-#include <vespa/vespalib/io/mapped_file_input.h>
-#include <thread>
-#include <chrono>
-
-using namespace vespalib;
-
-vespalib::string read_file(const vespalib::string &file_name) {
- return MappedFileInput(file_name).get().make_string();
-}
-
-vespalib::string find_content_type(const vespalib::string &file_name) {
- if (ends_with(file_name, ".html")) {
- return "text/html";
- }
- if (ends_with(file_name, ".js")) {
- return "text/javascript";
- }
- if (ends_with(file_name, ".ico")) {
- return "image/x-icon";
- }
- return "text/plain";
-}
-
-int main(int, char **) {
- ws::WebsocketServer::StaticRepo repo;
- for (vespalib::string file_name: { "index.html", "test.html", "favicon.ico" }) {
- vespalib::string content = read_file(file_name);
- vespalib::string content_type = find_content_type(file_name);
- if (!content.empty()) {
- fprintf(stderr, "loaded file: %s as content %s\n", file_name.c_str(), content_type.c_str());
- repo.emplace("/" + file_name, ws::WebsocketServer::StaticPage{content_type, content});
- }
- }
- ws::WebsocketServer server(0, std::move(repo));
- int port = server.port();
- SignalHandler::INT.hook();
- fprintf(stderr, "running websocket server at http://%s:%d/index.html\n",
- HostName::get().c_str(), port);
- fprintf(stderr, "use ^C (SIGINT) to exit\n");
- while (!SignalHandler::INT.check()) {
- std::this_thread::sleep_for(std::chrono::seconds(1));
- }
- fprintf(stderr, "exiting...\n");
- kill(getpid(), SIGTERM);
- return 0;
-}
diff --git a/vespalib/src/tests/websocket/websocket_test.cpp b/vespalib/src/tests/websocket/websocket_test.cpp
deleted file mode 100644
index 5b346df4243..00000000000
--- a/vespalib/src/tests/websocket/websocket_test.cpp
+++ /dev/null
@@ -1,117 +0,0 @@
-// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
-#include <vespa/vespalib/testkit/test_kit.h>
-#include <vespa/vespalib/net/socket_spec.h>
-#include <vespa/vespalib/websocket/handler.h>
-#include <vespa/vespalib/websocket/acceptor.h>
-#include <vespa/vespalib/websocket/key.h>
-#include <vespa/vespalib/websocket/buffer.h>
-#include <vespa/vespalib/util/gate.h>
-
-using namespace vespalib;
-using namespace vespalib::ws;
-
-template <typename T>
-struct Receptor : vespalib::ws::Handler<T> {
- std::unique_ptr<T> obj;
- vespalib::Gate gate;
- ~Receptor();
- void handle(std::unique_ptr<T> t) override {
- obj = std::move(t);
- gate.countDown();
- }
-};
-
-template <typename T>
-Receptor<T>::~Receptor() = default;
-
-vespalib::string read_bytes(Socket &socket, size_t wanted_bytes) {
- char tmp[64];
- vespalib::string result;
- while (result.size() < wanted_bytes) {
- size_t read_size = std::min(sizeof(tmp), wanted_bytes - result.size());
- size_t read_result = socket.read(tmp, read_size);
- if (static_cast<ssize_t>(read_result) <= 0) {
- return result;
- }
- result.append(tmp, read_result);
- }
- return result;
-}
-
-void verify_socket_io(bool is_server, Socket &socket) {
- vespalib::string server_message = "hello, this is the server speaking";
- vespalib::string client_message = "please pick up, I need to talk to you";
- if(is_server) {
- socket.write(server_message.data(), server_message.size());
- vespalib::string read = read_bytes(socket, client_message.size());
- EXPECT_EQUAL(client_message, read);
- } else {
- socket.write(client_message.data(), client_message.size());
- vespalib::string read = read_bytes(socket, server_message.size());
- EXPECT_EQUAL(server_message, read);
- }
-}
-
-void verify_socket_io_async(Socket &server, Socket &client) {
- std::thread server_thread(verify_socket_io, true, std::ref(server));
- std::thread client_thread(verify_socket_io, false, std::ref(client));
- server_thread.join();
- client_thread.join();
-}
-
-void check_buffer_stats(const Buffer &buffer, size_t dead, size_t used, size_t free) {
- EXPECT_EQUAL(dead, buffer.dead());
- EXPECT_EQUAL(used, buffer.used());
- EXPECT_EQUAL(free, buffer.free());
-}
-
-TEST("require that basic reserve/commit/obtain/evict buffer cycle works") {
- Buffer buffer;
- check_buffer_stats(buffer, 0, 0, 0);
- char *a = buffer.reserve(1);
- check_buffer_stats(buffer, 0, 0, 1);
- *a = 'x';
- buffer.commit(1);
- check_buffer_stats(buffer, 0, 1, 0);
- EXPECT_EQUAL('x', *buffer.obtain());
- check_buffer_stats(buffer, 0, 1, 0);
- buffer.evict(1);
- check_buffer_stats(buffer, 1, 0, 0);
-}
-
-TEST("require that buffer moves contained data when more space is needed") {
- Buffer buffer;
- memcpy(buffer.reserve(3), "xyz", 3);
- buffer.commit(3);
- EXPECT_EQUAL('x', *buffer.obtain());
- buffer.evict(1);
- EXPECT_EQUAL('y', *buffer.obtain());
- check_buffer_stats(buffer, 1, 2, 0);
- buffer.reserve(1);
- check_buffer_stats(buffer, 0, 2, 1);
- EXPECT_EQUAL('y', *buffer.obtain());
- buffer.evict(1);
- EXPECT_EQUAL('z', *buffer.obtain());
- check_buffer_stats(buffer, 1, 1, 1);
- buffer.reserve(3);
- check_buffer_stats(buffer, 0, 1, 3);
- EXPECT_EQUAL('z', *buffer.obtain());
-}
-
-TEST("require that an acceptor can accept connections asynchronously") {
- Receptor<Socket> server;
- Acceptor acceptor(0, server);
- Socket::UP client = SimpleSocket::connect(SocketSpec::from_port(acceptor.port()));
- server.gate.await(60s);
- ASSERT_TRUE(server.obj.get() != nullptr);
- ASSERT_TRUE(client.get() != nullptr);
- TEST_DO(verify_socket_io_async(*server.obj, *client));
-}
-
-TEST("require that websocket accept tokens are generated correctly") {
- vespalib::string key("dGhlIHNhbXBsZSBub25jZQ==");
- vespalib::string accept_token("s3pPLMBiTxaQ9kYGzzhZRbK+xOo=");
- EXPECT_EQUAL(accept_token, Key::accept(key));
-}
-
-TEST_MAIN() { TEST_RUN_ALL(); }
diff --git a/vespalib/src/vespa/vespalib/CMakeLists.txt b/vespalib/src/vespa/vespalib/CMakeLists.txt
index 738e0c6c766..765ed0d5634 100644
--- a/vespalib/src/vespa/vespalib/CMakeLists.txt
+++ b/vespalib/src/vespa/vespalib/CMakeLists.txt
@@ -24,7 +24,6 @@ vespa_add_library(vespalib
$<TARGET_OBJECTS:vespalib_vespalib_time>
$<TARGET_OBJECTS:vespalib_vespalib_trace>
$<TARGET_OBJECTS:vespalib_vespalib_util>
- $<TARGET_OBJECTS:vespalib_vespalib_websocket>
INSTALL lib64
DEPENDS
${VESPA_GCC_LIB}
diff --git a/vespalib/src/vespa/vespalib/websocket/CMakeLists.txt b/vespalib/src/vespa/vespalib/websocket/CMakeLists.txt
deleted file mode 100644
index 1aee013d2bc..00000000000
--- a/vespalib/src/vespa/vespalib/websocket/CMakeLists.txt
+++ /dev/null
@@ -1,13 +0,0 @@
-# Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
-vespa_add_library(vespalib_vespalib_websocket OBJECT
- SOURCES
- acceptor.cpp
- buffer.cpp
- connection.cpp
- frame.cpp
- handler.cpp
- key.cpp
- request.cpp
- websocket_server.cpp
- DEPENDS
-)
diff --git a/vespalib/src/vespa/vespalib/websocket/README b/vespalib/src/vespa/vespalib/websocket/README
deleted file mode 100644
index 5ecb11cbb12..00000000000
--- a/vespalib/src/vespa/vespalib/websocket/README
+++ /dev/null
@@ -1,22 +0,0 @@
-NOTE:
-
-(0) if you use this code and something breaks; it is your own fault.
-
-(1) this code is experimental and will probably undergo large changes
-before it is ready for production use.
-
-(2) please do not use this code in your applications just yet.
-
-(3) if you have any questions/suggestions about the code, please
-contact havardpe@yahoo-inc.com
-
-(4) the goal of this library:
-- accept websocket connections for application resources
-- serve simple HTTP GET requests (read only)
-- negotiate custom binary connections (fs4 packet protocol, fnet rpc)
-
-(5) what to build on top:
-- Remote Slime Message Passing over websockets (next-gen rpc)
-- back-end state API serving
-- json (text) binding to slime messaging (rpc from browser javascript)
-- HTTP tunneling of application data (cross-colo feeding)
diff --git a/vespalib/src/vespa/vespalib/websocket/acceptor.cpp b/vespalib/src/vespa/vespalib/websocket/acceptor.cpp
deleted file mode 100644
index a8fbb0e4231..00000000000
--- a/vespalib/src/vespa/vespalib/websocket/acceptor.cpp
+++ /dev/null
@@ -1,34 +0,0 @@
-// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
-
-#include "acceptor.h"
-#include <vespa/vespalib/net/socket_spec.h>
-#include <functional>
-
-namespace vespalib::ws {
-
-void
-Acceptor::accept_main(Handler<Socket> &socket_handler)
-{
- while (!_is_closed) {
- SocketHandle handle = _server_socket.accept();
- if (handle.valid()) {
- socket_handler.handle(std::make_unique<SimpleSocket>(std::move(handle)));
- }
- }
-}
-
-Acceptor::Acceptor(int port_in, Handler<Socket> &socket_handler)
- : _server_socket(port_in),
- _is_closed(false),
- _accept_thread(&Acceptor::accept_main, this, std::ref(socket_handler))
-{
-}
-
-Acceptor::~Acceptor()
-{
- _server_socket.shutdown();
- _is_closed = true;
- _accept_thread.join();
-}
-
-} // namespace vespalib::ws
diff --git a/vespalib/src/vespa/vespalib/websocket/acceptor.h b/vespalib/src/vespa/vespalib/websocket/acceptor.h
deleted file mode 100644
index 711c9684161..00000000000
--- a/vespalib/src/vespa/vespalib/websocket/acceptor.h
+++ /dev/null
@@ -1,29 +0,0 @@
-// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
-
-#pragma once
-
-#include "handler.h"
-#include <vespa/vespalib/net/socket.h>
-#include <vespa/vespalib/net/server_socket.h>
-#include <thread>
-#include <atomic>
-
-namespace vespalib {
-namespace ws {
-
-class Acceptor {
-private:
- ServerSocket _server_socket;
- std::atomic<bool> _is_closed;
- std::thread _accept_thread;
-
- void accept_main(Handler<Socket> &socket_handler);
-
-public:
- Acceptor(int port_in, Handler<Socket> &socket_handler);
- ~Acceptor();
- int port() { return _server_socket.address().port(); }
-};
-
-} // namespace vespalib::ws
-} // namespace vespalib
diff --git a/vespalib/src/vespa/vespalib/websocket/buffer.cpp b/vespalib/src/vespa/vespalib/websocket/buffer.cpp
deleted file mode 100644
index c35fd4a3597..00000000000
--- a/vespalib/src/vespa/vespalib/websocket/buffer.cpp
+++ /dev/null
@@ -1,18 +0,0 @@
-// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
-
-#include "buffer.h"
-
-namespace vespalib::ws {
-
-void
-Buffer::ensure_free(size_t bytes)
-{
- memmove(&_data[0], &_data[_read_pos], used());
- _write_pos -= _read_pos;
- _read_pos = 0;
- if (free() < bytes) {
- _data.resize(_write_pos + bytes);
- }
-}
-
-} // namespace vespalib::ws
diff --git a/vespalib/src/vespa/vespalib/websocket/buffer.h b/vespalib/src/vespa/vespalib/websocket/buffer.h
deleted file mode 100644
index 382c60d0b0c..00000000000
--- a/vespalib/src/vespa/vespalib/websocket/buffer.h
+++ /dev/null
@@ -1,46 +0,0 @@
-// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
-
-
-#pragma once
-
-#include <vespa/vespalib/stllike/string.h>
-#include <vector>
-
-namespace vespalib {
-namespace ws {
-
-class Buffer
-{
-private:
- std::vector<char> _data;
- size_t _read_pos;
- size_t _write_pos;
- void ensure_free(size_t bytes);
-public:
- Buffer() : _data(), _read_pos(0), _write_pos(0) {}
- void clear() {
- _read_pos = 0;
- _write_pos = 0;
- }
- size_t dead() const { return _read_pos; }
- size_t used() const { return (_write_pos - _read_pos); }
- size_t free() const { return (_data.size() - _write_pos); }
- bool has_next() const { return (used() > 0); }
- char next() { return _data[_read_pos++]; }
- void push(char value) {
- *reserve(1) = value;
- commit(1);
- }
- const char *obtain() const { return &_data[_read_pos]; }
- void evict(size_t bytes) { _read_pos += bytes; }
- char *reserve(size_t bytes) {
- if (free() < bytes) {
- ensure_free(bytes);
- }
- return &_data[_write_pos];
- }
- void commit(size_t bytes) { _write_pos += bytes; }
-};
-
-} // namespace vespalib::ws
-} // namespace vespalib
diff --git a/vespalib/src/vespa/vespalib/websocket/connection.cpp b/vespalib/src/vespa/vespalib/websocket/connection.cpp
deleted file mode 100644
index 173839f376b..00000000000
--- a/vespalib/src/vespa/vespalib/websocket/connection.cpp
+++ /dev/null
@@ -1,207 +0,0 @@
-// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
-
-#include "connection.h"
-#include <vespa/vespalib/util/size_literals.h>
-#include <cstdarg>
-#include <cassert>
-
-namespace vespalib::ws {
-
-namespace {
-
-void stripCR(vespalib::string &dst) {
- if (!dst.empty() && dst[dst.size() - 1] == '\r') {
- dst.resize(dst.size() - 1);
- }
-}
-
-Frame::Type type_from_opcode(char opcode) {
- switch (opcode) {
- case 0x0: return Frame::Type::NONE;
- case 0x1: return Frame::Type::TEXT;
- case 0x2: return Frame::Type::DATA;
- case 0x8: return Frame::Type::PING;
- case 0x9: return Frame::Type::PONG;
- case 0xa: return Frame::Type::CLOSE;
- default: return Frame::Type::INVALID;
- }
-}
-
-char opcode_from_type(Frame::Type type) {
- switch (type) {
- case Frame::Type::NONE: return 0x0;
- case Frame::Type::TEXT: return 0x1;
- case Frame::Type::DATA: return 0x2;
- case Frame::Type::PING: return 0x8;
- case Frame::Type::PONG: return 0x9;
- case Frame::Type::CLOSE: return 0xa;
- default: return 0xf;
- }
-}
-
-} // namespace vespalib::ws::<unnamed>
-
-
-Connection::Connection(Socket::UP socket)
- : _socket(std::move(socket)),
- _input(),
- _output()
-{
-}
-
-bool
-Connection::fill_input(size_t min_bytes)
-{
- while (_input.used() < min_bytes) {
- size_t max_read = (8_Ki);
- char *ptr = _input.reserve(max_read);
- ssize_t read_res = _socket->read(ptr, max_read);
- if (read_res > 0) {
- _input.commit(read_res);
- } else {
- return false;
- }
- }
- return true;
-}
-
-bool
-Connection::read_line(string &dst)
-{
- dst.clear();
- for (int c = read_byte(); c >= 0; c = read_byte()) {
- if (c != '\n') {
- dst.push_back(c);
- } else {
- stripCR(dst);
- return true;
- }
- }
- return !dst.empty();
-}
-
-bool
-Connection::read_frame(Frame &frame)
-{
- if (!fill_input(2)) {
- return false;
- }
- char h1 = _input.next();
- char h2 = _input.next();
- frame.type = type_from_opcode(h1 & 0x0f);
- frame.last = ((h1 & 0x80) != 0);
- frame.payload.clear();
- size_t len = (h2 & 0x7f);
- if (len > 125) {
- size_t len_bytes = (len == 127) ? 8 : 2;
- if (!fill_input(len_bytes)) {
- return false;
- }
- len = 0;
- for (size_t i = 0; i < len_bytes; ++i) {
- len = (len << 8) + (_input.next() & 0xff);
- }
- }
- char mask[4];
- bool use_mask = ((h2 & 0x80) != 0);
- if (use_mask) {
- if (!fill_input(4)) {
- return false;
- }
- for (size_t i = 0; i < 4; ++i) {
- mask[i] = _input.next();
- }
- }
- if (!fill_input(len)) {
- return false;
- }
- const char *src = _input.obtain();
- char *dst = frame.payload.reserve(len);
- if (use_mask) {
- for (size_t i = 0; i < len; ++i) {
- dst[i] = (src[i] ^ mask[i & 0x3]);
- }
- } else {
- memcpy(dst, src, len);
- }
- frame.payload.commit(len);
- _input.evict(len);
- return true;
-}
-
-void
-Connection::write_frame(const Frame &frame)
-{
- size_t len = frame.payload.used();
- bool large_len = (len > 125);
- bool huge_len = (len > 0xffFF);
- char h1 = opcode_from_type(frame.type);
- if (frame.last) {
- h1 |= 0x80;
- }
- char h2 = (large_len) ? 126 : len;
- if (huge_len) {
- ++h2;
- }
- _output.push(h1);
- _output.push(h2);
- if (large_len) {
- size_t len_bytes = (huge_len) ? 8 : 2;
- size_t len_src = len;
- char *len_dst = _output.reserve(len_bytes);
- for (size_t i = len_bytes; i > 0; --i) {
- len_dst[i - 1] = (len_src & 0xff);
- len_src >>= 8;
- }
- _output.commit(len_bytes);
- }
- char *dst = _output.reserve(len);
- memcpy(dst, frame.payload.obtain(), len);
- _output.commit(len);
-}
-
-void
-Connection::printf(const char *fmt, ...)
-{
- char *dst = _output.reserve(256);
- int space = _output.free();
- int size;
- va_list ap;
- va_start(ap, fmt);
- size = vsnprintf(dst, space, fmt, ap);
- va_end(ap);
- assert(size >= 0);
- if (size >= space) {
- space = size + 1;
- dst = _output.reserve(space);
- va_start(ap, fmt);
- size = vsnprintf(dst, space, fmt, ap);
- va_end(ap);
- assert((size + 1) == space);
- }
- _output.commit(size);
-}
-
-void
-Connection::write(const char *data, size_t len)
-{
- char *dst = _output.reserve(len);
- memcpy(dst, data, len);
- _output.commit(len);
-}
-
-bool
-Connection::flush()
-{
- while (_output.used() > 0) {
- ssize_t write_res = _socket->write(_output.obtain(), _output.used());
- if (write_res > 0) {
- _output.evict(write_res);
- } else {
- return false;
- }
- }
- return true;
-}
-
-} // namespace vespalib::ws
diff --git a/vespalib/src/vespa/vespalib/websocket/connection.h b/vespalib/src/vespa/vespalib/websocket/connection.h
deleted file mode 100644
index fdfcd227f98..00000000000
--- a/vespalib/src/vespa/vespalib/websocket/connection.h
+++ /dev/null
@@ -1,54 +0,0 @@
-// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
-
-
-#pragma once
-
-#include <vespa/vespalib/net/socket.h>
-#include "buffer.h"
-#include "frame.h"
-
-namespace vespalib {
-namespace ws {
-
-class Connection
-{
-private:
- Socket::UP _socket;
- Buffer _input;
- Buffer _output;
-
- bool fill_input(size_t min_bytes);
-
-public:
- typedef std::unique_ptr<Connection> UP;
- explicit Connection(Socket::UP socket);
-
- int read_byte() {
- if (!_input.has_next()) {
- if (!fill_input(1)) {
- return -1;
- }
- }
- return (_input.next() & 0xff);
- }
-
- bool read_line(vespalib::string &dst);
-
- bool read_frame(Frame &frame);
-
- void write_frame(const Frame &frame);
-
- void printf(const char *fmt, ...)
-#ifdef __GNUC__
- // Add printf format checks with gcc
- __attribute__ ((format (printf,2,3)))
-#endif
- ;
-
- void write(const char *data, size_t len);
-
- bool flush();
-};
-
-} // namespace vespalib::ws
-} // namespace vespalib
diff --git a/vespalib/src/vespa/vespalib/websocket/frame.cpp b/vespalib/src/vespa/vespalib/websocket/frame.cpp
deleted file mode 100644
index d742d95698b..00000000000
--- a/vespalib/src/vespa/vespalib/websocket/frame.cpp
+++ /dev/null
@@ -1,7 +0,0 @@
-// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
-
-#include "frame.h"
-
-namespace vespalib::ws {
-
-} // namespace vespalib::ws
diff --git a/vespalib/src/vespa/vespalib/websocket/frame.h b/vespalib/src/vespa/vespalib/websocket/frame.h
deleted file mode 100644
index 17a9d2008e8..00000000000
--- a/vespalib/src/vespa/vespalib/websocket/frame.h
+++ /dev/null
@@ -1,22 +0,0 @@
-// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
-
-
-#pragma once
-
-#include <memory>
-#include <vespa/vespalib/stllike/string.h>
-#include "buffer.h"
-
-namespace vespalib {
-namespace ws {
-
-struct Frame {
- enum class Type { NONE, TEXT, DATA, PING, PONG, CLOSE, INVALID };
- Type type;
- bool last;
- Buffer payload;
- Frame() : type(Type::INVALID), last(true), payload() {}
-};
-
-} // namespace vespalib::ws
-} // namespace vespalib
diff --git a/vespalib/src/vespa/vespalib/websocket/handler.cpp b/vespalib/src/vespa/vespalib/websocket/handler.cpp
deleted file mode 100644
index bbff65447d8..00000000000
--- a/vespalib/src/vespa/vespalib/websocket/handler.cpp
+++ /dev/null
@@ -1,15 +0,0 @@
-// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
-
-#include "handler.h"
-
-namespace vespalib::ws {
-
-namespace {
-
-struct DummyItem {};
-
-} // namespace vespalib::ws::<unnamed>
-
-template struct Handler<DummyItem>;
-
-} // namespace vespalib::ws
diff --git a/vespalib/src/vespa/vespalib/websocket/handler.h b/vespalib/src/vespa/vespalib/websocket/handler.h
deleted file mode 100644
index 8919f4bfdcc..00000000000
--- a/vespalib/src/vespa/vespalib/websocket/handler.h
+++ /dev/null
@@ -1,22 +0,0 @@
-// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
-
-
-#pragma once
-
-#include <memory>
-
-namespace vespalib {
-namespace ws {
-
-/**
- * A Handler is a component to whom you can pass an object.
- **/
-template <typename T>
-struct Handler
-{
- virtual void handle(std::unique_ptr<T> obj) = 0;
- virtual ~Handler() {}
-};
-
-} // namespace vespalib::ws
-} // namespace vespalib
diff --git a/vespalib/src/vespa/vespalib/websocket/key.cpp b/vespalib/src/vespa/vespalib/websocket/key.cpp
deleted file mode 100644
index 0760c10fe31..00000000000
--- a/vespalib/src/vespa/vespalib/websocket/key.cpp
+++ /dev/null
@@ -1,48 +0,0 @@
-// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
-
-#include "key.h"
-#include <vespa/vespalib/util/sha1.h>
-
-namespace vespalib::ws {
-
-namespace {
-
-const char *base64_chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
- "abcdefghijklmnopqrstuvwxyz"
- "0123456789+/";
-
-char id(int value) { return base64_chars[value & 0x3f]; }
-vespalib::string encode64(const char *data, size_t len) {
- uint8_t tmp[3];
- vespalib::string result;
- for (size_t i = 0; i < len; i += 3) {
- tmp[0] = data[i];
- tmp[1] = (i + 1 < len) ? data[i + 1] : 0;
- tmp[2] = (i + 2 < len) ? data[i + 2] : 0;
- result.append(id(tmp[0] >> 2));
- result.append(id((tmp[0] << 4) | (tmp[1] >> 4)));
- result.append((i + 1 < len) ? id((tmp[1] << 2) | (tmp[2] >> 6)) : '=');
- result.append((i + 2 < len) ? id(tmp[2]) : '=');
- }
- return result;
-}
-
-} // namespace vespalib::ws::<unnamed>
-
-vespalib::string
-Key::create()
-{
- return "dGhlIHNhbXBsZSBub25jZQ==";
-}
-
-vespalib::string
-Key::accept(const vespalib::string &key)
-{
- char hash[20];
- vespalib::string hash_input(key);
- hash_input.append("258EAFA5-E914-47DA-95CA-C5AB0DC85B11");
- Sha1::hash(hash_input.data(), hash_input.size(), hash, 20);
- return encode64(hash, 20);
-}
-
-} // namespace vespalib::ws
diff --git a/vespalib/src/vespa/vespalib/websocket/key.h b/vespalib/src/vespa/vespalib/websocket/key.h
deleted file mode 100644
index 76062594f38..00000000000
--- a/vespalib/src/vespa/vespalib/websocket/key.h
+++ /dev/null
@@ -1,27 +0,0 @@
-// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
-
-
-#pragma once
-
-#include <vespa/vespalib/stllike/string.h>
-
-namespace vespalib {
-namespace ws {
-
-struct Key
-{
- /**
- * Create a new random key that can be used by a client to request
- * a version 13 websocket connection upgrade.
- **/
- static vespalib::string create();
-
- /**
- * Generate a version 13 websocket handshake accept token for a
- * client key.
- **/
- static vespalib::string accept(const vespalib::string &key);
-};
-
-} // namespace vespalib::ws
-} // namespace vespalib
diff --git a/vespalib/src/vespa/vespalib/websocket/request.cpp b/vespalib/src/vespa/vespalib/websocket/request.cpp
deleted file mode 100644
index 44b05d9947e..00000000000
--- a/vespalib/src/vespa/vespalib/websocket/request.cpp
+++ /dev/null
@@ -1,142 +0,0 @@
-// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
-
-#include "request.h"
-#include <cassert>
-#include <algorithm>
-
-namespace vespalib::ws {
-
-namespace {
-
-void split(vespalib::stringref str, vespalib::stringref sep,
- std::vector<vespalib::string> &dst)
-{
- dst.clear();
- vespalib::string tmp;
- for (size_t i = 0; i < str.size(); ++i) {
- if (sep.find(str[i]) != vespalib::string::npos) {
- if (!tmp.empty()) {
- dst.push_back(tmp);
- tmp.clear();
- }
- } else {
- tmp.push_back(str[i]);
- }
- }
- if (!tmp.empty()) {
- dst.push_back(tmp);
- }
-}
-
-} // namespace vespalib::ws::<unnamed>
-
-Request::Request() { }
-Request::~Request() { }
-
-bool
-Request::handle_header(vespalib::string &header_name,
- const vespalib::string &header_line)
-{
- assert(!header_line.empty());
- size_t pos = 0;
- size_t end = header_line.size();
- bool continuation = (header_line[0] == ' ') || (header_line[0] == '\t');
- if (!continuation) {
- pos = header_line.find(":");
- if (pos == vespalib::string::npos) {
- return false;
- } else {
- header_name.assign(header_line, 0, pos++);
- std::transform(header_name.begin(), header_name.end(),
- header_name.begin(), ::tolower);
- }
- }
- while ((pos < end) && (isspace(header_line[pos]))) {
- ++pos; // strip leading whitespace
- }
- while ((pos < end) && (isspace(header_line[end - 1]))) {
- --end; // strip trailing whitespace
- }
- if (header_name.empty()) {
- return false;
- }
- auto header_insert_result = _headers.insert(std::make_pair(header_name, vespalib::string()));
- bool header_found = !header_insert_result.second;
- vespalib::string &header_value = header_insert_result.first->second;
- if (!header_found) {
- header_value.assign(header_line, pos, end - pos);
- } else {
- if (continuation) {
- header_value.push_back(' ');
- } else { // duplicate header
- header_value.push_back(',');
- }
- header_value.append(header_line.data() + pos, end - pos);
- }
- return true;
-}
-
-bool
-Request::read_header(Connection &conn)
-{
- vespalib::string line;
- vespalib::string header_name_space;
- std::vector<vespalib::string> parts;
- if (!conn.read_line(line)) {
- return false;
- }
- split(line, "\t ", parts);
- if (parts.size() != 3) {
- return false;
- }
- _method = parts[0];
- _uri = parts[1];
- _version = parts[2];
- while (conn.read_line(line)) {
- if (line.empty()) {
- fprintf(stderr, "request: %s %s %s\n",
- _method.c_str(), _uri.c_str(), _version.c_str());
- for (const auto &h: _headers) {
- fprintf(stderr, "request: '%s' -> '%s'\n",
- h.first.c_str(), h.second.c_str());
- }
- return true; // done
- }
- if (!handle_header(header_name_space, line)) {
- return false; // malformed header
- }
- }
- return false; // incomplete headers
-}
-
-const vespalib::string &
-Request::get_header(const vespalib::string &name) const
-{
- auto pos = _headers.find(name);
- if (pos == _headers.end()) {
- return _empty;
- }
- return pos->second;
-}
-
-bool
-Request::has_connection_token(const vespalib::string &token) const
-{
- std::vector<vespalib::string> tokens;
- split(get_header("connection"), ",\t ", tokens);
- for (const auto &t: tokens) {
- if (strcasecmp(t.c_str(), token.c_str()) == 0) {
- return true;
- }
- }
- return false;
-}
-
-bool
-Request::is_ws_upgrade() const
-{
- return ((strcasecmp(get_header("upgrade").c_str(), "websocket") == 0) &&
- has_connection_token("upgrade"));
-}
-
-}
diff --git a/vespalib/src/vespa/vespalib/websocket/request.h b/vespalib/src/vespa/vespalib/websocket/request.h
deleted file mode 100644
index fb4dc25b0ab..00000000000
--- a/vespalib/src/vespa/vespalib/websocket/request.h
+++ /dev/null
@@ -1,38 +0,0 @@
-// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
-
-
-#pragma once
-
-#include "connection.h"
-#include <vespa/vespalib/stllike/string.h>
-#include <map>
-#include <vector>
-
-namespace vespalib {
-namespace ws {
-
-class Request
-{
-private:
- vespalib::string _method;
- vespalib::string _uri;
- vespalib::string _version;
- std::map<vespalib::string, vespalib::string> _headers;
- vespalib::string _empty;
-
- bool handle_header(vespalib::string &header_name,
- const vespalib::string &header_line);
-
-public:
- Request();
- ~Request();
- bool read_header(Connection &conn);
- bool is_get() const { return _method == "GET"; }
- const vespalib::string &get_header(const vespalib::string &name) const;
- bool has_connection_token(const vespalib::string &token) const;
- bool is_ws_upgrade() const;
- const vespalib::string &uri() const { return _uri; }
-};
-
-} // namespace vespalib::ws
-} // namespace vespalib
diff --git a/vespalib/src/vespa/vespalib/websocket/websocket_server.cpp b/vespalib/src/vespa/vespalib/websocket/websocket_server.cpp
deleted file mode 100644
index dc9b38cd87c..00000000000
--- a/vespalib/src/vespa/vespalib/websocket/websocket_server.cpp
+++ /dev/null
@@ -1,164 +0,0 @@
-// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
-
-#include "websocket_server.h"
-#include "connection.h"
-#include "request.h"
-#include "key.h"
-#include <vespa/vespalib/util/stringfmt.h>
-#include <vespa/vespalib/util/host_name.h>
-
-namespace vespalib::ws {
-
-namespace {
-
-vespalib::string magic = "[SELF]";
-
-void respond_static(Connection &conn, const WebsocketServer::StaticPage &page, const vespalib::string &self) {
- conn.printf("HTTP/1.1 200 OK\r\n");
- conn.printf("Connection: close\r\n");
- conn.printf("Content-Type: %s\r\n", page.content_type.c_str());
- conn.printf("\r\n");
- size_t pos = 0;
- while (pos < page.content.size()) {
- size_t next = page.content.find(magic, pos);
- if (next == vespalib::string::npos) {
- conn.write(page.content.data() + pos, page.content.size() - pos);
- pos = page.content.size();
- } else {
- conn.write(page.content.data() + pos, next - pos);
- conn.write(self.data(), self.size());
- pos = next + magic.size();
- }
- }
- conn.flush();
-}
-
-void respond_error(Connection &conn, int code, const vespalib::string &message) {
- conn.printf("HTTP/1.1 %d %s\r\n", code, message.c_str());
- conn.printf("Connection: close\r\n");
- conn.printf("Content-Type: text/html\r\n");
- conn.printf("\r\n");
- conn.printf("<html><body><h2>%d %s</h2></body></html>",
- code, message.c_str());
- conn.flush();
-}
-
-void respond_upgrade(Connection &conn, const vespalib::string &accept_token) {
- conn.printf("HTTP/1.1 101 Switching Protocols\r\n");
- conn.printf("Upgrade: websocket\r\n");
- conn.printf("Connection: Upgrade\r\n");
- conn.printf("Sec-WebSocket-Accept: %s\r\n", accept_token.c_str());
- conn.printf("\r\n");
- conn.flush();
-}
-
-void respond_upgrade_failed(Connection &conn) {
- conn.printf("HTTP/1.1 400 Upgrade Failed\r\n");
- conn.printf("Connection: close\r\n");
- conn.printf("Sec-WebSocket-Version: 13\r\n");
- conn.printf("\r\n");
- conn.flush();
-}
-
-const char *name_from_type(Frame::Type type) {
- switch (type) {
- case Frame::Type::NONE: return "NONE";
- case Frame::Type::TEXT: return "TEXT";
- case Frame::Type::DATA: return "DATA";
- case Frame::Type::PING: return "PING";
- case Frame::Type::PONG: return "PONG";
- case Frame::Type::CLOSE: return "CLOSE";
- default: return "INVALID";
- }
-}
-
-void handle_echo(Connection &conn) {
- fprintf(stderr, "server: got ws connection\n");
- Frame frame;
- bool done = false;
- while (!done && conn.read_frame(frame)) {
- fprintf(stderr, "server: got frame of type %s with size %zu\n",
- name_from_type(frame.type), frame.payload.used());
- if (frame.type == Frame::Type::TEXT) {
- fprintf(stderr, "server: got text: %s\n",
- vespalib::string(frame.payload.obtain(),
- frame.payload.used()).c_str());
- }
- if (frame.type == Frame::Type::INVALID) {
- break;
- }
- if (frame.type == Frame::Type::PONG) {
- continue;
- }
- if (frame.type == Frame::Type::PING) {
- frame.type = Frame::Type::PONG;
- }
- if (frame.type == Frame::Type::CLOSE) {
- done = true;
- }
- conn.write_frame(frame);
- conn.flush();
- }
- fprintf(stderr, "server: closing ws connection\n");
-}
-
-void handle_upgrade(Connection &conn, Request &req) {
- const vespalib::string version = req.get_header("sec-websocket-version");
- vespalib::string accept_token = Key::accept(req.get_header("sec-websocket-key"));
- if (version == "13") {
- respond_upgrade(conn, accept_token);
- handle_echo(conn);
- } else {
- respond_upgrade_failed(conn);
- }
-}
-
-} // namespace vespalib::ws::<unnamed>
-
-WebsocketServer::StaticPage::StaticPage(const vespalib::string & type, const vespalib::string & content_in)
- : content_type(type),
- content(content_in)
-{}
-WebsocketServer::StaticPage::StaticPage(const StaticPage &) = default;
-WebsocketServer::StaticPage & WebsocketServer::StaticPage::operator = (const StaticPage &) = default;
-WebsocketServer::StaticPage::~StaticPage() = default;
-
-WebsocketServer::WebsocketServer(int port_in, StaticRepo &&repo)
- : _acceptor(port_in, *this),
- _static_repo(std::move(repo)),
- _self(make_string("%s:%d", HostName::get().c_str(), _acceptor.port()))
-{
-}
-
-WebsocketServer::~WebsocketServer() = default;
-
-void
-WebsocketServer::handle(std::unique_ptr<Socket> socket)
-{
- Connection conn(std::move(socket));
- Request req;
- if (!req.read_header(conn)) {
- respond_error(conn, 400, "Bad Request");
- return;
- }
- if (!req.is_get()) {
- respond_error(conn, 501, "Not Implemented");
- return;
- }
- if (req.is_ws_upgrade()) {
- if (req.uri() == "/echo") {
- handle_upgrade(conn, req);
- } else {
- respond_error(conn, 404, "Not Found");
- }
- } else {
- auto page = _static_repo.find(req.uri());
- if (page != _static_repo.end()) {
- respond_static(conn, page->second, _self);
- } else {
- respond_error(conn, 404, "Not Found");
- }
- }
-}
-
-}
diff --git a/vespalib/src/vespa/vespalib/websocket/websocket_server.h b/vespalib/src/vespa/vespalib/websocket/websocket_server.h
deleted file mode 100644
index f30daafb726..00000000000
--- a/vespalib/src/vespa/vespalib/websocket/websocket_server.h
+++ /dev/null
@@ -1,38 +0,0 @@
-// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
-
-#pragma once
-
-#include "handler.h"
-#include "acceptor.h"
-#include <vespa/vespalib/stllike/string.h>
-#include <map>
-
-namespace vespalib::ws {
-
-class WebsocketServer : public Handler<Socket> {
-public:
- struct StaticPage {
- StaticPage(const vespalib::string & type, const vespalib::string & content_in);
- StaticPage(const StaticPage &);
- StaticPage & operator = (const StaticPage &);
- StaticPage(StaticPage &&) = default;
- StaticPage & operator = (StaticPage &&) = default;
- ~StaticPage();
- vespalib::string content_type;
- vespalib::string content;
- };
- typedef std::map<vespalib::string, StaticPage> StaticRepo;
-
-private:
- Acceptor _acceptor;
- StaticRepo _static_repo;
- vespalib::string _self;
-
-public:
- WebsocketServer(int port_in, StaticRepo &&repo = StaticRepo());
- ~WebsocketServer() override;
- void handle(std::unique_ptr<Socket> socket) override;
- int port() { return _acceptor.port(); }
-};
-
-} // namespace vespalib::ws