libreoffice-online/tools/Connect.cpp

244 lines
7.4 KiB
C++
Raw Normal View History

/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
/*
* 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/.
*/
#include <config.h>
2016-04-08 06:49:33 -05:00
#include <cstdlib>
#include <cstring>
#include <fstream>
#include <iostream>
#include <mutex>
#include <sysexits.h>
#include <thread>
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>
#include <Poco/Net/HTTPRequest.h>
#include <Poco/Net/HTTPResponse.h>
#include <Poco/Net/HTTPSClientSession.h>
2016-03-22 13:06:44 -05:00
#include <Poco/Net/InvalidCertificateHandler.h>
#include <Poco/Net/NetException.h>
2016-03-22 13:06:44 -05:00
#include <Poco/Net/SSLManager.h>
#include <Poco/SharedPtr.h>
#include <Poco/TemporaryFile.h>
#include <Poco/URI.h>
#include <Poco/Util/Application.h>
#include <Common.hpp>
#include <Protocol.hpp>
#include <LOOLWebSocket.hpp>
#include <Log.hpp>
#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
using Poco::Net::HTTPRequest;
using Poco::Net::HTTPResponse;
2016-03-22 13:06:44 -05:00
using Poco::Net::InvalidCertificateHandler;
using Poco::Net::SSLManager;
using Poco::Net::WebSocket;
using Poco::Net::WebSocketException;
using Poco::Runnable;
2016-03-22 13:06:44 -05:00
using Poco::SharedPtr;
using Poco::TemporaryFile;
using Poco::URI;
using Poco::Util::Application;
static bool closeExpected = false;
static std::mutex coutMutex;
/// Prints incoming data from a LOOLWebSocket.
class Output : public Runnable
{
public:
Output(LOOLWebSocket& ws) :
_ws(ws)
{
}
void run() override
{
int flags;
int n;
try
{
do
{
char buffer[100000];
n = _ws.receiveFrame(buffer, sizeof(buffer), flags);
if (n > 0 && (flags & WebSocket::FRAME_OP_BITMASK) != WebSocket::FRAME_OP_CLOSE)
{
{
std::unique_lock<std::mutex> lock(coutMutex);
std::cout << "Got " << LOOLWebSocket::getAbbreviatedFrameDump(buffer, n, flags) << std::endl;
}
std::string firstLine = getFirstLine(buffer, n);
StringVector tokens(LOOLProtocol::tokenize(firstLine, ' '));
if (std::getenv("DISPLAY") != nullptr && tokens.equals(0, "tile:"))
{
TemporaryFile pngFile;
std::ofstream pngStream(pngFile.path(), std::ios::binary);
pngStream.write(buffer + firstLine.size() + 1, n - firstLine.size() - 1);
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...
}
}
}
}
while (n > 0 && (flags & WebSocket::FRAME_OP_BITMASK) != WebSocket::FRAME_OP_CLOSE);
{
std::unique_lock<std::mutex> lock(coutMutex);
std::cout << "CLOSE frame received" << std::endl;
}
if (!closeExpected)
std::_Exit(EX_SOFTWARE);
}
catch (WebSocketException& exc)
{
std::unique_lock<std::mutex> lock(coutMutex);
2016-04-01 09:07:33 -05:00
std::cout << "Got exception " << exc.message() << std::endl;
}
}
private:
LOOLWebSocket& _ws;
};
/// Program for interactive or scripted testing of a lool server.
class Connect: public Poco::Util::Application
{
public:
Connect() :
#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
{
}
protected:
int main(const std::vector<std::string>& args) override
{
2016-03-22 13:06:44 -05:00
if (args.size() < 1)
{
LOG_ERR("Usage: connect documentURI [serverURI]");
return EX_USAGE;
2016-03-22 13:06:44 -05:00
}
if (args.size() > 1)
_uri = URI(args[1]);
#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(nullptr, 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
std::string encodedUri;
URI::encode(args[0], ":/?", encodedUri);
HTTPRequest request(HTTPRequest::HTTP_GET, "/lool/" + encodedUri + "/ws");
HTTPResponse response;
LOOLWebSocket ws(cs, request, response);
2015-03-27 09:53:33 -05:00
ws.setReceiveTimeout(0);
std::thread thread([&ws]{Output(ws).run();});
2016-04-01 09:07:33 -05:00
while (true)
{
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()));
{
std::unique_lock<std::mutex> lock(coutMutex);
std::cout << "Sleeping " << sleepTime << " seconds" << std::endl;
}
std::this_thread::sleep_for(std::chrono::seconds(sleepTime));
2015-04-13 06:50:17 -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.
{
std::unique_lock<std::mutex> lock(coutMutex);
std::cout << "Exiting" << std::endl;
}
break;
}
else if (line.find('#') == 0)
{
// 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
{
{
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
}
}
{
std::unique_lock<std::mutex> lock(coutMutex);
std::cout << "Shutting down websocket" << std::endl;
}
closeExpected = true;
2016-04-01 09:07:33 -05:00
ws.shutdown();
thread.join();
return EX_OK;
}
private:
URI _uri;
};
namespace Util
{
void alertAllUsers(const std::string& cmd, const std::string& kind)
{
std::cout << "error: cmd=" << cmd << " kind=" << kind << std::endl;
}
}
POCO_APP_MAIN(Connect)
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */