mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
116 lines
3.3 KiB
C++
116 lines
3.3 KiB
C++
/*
|
|
This file is part of solidity.
|
|
|
|
solidity is free software: you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation, either version 3 of the License, or
|
|
(at your option) any later version.
|
|
|
|
solidity is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with solidity. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
// SPDX-License-Identifier: GPL-3.0
|
|
#include <solc/LSPTCPTransport.h>
|
|
|
|
#include <libsolutil/JSON.h>
|
|
#include <fmt/format.h>
|
|
|
|
#include <optional>
|
|
#include <string>
|
|
#include <iostream>
|
|
|
|
namespace solidity::lsp
|
|
{
|
|
|
|
using std::function;
|
|
using std::nullopt;
|
|
using std::optional;
|
|
using std::string_view;
|
|
using std::to_string;
|
|
|
|
using namespace std::string_literals;
|
|
|
|
LSPTCPTransport::LSPTCPTransport(unsigned short _port, Trace _traceLevel, function<void(string_view)> _trace):
|
|
m_io_service(),
|
|
m_endpoint(boost::asio::ip::make_address("127.0.0.1"), _port),
|
|
m_acceptor(m_io_service),
|
|
m_stream(),
|
|
m_jsonTransport(),
|
|
m_traceLevel{_traceLevel},
|
|
m_trace(_trace ? std::move(_trace) : [](string_view) {})
|
|
{
|
|
m_acceptor.open(m_endpoint.protocol());
|
|
m_acceptor.set_option(boost::asio::ip::tcp::acceptor::reuse_address(true));
|
|
m_acceptor.bind(m_endpoint);
|
|
m_acceptor.listen();
|
|
|
|
if (m_traceLevel >= Trace::Messages)
|
|
m_trace("Listening on tcp://127.0.0.1:"s + to_string(_port));
|
|
}
|
|
|
|
void LSPTCPTransport::setTraceLevel(Trace _traceLevel)
|
|
{
|
|
m_traceLevel = _traceLevel;
|
|
|
|
if (m_jsonTransport)
|
|
m_jsonTransport->setTraceLevel(_traceLevel);
|
|
}
|
|
|
|
bool LSPTCPTransport::closed() const noexcept
|
|
{
|
|
return !m_acceptor.is_open();
|
|
}
|
|
|
|
optional<Json::Value> LSPTCPTransport::receive()
|
|
{
|
|
auto const clientClosed = [&]() { return !m_stream || !m_stream.value().good() || m_stream.value().eof(); };
|
|
|
|
if (clientClosed())
|
|
{
|
|
m_stream.emplace(m_acceptor.accept());
|
|
if (clientClosed())
|
|
return nullopt;
|
|
|
|
auto const remoteAddr = m_stream.value().socket().remote_endpoint().address().to_string();
|
|
auto const remotePort = m_stream.value().socket().remote_endpoint().port();
|
|
m_trace("New client connected from "s + remoteAddr + ":" + to_string(remotePort) + ".");
|
|
m_jsonTransport.emplace(m_stream.value(), m_stream.value(), m_traceLevel, [this](auto msg) { m_trace(msg); });
|
|
}
|
|
if (auto value = m_jsonTransport.value().receive(); value.has_value())
|
|
return value;
|
|
|
|
if (clientClosed())
|
|
{
|
|
m_trace("Client disconnected.");
|
|
m_jsonTransport.reset();
|
|
m_stream.reset();
|
|
}
|
|
return nullopt;
|
|
}
|
|
|
|
void LSPTCPTransport::notify(std::string const& _method, Json::Value const& _params)
|
|
{
|
|
if (m_jsonTransport.has_value())
|
|
m_jsonTransport.value().notify(_method, _params);
|
|
}
|
|
|
|
void LSPTCPTransport::reply(MessageID _id, Json::Value const& _result)
|
|
{
|
|
fmt::print("reply: {}\n{}\n", util::jsonPrettyPrint(_id), util::jsonPrettyPrint(_result));
|
|
if (m_jsonTransport.has_value())
|
|
m_jsonTransport.value().reply(_id, _result);
|
|
}
|
|
|
|
void LSPTCPTransport::error(MessageID _id, ErrorCode _code, std::string const& _message)
|
|
{
|
|
if (m_jsonTransport.has_value())
|
|
m_jsonTransport.value().error(_id, _code, _message);
|
|
}
|
|
|
|
}
|