2015-04-13 04:09:02 -05:00
|
|
|
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
|
2015-03-27 09:23:20 -05:00
|
|
|
/*
|
|
|
|
* This file is part of the LibreOffice project.
|
|
|
|
*
|
|
|
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
|
|
*/
|
|
|
|
|
2016-04-08 06:49:33 -05:00
|
|
|
#include "config.h"
|
|
|
|
|
2015-04-24 10:18:56 -05:00
|
|
|
#include <cstdlib>
|
2015-04-14 09:50:38 -05:00
|
|
|
#include <cstring>
|
|
|
|
#include <fstream>
|
2015-03-27 09:23:20 -05:00
|
|
|
#include <iostream>
|
2016-04-20 10:31:16 -05:00
|
|
|
#include <mutex>
|
2016-09-17 08:48:39 -05:00
|
|
|
#include <thread>
|
2015-03-27 09:23:20 -05:00
|
|
|
|
2016-03-22 13:06:44 -05:00
|
|
|
#include <Poco/Net/AcceptCertificateHandler.h>
|
|
|
|
#include <Poco/Net/Context.h>
|
2016-04-08 04:24:52 -05:00
|
|
|
#include <Poco/Net/HTTPClientSession.h>
|
2015-03-27 09:23:20 -05:00
|
|
|
#include <Poco/Net/HTTPRequest.h>
|
|
|
|
#include <Poco/Net/HTTPResponse.h>
|
loolwsd: include cleanup and organization
A source file (.cpp) must include its own header first.
This insures that the header is self-contained and
doesn't depend on arbitrary (and accidental) includes
before it to compile.
Furthermore, system headers should go next, followed by
C then C++ headers, then libraries (Poco, etc) and, finally,
project headers come last.
This makes sure that headers and included in the same dependency
order to avoid side-effects. For example, Poco should never rely on
anything from our project in the same way that a C header should
never rely on anything in C++, Poco, or project headers.
Also, includes ought to be sorted where possible, to improve
readability and avoid accidental duplicates (of which there
were a few).
Change-Id: I62cc1343e4a091d69195e37ed659dba20cfcb1ef
Reviewed-on: https://gerrit.libreoffice.org/25262
Reviewed-by: Ashod Nakashian <ashnakash@gmail.com>
Tested-by: Ashod Nakashian <ashnakash@gmail.com>
2016-05-21 09:23:07 -05:00
|
|
|
#include <Poco/Net/HTTPSClientSession.h>
|
2016-03-22 13:06:44 -05:00
|
|
|
#include <Poco/Net/InvalidCertificateHandler.h>
|
2015-03-27 09:23:20 -05:00
|
|
|
#include <Poco/Net/NetException.h>
|
2016-03-22 13:06:44 -05:00
|
|
|
#include <Poco/Net/PrivateKeyPassphraseHandler.h>
|
|
|
|
#include <Poco/Net/SSLManager.h>
|
loolwsd: include cleanup and organization
A source file (.cpp) must include its own header first.
This insures that the header is self-contained and
doesn't depend on arbitrary (and accidental) includes
before it to compile.
Furthermore, system headers should go next, followed by
C then C++ headers, then libraries (Poco, etc) and, finally,
project headers come last.
This makes sure that headers and included in the same dependency
order to avoid side-effects. For example, Poco should never rely on
anything from our project in the same way that a C header should
never rely on anything in C++, Poco, or project headers.
Also, includes ought to be sorted where possible, to improve
readability and avoid accidental duplicates (of which there
were a few).
Change-Id: I62cc1343e4a091d69195e37ed659dba20cfcb1ef
Reviewed-on: https://gerrit.libreoffice.org/25262
Reviewed-by: Ashod Nakashian <ashnakash@gmail.com>
Tested-by: Ashod Nakashian <ashnakash@gmail.com>
2016-05-21 09:23:07 -05:00
|
|
|
#include <Poco/Net/SocketStream.h>
|
2015-03-27 09:23:20 -05:00
|
|
|
#include <Poco/Net/StreamSocket.h>
|
|
|
|
#include <Poco/Net/TCPServer.h>
|
|
|
|
#include <Poco/Net/TCPServerConnection.h>
|
|
|
|
#include <Poco/Net/TCPServerConnectionFactory.h>
|
|
|
|
#include <Poco/Process.h>
|
2016-03-22 13:06:44 -05:00
|
|
|
#include <Poco/SharedPtr.h>
|
2015-04-14 09:50:38 -05:00
|
|
|
#include <Poco/StringTokenizer.h>
|
|
|
|
#include <Poco/TemporaryFile.h>
|
2015-03-27 09:23:20 -05:00
|
|
|
#include <Poco/Thread.h>
|
|
|
|
#include <Poco/URI.h>
|
|
|
|
#include <Poco/Util/Application.h>
|
loolwsd: include cleanup and organization
A source file (.cpp) must include its own header first.
This insures that the header is self-contained and
doesn't depend on arbitrary (and accidental) includes
before it to compile.
Furthermore, system headers should go next, followed by
C then C++ headers, then libraries (Poco, etc) and, finally,
project headers come last.
This makes sure that headers and included in the same dependency
order to avoid side-effects. For example, Poco should never rely on
anything from our project in the same way that a C header should
never rely on anything in C++, Poco, or project headers.
Also, includes ought to be sorted where possible, to improve
readability and avoid accidental duplicates (of which there
were a few).
Change-Id: I62cc1343e4a091d69195e37ed659dba20cfcb1ef
Reviewed-on: https://gerrit.libreoffice.org/25262
Reviewed-by: Ashod Nakashian <ashnakash@gmail.com>
Tested-by: Ashod Nakashian <ashnakash@gmail.com>
2016-05-21 09:23:07 -05:00
|
|
|
#include <Poco/Version.h>
|
2015-03-27 09:23:20 -05:00
|
|
|
|
2015-12-27 16:23:43 -06:00
|
|
|
#include "Common.hpp"
|
2016-11-24 08:56:06 -06:00
|
|
|
#include "Protocol.hpp"
|
2016-11-10 02:47:25 -06:00
|
|
|
#include <LOOLWebSocket.hpp>
|
loolwsd: include cleanup and organization
A source file (.cpp) must include its own header first.
This insures that the header is self-contained and
doesn't depend on arbitrary (and accidental) includes
before it to compile.
Furthermore, system headers should go next, followed by
C then C++ headers, then libraries (Poco, etc) and, finally,
project headers come last.
This makes sure that headers and included in the same dependency
order to avoid side-effects. For example, Poco should never rely on
anything from our project in the same way that a C header should
never rely on anything in C++, Poco, or project headers.
Also, includes ought to be sorted where possible, to improve
readability and avoid accidental duplicates (of which there
were a few).
Change-Id: I62cc1343e4a091d69195e37ed659dba20cfcb1ef
Reviewed-on: https://gerrit.libreoffice.org/25262
Reviewed-by: Ashod Nakashian <ashnakash@gmail.com>
Tested-by: Ashod Nakashian <ashnakash@gmail.com>
2016-05-21 09:23:07 -05:00
|
|
|
#include "Log.hpp"
|
2015-03-27 09:23:20 -05:00
|
|
|
#include "Util.hpp"
|
|
|
|
|
|
|
|
using namespace LOOLProtocol;
|
|
|
|
|
2016-03-22 13:06:44 -05:00
|
|
|
using Poco::Net::AcceptCertificateHandler;
|
|
|
|
using Poco::Net::Context;
|
2016-05-24 07:13:58 -05:00
|
|
|
#if ENABLE_SSL
|
2016-03-22 13:06:44 -05:00
|
|
|
using Poco::Net::HTTPSClientSession;
|
2016-05-24 07:13:58 -05:00
|
|
|
#else
|
|
|
|
using Poco::Net::HTTPClientSession;
|
|
|
|
#endif
|
2015-03-27 09:23:20 -05:00
|
|
|
using Poco::Net::HTTPRequest;
|
|
|
|
using Poco::Net::HTTPResponse;
|
2016-03-22 13:06:44 -05:00
|
|
|
using Poco::Net::InvalidCertificateHandler;
|
|
|
|
using Poco::Net::SSLManager;
|
2015-03-27 09:23:20 -05:00
|
|
|
using Poco::Net::WebSocket;
|
|
|
|
using Poco::Net::WebSocketException;
|
|
|
|
using Poco::Runnable;
|
2016-03-22 13:06:44 -05:00
|
|
|
using Poco::SharedPtr;
|
2015-04-14 09:50:38 -05:00
|
|
|
using Poco::StringTokenizer;
|
|
|
|
using Poco::TemporaryFile;
|
2015-03-27 09:23:20 -05:00
|
|
|
using Poco::Thread;
|
|
|
|
using Poco::URI;
|
|
|
|
using Poco::Util::Application;
|
|
|
|
|
2016-04-14 09:45:46 -05:00
|
|
|
static bool closeExpected = false;
|
2016-04-20 10:31:16 -05:00
|
|
|
static std::mutex coutMutex;
|
2016-04-14 09:45:46 -05:00
|
|
|
|
2016-11-10 02:47:25 -06:00
|
|
|
/// Prints incoming data from a LOOLWebSocket.
|
2016-08-13 23:01:13 -05:00
|
|
|
class Output : public Runnable
|
2015-03-27 09:23:20 -05:00
|
|
|
{
|
|
|
|
public:
|
2016-11-10 02:47:25 -06:00
|
|
|
Output(LOOLWebSocket& ws) :
|
2015-03-27 09:23:20 -05:00
|
|
|
_ws(ws)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
void run() override
|
|
|
|
{
|
|
|
|
int flags;
|
|
|
|
int n;
|
|
|
|
try
|
|
|
|
{
|
|
|
|
do
|
|
|
|
{
|
2016-11-25 03:46:01 -06:00
|
|
|
char buffer[100000];
|
|
|
|
n = _ws.receiveFrame(buffer, sizeof(buffer), flags);
|
2016-02-23 12:03:43 -06:00
|
|
|
if (n > 0 && (flags & WebSocket::FRAME_OP_BITMASK) != WebSocket::FRAME_OP_CLOSE)
|
2015-03-27 09:23:20 -05:00
|
|
|
{
|
2016-04-20 10:31:16 -05:00
|
|
|
{
|
|
|
|
std::unique_lock<std::mutex> lock(coutMutex);
|
2016-11-25 03:46:01 -06:00
|
|
|
std::cout << "Got " << getAbbreviatedFrameDump(buffer, n, flags) << std::endl;
|
2016-04-20 10:31:16 -05:00
|
|
|
}
|
2015-04-14 09:50:38 -05:00
|
|
|
|
2016-11-25 03:46:01 -06:00
|
|
|
std::string firstLine = getFirstLine(buffer, n);
|
2015-04-14 09:50:38 -05:00
|
|
|
StringTokenizer tokens(firstLine, " ", StringTokenizer::TOK_IGNORE_EMPTY | StringTokenizer::TOK_TRIM);
|
2016-02-29 06:25:12 -06:00
|
|
|
|
2015-04-24 10:18:56 -05:00
|
|
|
if (std::getenv("DISPLAY") != nullptr && tokens[0] == "tile:")
|
2015-04-14 09:50:38 -05:00
|
|
|
{
|
|
|
|
TemporaryFile pngFile;
|
|
|
|
std::ofstream pngStream(pngFile.path(), std::ios::binary);
|
2016-11-25 03:46:01 -06:00
|
|
|
pngStream.write(buffer + firstLine.size() + 1, n - firstLine.size() - 1);
|
2015-04-14 09:50:38 -05:00
|
|
|
pngStream.close();
|
|
|
|
if (std::system((std::string("display ") + pngFile.path()).c_str()) == -1)
|
|
|
|
{
|
|
|
|
// Not worth it to display a warning, this is just a throwaway test program, and
|
|
|
|
// the developer running it surely notices if nothing shows up...
|
|
|
|
}
|
|
|
|
}
|
2015-03-27 09:23:20 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
while (n > 0 && (flags & WebSocket::FRAME_OP_BITMASK) != WebSocket::FRAME_OP_CLOSE);
|
2016-04-20 10:31:16 -05:00
|
|
|
|
|
|
|
{
|
|
|
|
std::unique_lock<std::mutex> lock(coutMutex);
|
|
|
|
std::cout << "CLOSE frame received" << std::endl;
|
|
|
|
}
|
2016-04-14 09:45:46 -05:00
|
|
|
if (!closeExpected)
|
|
|
|
std::_Exit(Application::EXIT_SOFTWARE);
|
2015-03-27 09:23:20 -05:00
|
|
|
}
|
|
|
|
catch (WebSocketException& exc)
|
|
|
|
{
|
2016-04-20 10:31:16 -05:00
|
|
|
std::unique_lock<std::mutex> lock(coutMutex);
|
2016-04-01 09:07:33 -05:00
|
|
|
std::cout << "Got exception " << exc.message() << std::endl;
|
2015-03-27 09:23:20 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-11-10 02:47:25 -06:00
|
|
|
LOOLWebSocket& _ws;
|
2015-03-27 09:23:20 -05:00
|
|
|
};
|
|
|
|
|
2016-08-13 23:01:13 -05:00
|
|
|
/// Program for interactive or scripted testing of a lool server.
|
2015-03-27 09:23:20 -05:00
|
|
|
class Connect: public Poco::Util::Application
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
Connect() :
|
2016-04-14 05:42:12 -05:00
|
|
|
#if ENABLE_SSL
|
2016-03-22 13:06:44 -05:00
|
|
|
_uri("https://127.0.0.1:" + std::to_string(DEFAULT_CLIENT_PORT_NUMBER) + "/ws")
|
2016-04-08 04:24:52 -05:00
|
|
|
#else
|
|
|
|
_uri("http://127.0.0.1:" + std::to_string(DEFAULT_CLIENT_PORT_NUMBER) + "/ws")
|
|
|
|
#endif
|
2015-03-27 09:23:20 -05:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
~Connect()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
protected:
|
|
|
|
int main(const std::vector<std::string>& args) override
|
|
|
|
{
|
2016-03-22 13:06:44 -05:00
|
|
|
if (args.size() < 1)
|
|
|
|
{
|
2016-12-19 17:28:26 -06:00
|
|
|
LOG_ERR("Usage: connect documentURI [serverURI]");
|
2016-03-22 13:06:44 -05:00
|
|
|
return Application::EXIT_USAGE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (args.size() > 1)
|
|
|
|
_uri = URI(args[1]);
|
|
|
|
|
2016-04-14 05:42:12 -05:00
|
|
|
#if ENABLE_SSL
|
2016-03-22 13:06:44 -05:00
|
|
|
Poco::Net::initializeSSL();
|
|
|
|
|
|
|
|
SharedPtr<InvalidCertificateHandler> invalidCertHandler = new AcceptCertificateHandler(false);
|
|
|
|
Context::Params sslParams;
|
|
|
|
Context::Ptr sslContext = new Poco::Net::Context(Poco::Net::Context::CLIENT_USE, sslParams);
|
|
|
|
SSLManager::instance().initializeClient(0, invalidCertHandler, sslContext);
|
2015-05-27 08:27:52 -05:00
|
|
|
|
2016-03-22 13:06:44 -05:00
|
|
|
HTTPSClientSession cs(_uri.getHost(), _uri.getPort());
|
2016-04-08 04:24:52 -05:00
|
|
|
#else
|
|
|
|
HTTPClientSession cs(_uri.getHost(), _uri.getPort());
|
|
|
|
#endif
|
2016-10-18 04:29:05 -05:00
|
|
|
std::string encodedUri;
|
|
|
|
URI::encode(args[0], ":/?", encodedUri);
|
|
|
|
HTTPRequest request(HTTPRequest::HTTP_GET, "/lool/" + encodedUri + "/ws");
|
2015-03-27 09:23:20 -05:00
|
|
|
HTTPResponse response;
|
2016-11-10 02:47:25 -06:00
|
|
|
LOOLWebSocket ws(cs, request, response);
|
2015-03-27 09:23:20 -05:00
|
|
|
|
2015-03-27 09:53:33 -05:00
|
|
|
ws.setReceiveTimeout(0);
|
|
|
|
|
2015-03-27 09:23:20 -05:00
|
|
|
Thread thread;
|
|
|
|
Output output(ws);
|
|
|
|
thread.start(output);
|
|
|
|
|
2016-04-01 09:07:33 -05:00
|
|
|
while (true)
|
2015-03-27 09:23:20 -05:00
|
|
|
{
|
|
|
|
std::string line;
|
|
|
|
std::getline(std::cin, line);
|
2016-04-01 09:07:33 -05:00
|
|
|
if (std::cin.eof())
|
2015-04-13 06:50:17 -05:00
|
|
|
{
|
2016-04-01 09:07:33 -05:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
else if (line.find("sleep ") == 0)
|
|
|
|
{
|
|
|
|
// Accept an input line "sleep <n>" that makes us sleep a number of seconds.
|
2015-04-13 06:50:17 -05:00
|
|
|
long sleepTime = std::stol(line.substr(std::string("sleep").length()));
|
2016-04-20 10:31:16 -05:00
|
|
|
{
|
|
|
|
std::unique_lock<std::mutex> lock(coutMutex);
|
|
|
|
std::cout << "Sleeping " << sleepTime << " seconds" << std::endl;
|
|
|
|
}
|
2016-09-17 08:48:39 -05:00
|
|
|
|
|
|
|
std::this_thread::sleep_for(std::chrono::seconds(sleepTime));
|
2015-04-13 06:50:17 -05:00
|
|
|
}
|
2016-04-18 13:09:36 -05:00
|
|
|
else if (line == "exit")
|
|
|
|
{
|
|
|
|
// While hacking on LOOL and editing input files for this program back and forth it
|
|
|
|
// is a good idea to be able to add an enforced exit in the middle of the input
|
|
|
|
// file.
|
2016-04-20 10:31:16 -05:00
|
|
|
{
|
|
|
|
std::unique_lock<std::mutex> lock(coutMutex);
|
|
|
|
std::cout << "Exiting" << std::endl;
|
|
|
|
}
|
2016-04-18 13:09:36 -05:00
|
|
|
break;
|
|
|
|
}
|
2016-04-27 07:58:33 -05:00
|
|
|
else if (line.find('#') == 0)
|
2016-04-18 13:09:36 -05:00
|
|
|
{
|
|
|
|
// Also comments can be useful in input files for this program
|
|
|
|
}
|
2015-04-13 06:50:17 -05:00
|
|
|
else
|
2016-04-01 09:07:33 -05:00
|
|
|
{
|
2016-04-20 10:31:16 -05:00
|
|
|
{
|
|
|
|
std::unique_lock<std::mutex> lock(coutMutex);
|
|
|
|
std::cout << "Sending: '" << line << "'" << std::endl;
|
|
|
|
}
|
2015-04-13 06:50:17 -05:00
|
|
|
ws.sendFrame(line.c_str(), line.size());
|
2016-04-01 09:07:33 -05:00
|
|
|
}
|
2015-03-27 09:23:20 -05:00
|
|
|
}
|
|
|
|
|
2016-04-20 10:31:16 -05:00
|
|
|
{
|
|
|
|
std::unique_lock<std::mutex> lock(coutMutex);
|
|
|
|
std::cout << "Shutting down websocket" << std::endl;
|
|
|
|
}
|
2016-04-14 09:45:46 -05:00
|
|
|
closeExpected = true;
|
2016-04-01 09:07:33 -05:00
|
|
|
ws.shutdown();
|
2015-03-27 09:23:20 -05:00
|
|
|
thread.join();
|
|
|
|
|
|
|
|
return Application::EXIT_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
URI _uri;
|
|
|
|
};
|
|
|
|
|
2016-09-28 14:07:07 -05:00
|
|
|
namespace Util
|
|
|
|
{
|
|
|
|
|
|
|
|
void alertAllUsers(const std::string& cmd, const std::string& kind)
|
|
|
|
{
|
|
|
|
std::cout << "error: cmd=" << cmd << " kind=" << kind << std::endl;
|
|
|
|
(void) kind;
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2015-03-27 09:23:20 -05:00
|
|
|
POCO_APP_MAIN(Connect)
|
|
|
|
|
|
|
|
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|