diff --git a/src/inspector/inspector_socket.cpp b/src/inspector/inspector_socket.cpp new file mode 100644 index 0000000000000000000000000000000000000000..47527a73194df180e825f5f3538ff93aa4dd4dfb --- /dev/null +++ b/src/inspector/inspector_socket.cpp @@ -0,0 +1,826 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "inspector_socket.h" + +#include +#include +#include + +#include "inspector/inspector_utils.h" +#include "llhttp.h" +#include "openssl/sha.h" // Sha-1 hash + +#define ACCEPT_KEY_LENGTH Base64EncodeSize(20) + +namespace jsvm { +namespace inspector { + +class TcpHolder { +public: + static void DisconnectAndDispose(TcpHolder* holder); + using Pointer = DeleteFnPtr; + + static Pointer Accept(uv_stream_t* server, InspectorSocket::DelegatePointer delegate); + void SetHandler(ProtocolHandler* handler); + int WriteRaw(const std::vector& buffer, uv_write_cb writeCb); + uv_tcp_t* GetTcp() + { + return &tcp; + } + InspectorSocket::Delegate* GetDelegate(); + +private: + static TcpHolder* From(void* handle) + { + return jsvm::inspector::ContainerOf(&TcpHolder::tcp, reinterpret_cast(handle)); + } + static void OnClosed(uv_handle_t* handle); + static void OnDataReceivedCb(uv_stream_t* stream, ssize_t nread, const uv_buf_t* buf); + explicit TcpHolder(InspectorSocket::DelegatePointer delegate); + ~TcpHolder() = default; + void ReclaimUvBuf(const uv_buf_t* buf, ssize_t read); + + uv_tcp_t tcp; + const InspectorSocket::DelegatePointer delegate; + ProtocolHandler* handler; + std::vector buffer; +}; + +class ProtocolHandler { +public: + ProtocolHandler(InspectorSocket* inspector, TcpHolder::Pointer tcp); + + virtual void AcceptUpgrade(const std::string& acceptKey) = 0; + virtual void OnData(std::vector* data) = 0; + virtual void OnEof() = 0; + virtual void Write(const std::vector data) = 0; + virtual void CancelHandshake() = 0; + + std::string GetHost() const; + + InspectorSocket* GetInspectorSocket() + { + return inspector; + } + virtual void Shutdown() = 0; + +protected: + virtual ~ProtocolHandler() = default; + int WriteRaw(const std::vector& buffer, uv_write_cb writeCb); + InspectorSocket::Delegate* GetDelegate(); + + InspectorSocket* const inspector; + TcpHolder::Pointer tcp; +}; + +namespace { +class WriteRequest { +public: + WriteRequest(ProtocolHandler* handler, const std::vector& buffer) + : handler(handler), storage(buffer), req(uv_write_t()), buf(uv_buf_init(storage.data(), storage.size())) + {} + + static WriteRequest* FromWriteReq(uv_write_t* req) + { + return jsvm::inspector::ContainerOf(&WriteRequest::req, req); + } + + static void Cleanup(uv_write_t* req, int status) + { + delete WriteRequest::FromWriteReq(req); + } + + ProtocolHandler* const handler; + std::vector storage; + uv_write_t req; + uv_buf_t buf; +}; + +void AllocateBuffer(uv_handle_t* stream, size_t len, uv_buf_t* buf) +{ + CHECK(len > 0); + *buf = uv_buf_init(new char[len], len); +} + +static void RemoveFromBeginning(std::vector* buffer, size_t count) +{ + buffer->erase(buffer->begin(), buffer->begin() + count); +} + +static const char CLOSE_FRAME[] = { '\x88', '\x00' }; + +enum WsDecodeResult { FRAME_OK, FRAME_INCOMPLETE, FRAME_CLOSE, FRAME_ERROR }; + +static void GenerateAcceptString(const std::string& clientKey, char (*buffer)[ACCEPT_KEY_LENGTH]) +{ + // Magic string from websockets spec. + static constexpr char wsMagic[] = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"; + std::string input(clientKey + wsMagic); + char hash[SHA_DIGEST_LENGTH]; + USE(SHA1(reinterpret_cast(input.data()), input.size(), + reinterpret_cast(hash))); + jsvm::inspector::Base64Encode(hash, sizeof(hash), *buffer, sizeof(*buffer)); +} + +static std::string TrimPort(const std::string& host) +{ + size_t lastColonPos = host.rfind(':'); + if (lastColonPos == std::string::npos) { + return host; + } + size_t bracket = host.rfind(']'); + if (bracket == std::string::npos || lastColonPos > bracket) { + return host.substr(0, lastColonPos); + } + return host; +} + +static bool IsIPAddress(const std::string& host) +{ + // To avoid DNS rebinding attacks, we are aware of the following requirements: + // * the host name must be an IP address (CVE-2018-7160, CVE-2022-32212), + // * the IP address must be routable (hackerone.com/reports/1632921), and + // * the IP address must be formatted unambiguously (CVE-2022-43548). + + // The logic below assumes that the string is null-terminated, so ensure that + // we did not somehow end up with null characters within the string. + if (host.find('\0') != std::string::npos) { + return false; + } + + // All IPv6 addresses must be enclosed in square brackets, and anything + // enclosed in square brackets must be an IPv6 address. + if (host.length() >= 4 && host.front() == '[' && host.back() == ']') { + // INET6_ADDRSTRLEN is the maximum length of the dual format (including the + // terminating null character), which is the longest possible representation + // of an IPv6 address: xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:ddd.ddd.ddd.ddd + if (host.length() - 2 >= INET6_ADDRSTRLEN) { + return false; + } + + // Annoyingly, libuv's implementation of inet_pton() deviates from other + // implementations of the function in that it allows '%' in IPv6 addresses. + if (host.find('%') != std::string::npos) { + return false; + } + + // Parse the IPv6 address to ensure it is syntactically valid. + char ipv6Str[INET6_ADDRSTRLEN]; + std::copy(host.begin() + 1, host.end() - 1, ipv6Str); + ipv6Str[host.length()] = '\0'; + unsigned char ipv6[sizeof(struct in6_addr)]; + if (uv_inet_pton(AF_INET6, ipv6Str, ipv6) != 0) { + return false; + } + + // The only non-routable IPv6 address is ::/128. It should not be necessary + // to explicitly reject it because it will still be enclosed in square + // brackets and not even macOS should make DNS requests in that case, but + // history has taught us that we cannot be careful enough. + // Note that RFC 4291 defines both "IPv4-Compatible IPv6 Addresses" and + // "IPv4-Mapped IPv6 Addresses", which means that there are IPv6 addresses + // (other than ::/128) that represent non-routable IPv4 addresses. However, + // this translation assumes that the host is interpreted as an IPv6 address + // in the first place, at which point DNS rebinding should not be an issue. + if (std::all_of(ipv6, ipv6 + sizeof(ipv6), [](auto b) { return b == 0; })) { + return false; + } + + // It is a syntactically valid and routable IPv6 address enclosed in square + // brackets. No client should be able to misinterpret this. + return true; + } + + // Anything not enclosed in square brackets must be an IPv4 address. It is + // important here that inet_pton() accepts only the so-called dotted-decimal + // notation, which is a strict subset of the so-called numbers-and-dots + // notation that is allowed by inet_aton() and inet_addr(). This subset does + // not allow hexadecimal or octal number formats. + unsigned char ipv4[sizeof(struct in_addr)]; + if (uv_inet_pton(AF_INET, host.c_str(), ipv4) != 0) { + return false; + } + + if (ipv4[0] == 0) { + return false; + } + + // It is a routable IPv4 address in dotted-decimal notation. + return true; +} + +// Constants for hybi-10 frame format. + +typedef int OpCode; + +const OpCode K_OP_CODE_CONTINUATION = 0x0; +const OpCode K_OP_CODE_TEXT = 0x1; +const OpCode K_OP_CODE_BINARY = 0x2; +const OpCode K_OP_CODE_CLOSE = 0x8; +const OpCode K_OP_CODE_PING = 0x9; +const OpCode K_OP_CODE_PONG = 0xA; + +const unsigned char K_FINAL_BIT = 0x80; +const unsigned char K_RESERVED_1_BIT = 0x40; +const unsigned char K_RESERVED_2_BIT = 0x20; +const unsigned char K_RESERVED_3_BIT = 0x10; +const unsigned char K_OP_CODE_MASK = 0xF; +const unsigned char K_MASK_BIT = 0x80; +const unsigned char K_PAYLOAD_LENGTH_MASK = 0x7F; + +const size_t K_MAX_SINGLE_BYTE_PAYLOAD_LENGTH = 125; +const size_t K_TWO_BYTE_PAYLOAD_LENGTH_FIELD = 126; +const size_t K_EIGHT_BYTE_PAYLOAD_LENGTH_FIELD = 127; +const size_t K_MASKING_KEY_WIDTH_IN_BYTES = 4; + +static std::vector encode_frame_hybi17(const std::vector& message) +{ + std::vector frame; + OpCode opCode = K_OP_CODE_TEXT; + frame.push_back(K_FINAL_BIT | opCode); + const size_t dataLength = message.size(); + if (dataLength <= K_MAX_SINGLE_BYTE_PAYLOAD_LENGTH) { + frame.push_back(static_cast(dataLength)); + } else if (dataLength <= 0xFFFF) { + frame.push_back(K_TWO_BYTE_PAYLOAD_LENGTH_FIELD); + frame.push_back((dataLength & 0xFF00) >> 8); + frame.push_back(dataLength & 0xFF); + } else { + frame.push_back(K_EIGHT_BYTE_PAYLOAD_LENGTH_FIELD); + char extendedPayloadLength[8]; + size_t remaining = dataLength; + // Fill the length into extendedPayloadLength in the network byte order. + constexpr size_t byteCount = 8; + for (int i = 0; i < byteCount; ++i) { + extendedPayloadLength[7 - i] = remaining & 0xFF; + remaining >>= 8; + } + frame.insert(frame.end(), extendedPayloadLength, extendedPayloadLength + 8); + CHECK_EQ(0, remaining); + } + frame.insert(frame.end(), message.begin(), message.end()); + return frame; +} + +static WsDecodeResult DecodeFrameHybi17(const std::vector& buffer, + bool clientFrame, + int* bytesConsumed, + std::vector* output, + bool* compressed) +{ + *bytesConsumed = 0; + if (buffer.size() < 2) { + return FRAME_INCOMPLETE; + } + + auto it = buffer.begin(); + + unsigned char firstByte = *it++; + unsigned char secondByte = *it++; + + bool final = (firstByte & K_FINAL_BIT) != 0; + bool reserved1 = (firstByte & K_RESERVED_1_BIT) != 0; + bool reserved2 = (firstByte & K_RESERVED_2_BIT) != 0; + bool reserved3 = (firstByte & K_RESERVED_3_BIT) != 0; + int opCode = firstByte & K_OP_CODE_MASK; + bool masked = (secondByte & K_MASK_BIT) != 0; + *compressed = reserved1; + if (!final || reserved2 || reserved3) { + return FRAME_ERROR; // Only compression extension is supported. + } + + bool closed = false; + switch (opCode) { + case K_OP_CODE_CLOSE: + closed = true; + break; + case K_OP_CODE_TEXT: + break; + case K_OP_CODE_BINARY: // We don't support binary frames yet. + case K_OP_CODE_CONTINUATION: // We don't support binary frames yet. + case K_OP_CODE_PING: // We don't support binary frames yet. + case K_OP_CODE_PONG: // We don't support binary frames yet. + default: + return FRAME_ERROR; + } + + // In Hybi-17 spec client MUST mask its frame. + if (clientFrame && !masked) { + return FRAME_ERROR; + } + + uint64_t payloadLength64 = secondByte & K_PAYLOAD_LENGTH_MASK; + if (payloadLength64 > K_MAX_SINGLE_BYTE_PAYLOAD_LENGTH) { + int extendedPayloadLengthSize; + if (payloadLength64 == K_TWO_BYTE_PAYLOAD_LENGTH_FIELD) { + extendedPayloadLengthSize = 2; + } else if (payloadLength64 == K_EIGHT_BYTE_PAYLOAD_LENGTH_FIELD) { + extendedPayloadLengthSize = 8; + } else { + return FRAME_ERROR; + } + if ((buffer.end() - it) < extendedPayloadLengthSize) { + return FRAME_INCOMPLETE; + } + payloadLength64 = 0; + for (int i = 0; i < extendedPayloadLengthSize; ++i) { + payloadLength64 <<= 8; + payloadLength64 |= static_cast(*it++); + } + } + + static const uint64_t maxPayloadLength = 0x7FFFFFFFFFFFFFFF; + static const size_t maxLength = SIZE_MAX; + if (payloadLength64 > maxPayloadLength || payloadLength64 > maxLength - K_MASKING_KEY_WIDTH_IN_BYTES) { + // WebSocket frame length too large. + return FRAME_ERROR; + } + size_t payloadLength = static_cast(payloadLength64); + + if (buffer.size() - K_MASKING_KEY_WIDTH_IN_BYTES < payloadLength) { + return FRAME_INCOMPLETE; + } + + std::vector::const_iterator maskingKey = it; + std::vector::const_iterator payload = it + K_MASKING_KEY_WIDTH_IN_BYTES; + for (size_t i = 0; i < payloadLength; ++i) { // Unmask the payload. + output->insert(output->end(), payload[i] ^ maskingKey[i % K_MASKING_KEY_WIDTH_IN_BYTES]); + } + + size_t pos = it + K_MASKING_KEY_WIDTH_IN_BYTES + payloadLength - buffer.begin(); + *bytesConsumed = pos; + return closed ? FRAME_CLOSE : FRAME_OK; +} + +// WS protocol +class WsHandler : public ProtocolHandler { +public: + WsHandler(InspectorSocket* inspector, TcpHolder::Pointer tcp) + : ProtocolHandler(inspector, std::move(tcp)), onCloseSent(&WsHandler::WaitForCloseReply), + onCloseReceived(&WsHandler::CloseFrameReceived), dispose(false) + {} + + void AcceptUpgrade(const std::string& acceptKey) override {} + void CancelHandshake() override {} + + void OnEof() override + { + tcp.reset(); + if (dispose) { + delete this; + } + } + + void Write(const std::vector data) override + { + std::vector output = encode_frame_hybi17(data); + WriteRaw(output, WriteRequest::Cleanup); + } + + void OnData(std::vector* data) override + { + // 1. Parse. + int processed = 0; + do { + processed = ParseWsFrames(*data); + // 2. Fix the data size & length + if (processed > 0) { + RemoveFromBeginning(data, processed); + } + } while (processed > 0 && !data->empty()); + } + +protected: + void Shutdown() override + { + if (tcp) { + dispose = true; + SendClose(); + } else { + // if tcp is null, delete this + delete this; + } + } + +private: + using Callback = void (WsHandler::*)(); + + static void OnCloseFrameWritten(uv_write_t* req, int status) + { + WriteRequest* wr = WriteRequest::FromWriteReq(req); + WsHandler* handler = static_cast(wr->handler); + delete wr; + Callback cb = handler->onCloseSent; + (handler->*cb)(); + } + + void WaitForCloseReply() + { + onCloseReceived = &WsHandler::OnEof; + } + + void SendClose() + { + WriteRaw(std::vector(CLOSE_FRAME, CLOSE_FRAME + sizeof(CLOSE_FRAME)), OnCloseFrameWritten); + } + + void CloseFrameReceived() + { + onCloseSent = &WsHandler::OnEof; + SendClose(); + } + + int ParseWsFrames(const std::vector& buffer) + { + int bytesConsumed = 0; + std::vector output; + bool compressed = false; + + WsDecodeResult r = DecodeFrameHybi17(buffer, true /* clientFrame */, &bytesConsumed, &output, &compressed); + // Compressed frame means client is ignoring the headers and misbehaves + if (compressed || r == FRAME_ERROR) { + OnEof(); + bytesConsumed = 0; + } else if (r == FRAME_CLOSE) { + (this->*onCloseReceived)(); + bytesConsumed = 0; + } else if (r == FRAME_OK) { + GetDelegate()->OnWsFrame(output); + } + return bytesConsumed; + } + + Callback onCloseSent; + Callback onCloseReceived; + bool dispose; +}; + +// HTTP protocol +class HttpEvent { +public: + HttpEvent(const std::string& path, bool upgrade, bool isGET, const std::string& wsKey, const std::string& host) + : path(path), upgrade(upgrade), isGET(isGET), wsKey(wsKey), host(host) + {} + + std::string path; + bool upgrade; + bool isGET; + std::string wsKey; + std::string host; +}; + +class HttpHandler : public ProtocolHandler { +public: + explicit HttpHandler(InspectorSocket* inspector, TcpHolder::Pointer tcp) + : ProtocolHandler(inspector, std::move(tcp)), parsingValue(false) + { + llhttp_init(&parser, HTTP_REQUEST, &parserSettings); + llhttp_settings_init(&parserSettings); + parserSettings.on_header_field = OnHeaderField; + parserSettings.on_header_value = OnHeaderValue; + parserSettings.on_message_complete = OnMessageComplete; + parserSettings.on_url = OnPath; + } + + void AcceptUpgrade(const std::string& acceptKey) override + { + char acceptString[ACCEPT_KEY_LENGTH]; + GenerateAcceptString(acceptKey, &acceptString); + const char acceptWsPrefix[] = "HTTP/1.1 101 Switching Protocols\r\n" + "Upgrade: websocket\r\n" + "Connection: Upgrade\r\n" + "Sec-WebSocket-Accept: "; + const char acceptWsSuffix[] = "\r\n\r\n"; + std::vector reply(acceptWsPrefix, acceptWsPrefix + sizeof(acceptWsPrefix) - 1); + reply.insert(reply.end(), acceptString, acceptString + sizeof(acceptString)); + reply.insert(reply.end(), acceptWsSuffix, acceptWsSuffix + sizeof(acceptWsSuffix) - 1); + if (WriteRaw(reply, WriteRequest::Cleanup) >= 0) { + inspector->SwitchProtocol(new WsHandler(inspector, std::move(tcp))); + } else { + tcp.reset(); + } + } + + void CancelHandshake() override + { + const char handshakeFailedResponse[] = "HTTP/1.0 400 Bad Request\r\n" + "Content-Type: text/html; charset=UTF-8\r\n\r\n" + "WebSockets request was expected\r\n"; + WriteRaw(std::vector(handshakeFailedResponse, + handshakeFailedResponse + sizeof(handshakeFailedResponse) - 1), + ThenCloseAndReportFailure); + } + + void OnEof() override + { + tcp.reset(); + } + + void Write(const std::vector data) override + { + WriteRaw(data, WriteRequest::Cleanup); + } + + void OnData(std::vector* data) override + { + llhttp_errno_t err = llhttp_execute(&parser, data->data(), data->size()); + if (err == HPE_PAUSED_UPGRADE) { + err = HPE_OK; + llhttp_resume_after_upgrade(&parser); + } + data->clear(); + if (err != HPE_OK) { + CancelHandshake(); + } + // Event handling may delete *this + std::vector httpEvents; + std::swap(httpEvents, events); + for (const HttpEvent& event : httpEvents) { + if (!IsAllowedHost(event.host) || !event.isGET) { + CancelHandshake(); + return; + } else if (!event.upgrade) { + GetDelegate()->OnHttpGet(event.host, event.path); + } else if (event.wsKey.empty()) { + CancelHandshake(); + return; + } else { + GetDelegate()->OnSocketUpgrade(event.host, event.path, event.wsKey); + } + } + } + +protected: + void Shutdown() override + { + delete this; + } + +private: + static void ThenCloseAndReportFailure(uv_write_t* req, int status) + { + ProtocolHandler* handler = WriteRequest::FromWriteReq(req)->handler; + WriteRequest::Cleanup(req, status); + handler->GetInspectorSocket()->SwitchProtocol(nullptr); + } + + static int OnHeaderValue(llhttp_t* parser, const char* at, size_t length) + { + HttpHandler* handler = From(parser); + handler->parsingValue = true; + handler->headers[handler->currentHeader].append(at, length); + return 0; + } + + static int OnHeaderField(llhttp_t* parser, const char* at, size_t length) + { + HttpHandler* handler = From(parser); + if (handler->parsingValue) { + handler->parsingValue = false; + handler->currentHeader.clear(); + } + handler->currentHeader.append(at, length); + return 0; + } + + static int OnPath(llhttp_t* parser, const char* at, size_t length) + { + HttpHandler* handler = From(parser); + handler->path.append(at, length); + return 0; + } + + static HttpHandler* From(llhttp_t* parser) + { + return jsvm::inspector::ContainerOf(&HttpHandler::parser, parser); + } + + static int OnMessageComplete(llhttp_t* parser) + { + // Event needs to be fired after the parser is done. + HttpHandler* handler = From(parser); + handler->events.emplace_back(handler->path, parser->upgrade, parser->method == HTTP_GET, + handler->HeaderValue("Sec-WebSocket-Key"), handler->HeaderValue("Host")); + handler->path = ""; + handler->parsingValue = false; + handler->headers.clear(); + handler->currentHeader = ""; + return 0; + } + + std::string HeaderValue(const std::string& header) const + { + bool headerFound = false; + std::string value; + for (const auto& header_value : headers) { + if (jsvm::inspector::StringEqualNoCaseN(header_value.first.data(), header.data(), header.length())) { + if (headerFound) { + return ""; + } + value = header_value.second; + headerFound = true; + } + } + return value; + } + + bool IsAllowedHost(const std::string& hostWithPort) const + { + std::string host = TrimPort(hostWithPort); + return host.empty() || IsIPAddress(host) || jsvm::inspector::StringEqualNoCase(host.data(), "localhost"); + } + + bool parsingValue; + llhttp_t parser; + llhttp_settings_t parserSettings; + std::vector events; + std::string currentHeader; + std::map headers; + std::string path; +}; + +} // namespace + +// Any protocol +ProtocolHandler::ProtocolHandler(InspectorSocket* inspector, TcpHolder::Pointer tcpParam) + : inspector(inspector), tcp(std::move(tcpParam)) +{ + CHECK_NOT_NULL(tcp); + tcp->SetHandler(this); +} + +int ProtocolHandler::WriteRaw(const std::vector& buffer, uv_write_cb writeCb) +{ + return tcp->WriteRaw(buffer, writeCb); +} + +InspectorSocket::Delegate* ProtocolHandler::GetDelegate() +{ + return tcp->GetDelegate(); +} + +std::string ProtocolHandler::GetHost() const +{ + char ip[INET6_ADDRSTRLEN]; + sockaddr_storage addr; + int len = sizeof(addr); + int err = uv_tcp_getsockname(tcp->GetTcp(), reinterpret_cast(&addr), &len); + if (err) { + return ""; + } + if (addr.ss_family == AF_INET6) { + // using ipv6 + const sockaddr_in6* v6 = reinterpret_cast(&addr); + err = uv_ip6_name(v6, ip, sizeof(ip)); + } else { + // using ipv4 + const sockaddr_in* v4 = reinterpret_cast(&addr); + err = uv_ip4_name(v4, ip, sizeof(ip)); + } + if (err) { + return ""; + } + return ip; +} + +// RAII uv_tcp_t wrapper +TcpHolder::TcpHolder(InspectorSocket::DelegatePointer delegate) : tcp(), delegate(std::move(delegate)), handler(nullptr) +{} + +// static +TcpHolder::Pointer TcpHolder::Accept(uv_stream_t* server, InspectorSocket::DelegatePointer delegate) +{ + TcpHolder* result = new TcpHolder(std::move(delegate)); + uv_stream_t* tcp = reinterpret_cast(&result->tcp); + int err = uv_tcp_init(server->loop, &result->tcp); + if (err == 0) { + err = uv_accept(server, tcp); + } + if (err == 0) { + err = uv_read_start(tcp, AllocateBuffer, OnDataReceivedCb); + } + if (err == 0) { + return TcpHolder::Pointer(result); + } else { + delete result; + return nullptr; + } +} + +void TcpHolder::SetHandler(ProtocolHandler* protocalHandler) +{ + handler = protocalHandler; +} + +int TcpHolder::WriteRaw(const std::vector& buffer, uv_write_cb writeCb) +{ + // Freed in write_request_cleanup + WriteRequest* wr = new WriteRequest(handler, buffer); + uv_stream_t* stream = reinterpret_cast(&tcp); + int err = uv_write(&wr->req, stream, &wr->buf, 1, writeCb); + if (err < 0) { + delete wr; + } + return err < 0; +} + +InspectorSocket::Delegate* TcpHolder::GetDelegate() +{ + return delegate.get(); +} + +// static +void TcpHolder::OnClosed(uv_handle_t* handle) +{ + delete From(handle); +} + +void TcpHolder::OnDataReceivedCb(uv_stream_t* tcp, ssize_t nread, const uv_buf_t* buf) +{ + TcpHolder* holder = From(tcp); + holder->ReclaimUvBuf(buf, nread); + if (nread < 0 || nread == UV_EOF) { + holder->handler->OnEof(); + } else { + holder->handler->OnData(&holder->buffer); + } +} + +// static +void TcpHolder::DisconnectAndDispose(TcpHolder* holder) +{ + uv_handle_t* handle = reinterpret_cast(&holder->tcp); + uv_close(handle, OnClosed); +} + +void TcpHolder::ReclaimUvBuf(const uv_buf_t* buf, ssize_t read) +{ + if (read > 0) { + // insert buffer + buffer.insert(buffer.end(), buf->base, buf->base + read); + } + delete[] buf->base; +} + +InspectorSocket::~InspectorSocket() = default; + +// static +void InspectorSocket::Shutdown(ProtocolHandler* handler) +{ + handler->Shutdown(); +} + +// static +InspectorSocket::Pointer InspectorSocket::Accept(uv_stream_t* server, DelegatePointer delegate) +{ + auto tcp = TcpHolder::Accept(server, std::move(delegate)); + InspectorSocket* inspector = nullptr; + if (tcp) { + // If accept tcp, create new inspector socket + inspector = new InspectorSocket(); + inspector->SwitchProtocol(new HttpHandler(inspector, std::move(tcp))); + return InspectorSocket::Pointer(inspector); + } + return InspectorSocket::Pointer(nullptr); +} + +void InspectorSocket::AcceptUpgrade(const std::string& acceptKey) +{ + protocolHandler->AcceptUpgrade(acceptKey); +} + +void InspectorSocket::CancelHandshake() +{ + protocolHandler->CancelHandshake(); +} + +std::string InspectorSocket::GetHost() +{ + return protocolHandler->GetHost(); +} + +void InspectorSocket::SwitchProtocol(ProtocolHandler* handler) +{ + protocolHandler.reset(std::move(handler)); +} + +void InspectorSocket::Write(const char* data, size_t len) +{ + protocolHandler->Write(std::vector(data, data + len)); +} + +} // namespace inspector +} // namespace jsvm diff --git a/src/inspector/inspector_socket.h b/src/inspector/inspector_socket.h new file mode 100644 index 0000000000000000000000000000000000000000..55080a7603d3cf32849313a65e5f01827f5caaab --- /dev/null +++ b/src/inspector/inspector_socket.h @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef SRC_INSPECTOR_SOCKET_H_ +#define SRC_INSPECTOR_SOCKET_H_ + +#include +#include + +#include "inspector_utils.h" +#include "uv.h" + +namespace jsvm { +namespace inspector { + +class ProtocolHandler; + +// HTTP Wrapper around a uv_tcp_t +class InspectorSocket { +private: + InspectorSocket() = default; +public: + using Pointer = std::unique_ptr; + + InspectorSocket(const InspectorSocket&) = delete; + + InspectorSocket& operator=(const InspectorSocket&) = delete; + + ~InspectorSocket(); + + class Delegate { + public: + virtual void OnWsFrame(const std::vector& frame) = 0; + virtual ~Delegate() = default; + virtual void OnHttpGet(const std::string& host, const std::string& path) = 0; + virtual void OnSocketUpgrade(const std::string& host, + const std::string& path, + const std::string& acceptKey) = 0; + }; + + using DelegatePointer = std::unique_ptr; + + static Pointer Accept(uv_stream_t* server, DelegatePointer delegate); + + void AcceptUpgrade(const std::string& acceptKey); + + void SwitchProtocol(ProtocolHandler* handler); + + void Write(const char* data, size_t len); + + void CancelHandshake(); + + std::string GetHost(); + +private: + static void Shutdown(ProtocolHandler* handler); + + DeleteFnPtr protocolHandler; +}; + +} // namespace inspector +} // namespace jsvm + +#endif // SRC_INSPECTOR_SOCKET_H_ diff --git a/src/inspector/inspector_socket_server.cpp b/src/inspector/inspector_socket_server.cpp new file mode 100644 index 0000000000000000000000000000000000000000..7cce8ad0bf7f6406932ef983900aaabf947ca3cc --- /dev/null +++ b/src/inspector/inspector_socket_server.cpp @@ -0,0 +1,637 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "inspector_socket_server.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "jsvm_version.h" +#include "uv.h" +#include "v8_inspector_protocol_json.h" +#include "zlib.h" + +namespace jsvm { +namespace inspector { + +// Function is declared in inspector_io.h so the rest of the node does not +// depend on inspector_socket_server.h +std::string FormatWsAddress(const std::string& host, int port, const std::string& targetId, bool includeProtocol); +namespace { +std::string FormatHostPort(const std::string& host, int port) +{ + // Host is valid (socket was bound) so colon means it's a v6 IP address + bool v6 = host.find(':') != std::string::npos; + std::ostringstream url; + if (v6) { + url << '['; + } + url << host; + if (v6) { + url << ']'; + } + url << ':' << port; + return url.str(); +} + +void Escape(std::string* string) +{ + for (char& c : *string) { + c = (c == '\"' || c == '\\') ? '_' : c; + } +} + +std::string FormatAddress(const std::string& host, const std::string& targetId, bool includeProtocol) +{ + std::ostringstream url; + if (includeProtocol) { + url << "ws://"; + } + url << host << '/' << targetId; + return url.str(); +} + +std::string MapToString(const std::map& object) +{ + bool first = true; + std::ostringstream json; + json << "{\n"; + for (const auto& nameValue : object) { + if (!first) { + json << ",\n"; + } + first = false; + json << " \"" << nameValue.first << "\": \""; + json << nameValue.second << "\""; + } + json << "\n} "; + return json.str(); +} + +std::string MapsToString(const std::vector>& array) +{ + bool isFirst = true; + std::ostringstream json; + json << "[ "; + for (const auto& object : array) { + if (!isFirst) { + json << ", "; + } + isFirst = false; + json << MapToString(object); + } + json << "]\n\n"; + return json.str(); +} + +void SendHttpResponse(InspectorSocket* socket, const std::string& response, int code) +{ + const char headers[] = "HTTP/1.0 %d OK\r\n" + "Content-Type: application/json; charset=UTF-8\r\n" + "Cache-Control: no-cache\r\n" + "Content-Length: %zu\r\n" + "\r\n"; + char header[sizeof(headers) + 20]; + int headerLen = snprintf_s(header, sizeof(header), sizeof(header) - 1, headers, code, response.size()); + CHECK(headerLen >= 0); + socket->Write(header, headerLen); + socket->Write(response.data(), response.size()); +} + +const char* MatchPathSegment(const char* path, const char* expected) +{ + size_t len = strlen(expected); + if (StringEqualNoCaseN(path, expected, len)) { + if (path[len] == '/') { + return path + len + 1; + } + if (path[len] == '\0') { + return path + len; + } + } + return nullptr; +} + +void SendHttpNotFound(InspectorSocket* socket) +{ + SendHttpResponse(socket, "", 404); +} + +void SendVersionResponse(InspectorSocket* socket) +{ + std::map response; + response["Protocol-Version"] = "1.1"; + response["Browser"] = "jsvm/" JSVM_VERSION_STRING; + SendHttpResponse(socket, MapToString(response), 200); +} + +void SendProtocolJson(InspectorSocket* socket) +{ + z_stream strm; + strm.zalloc = Z_NULL; + strm.zfree = Z_NULL; + strm.opaque = Z_NULL; + CHECK_EQ(inflateInit(&strm), Z_OK); + static const size_t decompressedSize = + PROTOCOL_JSON[0] * 0x10000u + PROTOCOL_JSON[1] * 0x100u + PROTOCOL_JSON[2]; + strm.next_in = const_cast(PROTOCOL_JSON + 3); + strm.avail_in = sizeof(PROTOCOL_JSON) - 3; + std::string data(decompressedSize, '\0'); + strm.next_out = reinterpret_cast(data.data()); + strm.avail_out = data.size(); + CHECK_EQ(inflate(&strm, Z_FINISH), Z_STREAM_END); + CHECK_EQ(strm.avail_out, 0); + CHECK_EQ(inflateEnd(&strm), Z_OK); + SendHttpResponse(socket, data, 200); +} +} // namespace + +std::string FormatWsAddress(const std::string& host, int port, const std::string& targetId, bool includeProtocol) +{ + return FormatAddress(FormatHostPort(host, port), targetId, includeProtocol); +} + +class SocketSession { +public: + SocketSession(InspectorSocketServer* server, int id, int serverPort); + void Close() + { + wsSocket.reset(); + } + void Send(const std::string& message); + void Own(InspectorSocket::Pointer wsSocketParam) + { + wsSocket = std::move(wsSocketParam); + } + int GetId() const + { + return id; + } + int ServerPort() + { + return serverPort; + } + InspectorSocket* GetWsSocket() + { + return wsSocket.get(); + } + void Accept(const std::string& wsKey) + { + wsSocket->AcceptUpgrade(wsKey); + } + void Decline() + { + wsSocket->CancelHandshake(); + } + + class Delegate : public InspectorSocket::Delegate { + public: + Delegate(InspectorSocketServer* server, int sessionId) : server(server), usessionId(sessionId) {} + ~Delegate() override + { + server->SessionTerminated(usessionId); + } + void OnHttpGet(const std::string& host, const std::string& path) override; + void OnSocketUpgrade(const std::string& host, const std::string& path, const std::string& wsKey) override; + void OnWsFrame(const std::vector& data) override; + + private: + SocketSession* Session() + { + return server->Session(usessionId); + } + + InspectorSocketServer* server; + int usessionId; + }; + +private: + const int id; + InspectorSocket::Pointer wsSocket; + const int serverPort; +}; + +class ServerSocket { +public: + explicit ServerSocket(InspectorSocketServer* server) + : tcpSocket(uv_tcp_t()), server(server), unixSocket(uv_pipe_t()) + {} + int Listen(sockaddr* addr, uv_loop_t* loop, int pid = -1); + void Close() + { + uv_close(reinterpret_cast(&tcpSocket), FreeOnCloseCallback); + } + void CloseUnix() + { + if (unixSocketOn) { + uv_close(reinterpret_cast(&unixSocket), nullptr); + unixSocketOn = false; + } + } + int GetPort() const + { + return port; + } + +private: + template + static ServerSocket* FromTcpSocket(UvHandle* socket) + { + return jsvm::inspector::ContainerOf(&ServerSocket::tcpSocket, reinterpret_cast(socket)); + } + static void SocketConnectedCallback(uv_stream_t* tcpSocket, int status); + static void UnixSocketConnectedCallback(uv_stream_t* unixSocket, int status); + static void FreeOnCloseCallback(uv_handle_t* tcpSocket) + { + delete FromTcpSocket(tcpSocket); + } + int DetectPort(uv_loop_t* loop, int pid); + ~ServerSocket() = default; + + uv_tcp_t tcpSocket; + InspectorSocketServer* server; + uv_pipe_t unixSocket; + int port = -1; + bool unixSocketOn = false; +}; + +void PrintDebuggerReadyMessage(const std::string& host, + const std::vector& serverSockets, + const std::vector& ids, + const char* verb, + bool publishUidStderr, + FILE* out) +{ + if (!publishUidStderr || out == nullptr) { + return; + } + for (const auto& serverSocket : serverSockets) { + for (const std::string& id : ids) { + if (fprintf(out, "Debugger %s on %s\n", verb, + FormatWsAddress(host, serverSocket->GetPort(), id, true).c_str()) < 0) { + return; + } + } + } + if (fprintf(out, "For help, see: %s\n", "https://nodejs.org/en/docs/inspector") < 0) { + return; + } + if (fflush(out) != 0) { + return; + } +} + +InspectorSocketServer::InspectorSocketServer(std::unique_ptr delegateParam, + uv_loop_t* loop, + const std::string& host, + int port, + const InspectPublishUid& inspectPublishUid, + FILE* out, + int pid) + : loop(loop), delegate(std::move(delegateParam)), host(host), port(port), inspectPublishUid(inspectPublishUid), + nextSessionId(0), out(out), pid(pid) +{ + delegate->AssignServer(this); + state = ServerState::NEW; +} + +InspectorSocketServer::~InspectorSocketServer() = default; + +SocketSession* InspectorSocketServer::Session(int sessionId) +{ + auto it = connectedSessions.find(sessionId); + return it == connectedSessions.end() ? nullptr : it->second.second.get(); +} + +void InspectorSocketServer::SessionStarted(int sessionId, const std::string& targetId, const std::string& wsKey) +{ + SocketSession* session = Session(sessionId); + if (!TargetExists(targetId)) { + session->Decline(); + return; + } + connectedSessions[sessionId].first = targetId; + session->Accept(wsKey); + delegate->StartSession(sessionId, targetId); +} + +void InspectorSocketServer::SessionTerminated(int sessionId) +{ + if (Session(sessionId) == nullptr) { + return; + } + bool wasAttached = connectedSessions[sessionId].first != ""; + if (wasAttached) { + delegate->EndSession(sessionId); + } + connectedSessions.erase(sessionId); + if (connectedSessions.empty()) { + if (wasAttached && state == ServerState::RUNNING && !serverSockets.empty()) { + PrintDebuggerReadyMessage(host, serverSockets, delegate->GetTargetIds(), "ending", + inspectPublishUid.console, out); + } + if (state == ServerState::STOPPED) { + delegate.reset(); + } + } +} + +bool InspectorSocketServer::HandleGetRequest(int sessionId, const std::string& hostName, const std::string& path) +{ + SocketSession* session = Session(sessionId); + InspectorSocket* socket = session->GetWsSocket(); + if (!inspectPublishUid.http) { + SendHttpNotFound(socket); + return true; + } + const char* command = MatchPathSegment(path.c_str(), "/json"); + if (!command) { + return false; + } + + bool hasHandled = false; + if (MatchPathSegment(command, "list") || command[0] == '\0') { + SendListResponse(socket, hostName, session); + hasHandled = true; + } else if (MatchPathSegment(command, "protocol")) { + SendProtocolJson(socket); + hasHandled = true; + } else if (MatchPathSegment(command, "version")) { + SendVersionResponse(socket); + hasHandled = true; + } + return hasHandled; +} + +void InspectorSocketServer::SendListResponse(InspectorSocket* socket, + const std::string& hostName, + SocketSession* session) +{ + std::vector> response; + for (const std::string& id : delegate->GetTargetIds()) { + response.push_back(std::map()); + std::map& targetMap = response.back(); + targetMap["description"] = "jsvm instance"; + targetMap["id"] = id; + targetMap["title"] = delegate->GetTargetTitle(id); + Escape(&targetMap["title"]); + targetMap["type"] = "node"; + // This attribute value is a "best effort" URL that is passed as a JSON + // string. It is not guaranteed to resolve to a valid resource. + targetMap["url"] = delegate->GetTargetUrl(id); + Escape(&targetMap["url"]); + + std::string detectedHost = hostName; + if (detectedHost.empty()) { + detectedHost = FormatHostPort(socket->GetHost(), session->ServerPort()); + } + std::string formattedAddress = FormatAddress(detectedHost, id, false); + targetMap["devtoolsFrontendUrl"] = GetFrontendURL(false, formattedAddress); + // The compat URL is for Chrome browsers older than 66.0.3345.0 + targetMap["devtoolsFrontendUrlCompat"] = GetFrontendURL(true, formattedAddress); + targetMap["webSocketDebuggerUrl"] = FormatAddress(detectedHost, id, true); + } + SendHttpResponse(socket, MapsToString(response), 200); +} + +std::string InspectorSocketServer::GetFrontendURL(bool isCompat, const std::string& formattedAddress) +{ + std::ostringstream frontendUrl; + frontendUrl << "devtools://devtools/bundled/"; + frontendUrl << (isCompat ? "inspector" : "js_app"); + frontendUrl << ".html?v8only=true&ws="; + frontendUrl << formattedAddress; + return frontendUrl.str(); +} + +bool InspectorSocketServer::Start() +{ + CHECK_NOT_NULL(delegate); + CHECK_EQ(state, ServerState::NEW); + std::unique_ptr delegateHolder; + // We will return it if startup is successful + delegate.swap(delegateHolder); + struct addrinfo hints; + memset_s(&hints, sizeof(hints), 0, sizeof(hints)); + hints.ai_flags = AI_NUMERICSERV; + hints.ai_socktype = SOCK_STREAM; + uv_getaddrinfo_t req; + const std::string portString = std::to_string(port); + int err = uv_getaddrinfo(loop, &req, nullptr, host.c_str(), portString.c_str(), &hints); + if (err < 0) { + if (out != nullptr) { + if (fprintf(out, "Unable to resolve \"%s\": %s\n", host.c_str(), uv_strerror(err)) < 0) { + return false; + } + } + return false; + } + for (addrinfo* address = req.addrinfo; address != nullptr; address = address->ai_next) { + auto serverSocket = ServerSocketPtr(new ServerSocket(this)); + err = serverSocket->Listen(address->ai_addr, loop, pid); + if (err == 0) { + serverSockets.push_back(std::move(serverSocket)); + } + } + uv_freeaddrinfo(req.addrinfo); + + // We only show error if we failed to start server on all addresses. We only + // show one error, for the last address. + if (serverSockets.empty()) { + if (out != nullptr) { + if (fprintf(out, "Starting inspector on %s:%d failed: %s\n", host.c_str(), port, uv_strerror(err)) < 0) { + return false; + } + if (fflush(out) != 0) { + return false; + } + } + return false; + } + delegate.swap(delegateHolder); + state = ServerState::RUNNING; + PrintDebuggerReadyMessage(host, serverSockets, delegate->GetTargetIds(), "listening", inspectPublishUid.console, + out); + return true; +} + +void InspectorSocketServer::Stop() +{ + if (state == ServerState::STOPPED) { + return; + } + CHECK_EQ(state, ServerState::RUNNING); + state = ServerState::STOPPED; + serverSockets.clear(); + if (Done()) { + delegate.reset(); + } +} + +void InspectorSocketServer::TerminateConnections() +{ + for (const auto& keyValue : connectedSessions) { + keyValue.second.second->Close(); + } +} + +bool InspectorSocketServer::TargetExists(const std::string& id) +{ + const std::vector& targetIds = delegate->GetTargetIds(); + const auto& found = std::find(targetIds.begin(), targetIds.end(), id); + return found != targetIds.end(); +} + +int InspectorSocketServer::GetPort() const +{ + if (!serverSockets.empty()) { + return serverSockets[0]->GetPort(); + } + return port; +} + +void InspectorSocketServer::Accept(int serverPort, uv_stream_t* serverSocket) +{ + std::make_unique session(this, nextSessionId++, serverPort); + + InspectorSocket::DelegatePointer delegatePointer = + InspectorSocket::DelegatePointer(new SocketSession::Delegate(this, session->GetId())); + + InspectorSocket::Pointer inspector = InspectorSocket::Accept(serverSocket, std::move(delegatePointer)); + if (inspector) { + session->Own(std::move(inspector)); + connectedSessions[session->GetId()].second = std::move(session); + } +} + +void InspectorSocketServer::Send(int sessionId, const std::string& message) +{ + SocketSession* session = Session(sessionId); + if (session != nullptr) { + session->Send(message); + } +} + +void InspectorSocketServer::CloseServerSocket(ServerSocket* server) +{ + server->Close(); + server->CloseUnix(); +} + +// InspectorSession tracking +SocketSession::SocketSession(InspectorSocketServer* server, int id, int serverPort) : id(id), serverPort(serverPort) {} + +void SocketSession::Send(const std::string& message) +{ + wsSocket->Write(message.data(), message.length()); +} + +void SocketSession::Delegate::OnHttpGet(const std::string& host, const std::string& path) +{ + if (!server->HandleGetRequest(usessionId, host, path)) { + Session()->GetWsSocket()->CancelHandshake(); + } +} + +void SocketSession::Delegate::OnSocketUpgrade(const std::string& host, + const std::string& path, + const std::string& wsKey) +{ + std::string id = path.empty() ? path : path.substr(1); + server->SessionStarted(usessionId, id, wsKey); +} + +void SocketSession::Delegate::OnWsFrame(const std::vector& data) +{ + server->MessageReceived(usessionId, std::string(data.data(), data.size())); +} + +// ServerSocket implementation +int ServerSocket::DetectPort(uv_loop_t* loop, int pid) +{ + sockaddr_storage addr; + int len = sizeof(addr); + int err = uv_tcp_getsockname(&tcpSocket, reinterpret_cast(&addr), &len); + if (err != 0) { + return err; + } + int portNum; + if (addr.ss_family == AF_INET6) { + portNum = reinterpret_cast(&addr)->sin6_port; + } else { + portNum = reinterpret_cast(&addr)->sin_port; + } + port = ntohs(portNum); + if (!unixSocketOn && pid != -1) { + auto unixDomainSocketPath = "jsvm_devtools_remote_" + std::to_string(port) + "_" + std::to_string(pid); + auto* abstract = new char[unixDomainSocketPath.length() + 2]; + abstract[0] = '\0'; + int ret = strcpy_s(abstract + 1, unixDomainSocketPath.length() + 2, unixDomainSocketPath.c_str()); + CHECK(ret == 0); + auto status = uv_pipe_init(loop, &unixSocket, 0); + if (status == 0) { + status = uv_pipe_bind2(&unixSocket, abstract, unixDomainSocketPath.length() + 1, 0); + } + if (status == 0) { + constexpr int unixBacklog = 128; + status = uv_listen(reinterpret_cast(&unixSocket), unixBacklog, + ServerSocket::UnixSocketConnectedCallback); + } + unixSocketOn = status == 0; + delete[] abstract; + } + return err; +} + +int ServerSocket::Listen(sockaddr* addr, uv_loop_t* loop, int pid) +{ + uv_tcp_t* server = &tcpSocket; + CHECK_EQ(0, uv_tcp_init(loop, server)); + int err = uv_tcp_bind(server, addr, 0); + if (err == 0) { + // 511 is the value used by a 'net' module by default + err = uv_listen(reinterpret_cast(server), 511, ServerSocket::SocketConnectedCallback); + } + if (err == 0) { + err = DetectPort(loop, pid); + } + return err; +} + +// static +void ServerSocket::SocketConnectedCallback(uv_stream_t* tcpSocket, int status) +{ + if (status == 0) { + ServerSocket* serverSocket = ServerSocket::FromTcpSocket(tcpSocket); + // Memory is freed when the socket closes. + serverSocket->server->Accept(serverSocket->port, tcpSocket); + } +} + +void ServerSocket::UnixSocketConnectedCallback(uv_stream_t* unixSocket, int status) +{ + if (status == 0) { + (void)unixSocket; + } +} +} // namespace inspector +} // namespace jsvm diff --git a/src/inspector/inspector_socket_server.h b/src/inspector/inspector_socket_server.h new file mode 100644 index 0000000000000000000000000000000000000000..41c369e7861d164bd16e34333bdb9c0830fe675d --- /dev/null +++ b/src/inspector/inspector_socket_server.h @@ -0,0 +1,133 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef SRC_INSPECTOR_SOCKET_SERVER_H_ +#define SRC_INSPECTOR_SOCKET_SERVER_H_ + +#include +#include +#include + +#include "inspector_socket.h" +#include "jsvm_host_port.h" +#include "uv.h" + +#ifndef ENABLE_INSPECTOR +#error("This header can only be used when inspector is enabled") +#endif + +namespace jsvm { +namespace inspector { + +std::string FormatWsAddress(const std::string& host, int port, const std::string& targetId, bool includeProtocol); + +class InspectorSocketServer; +class SocketSession; +class ServerSocket; + +class SocketServerDelegate { +public: + virtual ~SocketServerDelegate() = default; + + virtual void AssignServer(InspectorSocketServer* server) = 0; + + virtual void StartSession(int sessionId, const std::string& targetId) = 0; + + virtual void EndSession(int sessionId) = 0; + + virtual void MessageReceived(int sessionId, const std::string& message) = 0; + + virtual std::vector GetTargetIds() = 0; + + virtual std::string GetTargetTitle(const std::string& id) = 0; + + virtual std::string GetTargetUrl(const std::string& id) = 0; +}; + +// HTTP Server, writes messages requested as TransportActions, and responds to HTTP requests and WS upgrades. + +class InspectorSocketServer { +public: + InspectorSocketServer(std::unique_ptr delegateParam, + uv_loop_t* loop, + const std::string& host, + int port, + const InspectPublishUid& inspectPublishUid, + FILE* out = stderr, + int pid = -1); + + ~InspectorSocketServer(); + + // Start listening on host/port + bool Start(); + + // Called by the TransportAction sent with InspectorIo::Write(): kKill and kStop + void Stop(); + + // kSendMessage + void Send(int sessionId, const std::string& message); + + // kKill + void TerminateConnections(); + + int GetPort() const; + + // Session connection lifecycle + void Accept(int serverPort, uv_stream_t* serverSocket); + + bool HandleGetRequest(int sessionId, const std::string& hostName, const std::string& path); + + void SessionStarted(int sessionId, const std::string& targetId, const std::string& wsKey); + + void SessionTerminated(int sessionId); + + void MessageReceived(int sessionId, const std::string& message) + { + delegate->MessageReceived(sessionId, message); + } + + SocketSession* Session(int sessionId); + + bool Done() const + { + return serverSockets.empty() && connectedSessions.empty(); + } + + static void CloseServerSocket(ServerSocket* server); + using ServerSocketPtr = DeleteFnPtr; + +private: + void SendListResponse(InspectorSocket* socket, const std::string& hostName, SocketSession* session); + std::string GetFrontendURL(bool isCompat, const std::string& formattedAddress); + bool TargetExists(const std::string& id); + + enum class ServerState { NEW, RUNNING, STOPPED }; + uv_loop_t* loop; + std::unique_ptr delegate; + const std::string host; + int port; + InspectPublishUid inspectPublishUid; + std::vector serverSockets; + std::map>> connectedSessions; + int nextSessionId; + FILE* out; + ServerState state; + int pid; +}; + +} // namespace inspector +} // namespace jsvm + +#endif // SRC_INSPECTOR_SOCKET_SERVER_H_ diff --git a/src/inspector/inspector_utils.cpp b/src/inspector/inspector_utils.cpp new file mode 100644 index 0000000000000000000000000000000000000000..bc2cc775b3144766ef4398237ff3133a5bc5f3db --- /dev/null +++ b/src/inspector/inspector_utils.cpp @@ -0,0 +1,207 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "inspector_utils.h" + +#include "jsvm_dfx.h" +#include "unicode/unistr.h" + +#if HAVE_OPENSSL +#include "openssl/opensslv.h" +#endif + +#if OPENSSL_VERSION_MAJOR >= 3 +#include "openssl/provider.h" +#endif + +#include +#include + +namespace jsvm { +namespace inspector { +namespace { +inline icu::UnicodeString Utf8ToUtf16(const char* data, size_t len) +{ + icu::UnicodeString utf16Str = icu::UnicodeString::fromUTF8(icu::StringPiece(data, len)); + + return utf16Str; +} + +inline std::string Utf16toUtf8(const char16_t* data, size_t length) +{ + icu::UnicodeString unicodeStr(data, length); + std::string utf8Str; + unicodeStr.toUTF8String(utf8Str); + + return utf8Str; +} +} // namespace + +std::unique_ptr Utf8ToStringView(const std::string_view message) +{ + icu::UnicodeString utf16Str = Utf8ToUtf16(message.data(), message.length()); + size_t utf16Len = utf16Str.length(); + + v8_inspector::StringView view(reinterpret_cast(utf16Str.getBuffer()), utf16Len); + return v8_inspector::StringBuffer::create(view); +} + +std::string StringViewToUtf8(v8_inspector::StringView view) +{ + if (view.length() == 0) { + return ""; + } + if (view.is8Bit()) { + return std::string(reinterpret_cast(view.characters8()), view.length()); + } + const char16_t* source = reinterpret_cast(view.characters16()); + + return Utf16toUtf8(source, view.length()); +} + +constexpr size_t TO_TRANSFORM_CHAR_NUM = 3; +constexpr size_t TRANSFORMED_CHAR_NUM = 4; + +static constexpr char BASE64_CHAR_SET[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + +size_t Base64Encode(const char* inputString, size_t slen, char* outputBuffer, size_t dlen) +{ + // 1: caluate encode size and check + size_t strLen = slen; + size_t encodedStrLen = Base64EncodeSize(slen); + + CHECK_GE(dlen, encodedStrLen); + + // 2: the index do not exceed the range of outputBuffer and form a complete four-character block + for (size_t i = 0, j = 0; j < strLen - 2; i += TRANSFORMED_CHAR_NUM, j += TO_TRANSFORM_CHAR_NUM) { + // convert three 8bit into four 6bit; then add two 0 bit in each 6 bit + // former 00 + first 6 bits of the first char + outputBuffer[i] = BASE64_CHAR_SET[(static_cast(inputString[j]) & 0xff) >> 2]; + // 00 + the last 2 bits of the first char + the first 4 bits of the second char + outputBuffer[i + 1] = BASE64_CHAR_SET[(static_cast(inputString[j]) & 0x03) << 4 | + (static_cast(inputString[j + 1]) & 0xf0) >> 4]; + // 00 + last 4 bits of the second char + the first 2 bits of the third char + outputBuffer[i + 2] = BASE64_CHAR_SET[(static_cast(inputString[j + 1]) & 0x0f) << 2 | + (static_cast(inputString[j + 2]) & 0xc0) >> 6]; + // 00 + the last 6 bits of the third char + outputBuffer[i + 3] = BASE64_CHAR_SET[static_cast(inputString[j + 2]) & 0x3f]; + } + switch (strLen % TO_TRANSFORM_CHAR_NUM) { + // the original string is less than three bytes, and the missing place is filled with '=' to patch four bytes + case 1: + // 1,2: the original character is one, and two characters are missing after conversion + outputBuffer[encodedStrLen - 4] = + BASE64_CHAR_SET[(static_cast(inputString[strLen - 1]) & 0xff) >> 2]; + outputBuffer[encodedStrLen - 3] = + BASE64_CHAR_SET[(static_cast(inputString[strLen - 1]) & 0x03) << 4]; + outputBuffer[encodedStrLen - 2] = '='; + outputBuffer[encodedStrLen - 1] = '='; + break; + case 2: + // 1: the original character is two, and a character are missing after conversion + outputBuffer[encodedStrLen - 4] = + BASE64_CHAR_SET[(static_cast(inputString[strLen - 2]) & 0xff) >> 2]; + outputBuffer[encodedStrLen - 3] = + BASE64_CHAR_SET[(static_cast(inputString[strLen - 2]) & 0x03) << 4 | + (static_cast(inputString[strLen - 1]) & 0xf0) >> 4]; + outputBuffer[encodedStrLen - 2] = + BASE64_CHAR_SET[(static_cast(inputString[strLen - 1]) & 0x0f) << 2]; + outputBuffer[encodedStrLen - 1] = '='; + break; + default: + break; + } + + return encodedStrLen; +} + +std::string GetHumanReadableProcessName() +{ + return "JSVM[" + std::to_string(platform::OS::GetPid()) + "]"; +} + +MUST_USE_RESULT bool CSPRNG(void* buffer, size_t length) +{ + unsigned char* buf = static_cast(buffer); + do { + if (RAND_status() == 1) { +#if OPENSSL_VERSION_MAJOR >= 3 + if (RAND_bytes_ex(nullptr, buf, length, 0) == 1) { + return true; + } +#else + while (length > INT_MAX && RAND_bytes(buf, INT_MAX) == 1) { + buf += INT_MAX; + length -= INT_MAX; + } + if (length <= INT_MAX && RAND_bytes(buf, static_cast(length)) == 1) { + return true; + } +#endif + } +#if OPENSSL_VERSION_MAJOR >= 3 + const auto code = ERR_peek_last_error(); + // A misconfigured OpenSSL 3 installation may report 1 from RAND_poll() + // and RAND_status() but fail in RAND_bytes() if it cannot look up + // a matching algorithm for the CSPRNG. + if (ERR_GET_LIB(code) == ERR_LIB_RAND) { + const auto reason = ERR_GET_REASON(code); + if (reason == RAND_R_ERROR_INSTANTIATING_DRBG || reason == RAND_R_UNABLE_TO_FETCH_DRBG || + reason == RAND_R_UNABLE_TO_CREATE_DRBG) { + return false; + } + } +#endif + } while (RAND_poll() == 1); + + return false; +} + +void CheckedUvLoopClose(uv_loop_t* loop) +{ + if (uv_loop_close(loop) == 0) { + return; + } + + // Finally, abort. + UNREACHABLE("uv_loop_close() while having open handles"); +} + +using v8::Isolate; +using v8::Local; +using v8::String; +using v8::Value; + +TwoByteValue::TwoByteValue(Isolate* isolate, Local value) +{ + if (value.IsEmpty()) { + return; + } + + Local string; + if (!value->ToString(isolate->GetCurrentContext()).ToLocal(&string)) { + return; + } + + // Allocate enough space to include the null terminator + const size_t storage = string->Length() + 1; + AllocateSufficientStorage(storage); + + const int flags = String::NO_NULL_TERMINATION; + const int length = string->Write(isolate, Out(), 0, storage, flags); + SetLengthAndZeroTerminate(length); +} +} // namespace inspector +} // namespace jsvm \ No newline at end of file diff --git a/src/inspector/inspector_utils.h b/src/inspector/inspector_utils.h new file mode 100644 index 0000000000000000000000000000000000000000..7d01bd4df6115ad0ebd05d13fa26aa5be01b3336 --- /dev/null +++ b/src/inspector/inspector_utils.h @@ -0,0 +1,313 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef INSPECTOR_UTILS_H +#define INSPECTOR_UTILS_H +#include +#include +#include +#include + +#include "jsvm_dfx.h" +#include "jsvm_util.h" +#include "uv.h" +#include "v8-inspector.h" + +#ifdef __GNUC__ +#define MUST_USE_RESULT __attribute__((warn_unused_result)) +#else +#define MUST_USE_RESULT +#endif + +namespace jsvm { +namespace inspector { +template +class ContainerOfHelper { +public: + // The helper is for doing safe downcasts from base types to derived types. + inline ContainerOfHelper(Inner Outer::*field, Inner* pointer); + template + inline operator TypeName*() const; + +private: + Outer* const pointer; +}; + +inline char ToLower(char c) +{ + return std::tolower(c, std::locale::classic()); +} + +inline bool StringEqualNoCase(const char* a, const char* b) +{ + while (ToLower(*a) == ToLower(*b++)) { + if (*a++ == '\0') { + return true; + } + } + return false; +} + +inline bool StringEqualNoCaseN(const char* a, const char* b, size_t length) +{ + for (size_t i = 0; i < length; i++) { + if (ToLower(a[i]) != ToLower(b[i])) { + return false; + } + if (a[i] == '\0') { + return true; + } + } + return true; +} + +// Use this when a variable or parameter is unused in order to explicitly +// silence a compiler warning about that. +template +inline void USE(T&&) +{} + +// Used to be a macro, hence the uppercase name. +template +inline v8::Local FIXED_ONE_BYTE_STRING(v8::Isolate* isolate, const char (&data)[N]) +{ + return OneByteString(isolate, data, N - 1); +} + +template +inline v8::Local FIXED_ONE_BYTE_STRING(v8::Isolate* isolate, const std::array& arr) +{ + return OneByteString(isolate, arr.data(), N - 1); +} + +template +struct FunctionDeleter { + void operator()(T* pointer) const + { + function(pointer); + } + typedef std::unique_ptr Pointer; +}; + +template +using DeleteFnPtr = typename FunctionDeleter::Pointer; + +template +constexpr uintptr_t OffsetOf(Inner Outer::*field) +{ + return reinterpret_cast(&(static_cast(nullptr)->*field)); +} + +template +ContainerOfHelper::ContainerOfHelper(Inner Outer::*field, Inner* pointer) + : pointer(reinterpret_cast(reinterpret_cast(pointer) - OffsetOf(field))) +{} + +template +template +ContainerOfHelper::operator TypeName*() const +{ + return static_cast(pointer); +} + +// Calculate the address of the outer (i.e. embedding) struct from +// the interior pointer to a data member. +template +constexpr ContainerOfHelper ContainerOf(Inner Outer::*field, Inner* pointer) +{ + return ContainerOfHelper(field, pointer); +} + +template +class MaybeStackBuffer { +public: + const T* Out() const + { + return buf; + } + + T* Out() + { + return buf; + } + + // operator* for compatibility with `v8::String::(Utf8)Value` + T* operator*() + { + return buf; + } + + const T* operator*() const + { + return buf; + } + + T& operator[](size_t index) + { + CHECK_LT(index, GetLength()); + return buf[index]; + } + + const T& operator[](size_t index) const + { + CHECK_LT(index, GetLength()); + return buf[index]; + } + + size_t GetLength() const + { + return length; + } + + // Current maximum capacity of the buffer with which SetLength() can be used + // without first calling AllocateSufficientStorage(). + size_t GetCapacity() const + { + return capacity; + } + + void AllocateSufficientStorage(size_t storage); + + void SetLength(size_t lengthParam) + { + // GetCapacity() returns how much memory is actually available. + CHECK_LE(lengthParam, GetCapacity()); + length = lengthParam; + } + + void SetLengthAndZeroTerminate(size_t len) + { + // GetCapacity() returns how much memory is actually available. + CHECK_LE(len + 1, GetCapacity()); + SetLength(len); + + // T() is 0 for integer types, nullptr for pointers, etc. + buf[len] = T(); + } + + void Invalidate() + { + CHECK(!IsAllocated()); + capacity = 0; + length = 0; + buf = nullptr; + } + + // If the buffer is stored in the heap rather than on the stack. + bool IsAllocated() const + { + return !IsInvalidated() && buf != bufSt; + } + + // If Invalidate() has been called. + bool IsInvalidated() const + { + return buf == nullptr; + } + + // Release ownership of the malloc'd buffer. + // Note: This does not free the buffer. + void Release() + { + CHECK(IsAllocated()); + buf = bufSt; + length = 0; + capacity = jsvm::ArraySize(bufSt); + } + + MaybeStackBuffer() : length(0), capacity(jsvm::ArraySize(bufSt)), buf(bufSt) + { + // Default to a zero-length, null-terminated buffer. + buf[0] = T(); + } + + explicit MaybeStackBuffer(size_t storage) : MaybeStackBuffer() + { + AllocateSufficientStorage(storage); + } + + ~MaybeStackBuffer() + { + if (IsAllocated()) { + free(buf); + } + } + + inline std::basic_string ToString() const + { + return { Out(), GetLength() }; + } + inline std::basic_string_view ToStringView() const + { + return { Out(), GetLength() }; + } + +private: + size_t length; + // capacity of the malloc'ed buf + size_t capacity; + T* buf; + T bufSt[kStackStorageSize]; +}; + +class TwoByteValue : public MaybeStackBuffer { +public: + explicit TwoByteValue(v8::Isolate* isolate, v8::Local value); +}; + +template +void MaybeStackBuffer::AllocateSufficientStorage(size_t storage) +{ + CHECK(!IsInvalidated()); + if (storage > GetCapacity()) { + bool wasAllocated = IsAllocated(); + T* allocatedPtr = wasAllocated ? buf : nullptr; + buf = reinterpret_cast(Realloc(allocatedPtr, storage)); + capacity = storage; + if (!wasAllocated && length > 0) { + int ret = memcpy_s(buf, length * sizeof(buf[0]), bufSt, length * sizeof(buf[0])); + CHECK(ret == 0); + } + } + + length = storage; +} + +// Convertion between v8_inspector::StringView and std::string +std::string StringViewToUtf8(v8_inspector::StringView view); +std::unique_ptr Utf8ToStringView(const std::string_view message); + +// Encode base64 +inline constexpr size_t Base64EncodeSize(size_t size) +{ + return ((size + 2) / 3 * 4); +} + +// Be careful: If dlen is less than expected encode size, it will crash. +size_t Base64Encode(const char* inputString, size_t slen, char* outputBuffer, size_t dlen); + +std::string GetHumanReadableProcessName(); + +// Either succeeds with exactly |length| bytes of cryptographically +// strong pseudo-random data, or fails. This function may block. +// Don't assume anything about the contents of |buffer| on error. +// As a special case, |length == 0| can be used to check if the CSPRNG +// is properly seeded without consuming entropy. +MUST_USE_RESULT bool CSPRNG(void* buffer, size_t length); + +void CheckedUvLoopClose(uv_loop_t* loop); +} // namespace inspector +} // namespace jsvm +#endif diff --git a/src/inspector/js_native_api_v8_inspector.cpp b/src/inspector/js_native_api_v8_inspector.cpp new file mode 100644 index 0000000000000000000000000000000000000000..2f562e7b53ab18099c80140127930351d93f7927 --- /dev/null +++ b/src/inspector/js_native_api_v8_inspector.cpp @@ -0,0 +1,1331 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "js_native_api_v8_inspector.h" + +#include + +#include "inspector_socket_server.h" +#include "inspector_utils.h" +#include "js_native_api_v8.h" +#include "jsvm_mutex.h" +#include "libplatform/libplatform.h" +#include "v8-inspector.h" +#include "v8-platform.h" + +#ifdef __POSIX__ +#include // PTHREAD_STACK_MIN +#include +#endif // __POSIX__ + +#include +#include +#include +#include +#include +#include + +namespace v8impl { + +namespace { +using jsvm::ConditionVariable; +using jsvm::Mutex; +using jsvm::inspector::StringViewToUtf8; +using jsvm::inspector::Utf8ToStringView; +using v8_inspector::StringBuffer; +using v8_inspector::StringView; + +class MainThreadInterface; + +class Request { +public: + virtual void Call(MainThreadInterface*) = 0; + virtual ~Request() = default; +}; + +class Deletable { +public: + virtual ~Deletable() = default; +}; + +using MessageQueue = std::deque>; + +class MainThreadHandle : public std::enable_shared_from_this { +public: + explicit MainThreadHandle(MainThreadInterface* mainThread) : mainThread(mainThread) {} + ~MainThreadHandle() + { + Mutex::ScopedLock scopedLock(blockLock); + CHECK_NULL(mainThread); // mainThread should have called Reset + } + std::unique_ptr Connect(std::unique_ptr delegate, bool preventShutdown); + int NewObjectId() + { + return ++nextObjectId; + } + bool Post(std::unique_ptr request); + +private: + void Reset(); + + MainThreadInterface* mainThread; + Mutex blockLock; + int nextSessionId = 0; + std::atomic_int nextObjectId = { 1 }; + + friend class MainThreadInterface; +}; + +class MainThreadInterface : public std::enable_shared_from_this { +public: + explicit MainThreadInterface(Agent* agent); + ~MainThreadInterface(); + + void DispatchMessages(); + void Post(std::unique_ptr request); + bool WaitForFrontendEvent(); + std::shared_ptr GetHandle(); + Agent* InspectorAgent() + { + return agent; + } + void AddObject(int handle, std::unique_ptr object); + Deletable* GetObject(int id); + Deletable* GetObjectIfExists(int id); + void RemoveObject(int handle); + +private: + MessageQueue requests; + Mutex requestsLock; // requests live across threads + // This queue is to maintain the order of the messages for the cases + // when we reenter the DispatchMessages function. + MessageQueue dispatchingMessageQueue; + bool dispatchingMessages = false; + ConditionVariable incomingMessageCond; + // Used from any thread + Agent* const agent; + std::shared_ptr handle; + std::unordered_map> managedObjects; +}; + +template +class DeletableWrapper : public Deletable { +public: + explicit DeletableWrapper(std::unique_ptr object) : object(std::move(object)) {} + ~DeletableWrapper() override = default; + + static T* Get(MainThreadInterface* thread, int id) + { + return static_cast*>(thread->GetObject(id))->object.get(); + } + +private: + std::unique_ptr object; +}; + +template +std::unique_ptr WrapInDeletable(std::unique_ptr object) +{ + return std::make_unique>(std::move(object)); +} + +template +class CreateObjectRequest : public Request { +public: + CreateObjectRequest(int objectId, Factory factory) : objectId(objectId), factory(std::move(factory)) {} + + void Call(MainThreadInterface* thread) override + { + thread->AddObject(objectId, WrapInDeletable(factory(thread))); + } + +private: + int objectId; + Factory factory; +}; + +template +std::unique_ptr NewCreateRequest(int objectId, Factory factory) +{ + return std::make_unique>(objectId, std::move(factory)); +} + +class DeleteRequest : public Request { +public: + explicit DeleteRequest(int objectId) : objectId(objectId) {} + + void Call(MainThreadInterface* thread) override + { + thread->RemoveObject(objectId); + } + +private: + int objectId; +}; + +template +class CallRequest : public Request { +public: + CallRequest(int id, Fn fn) : id(id), fn(std::move(fn)) {} + + void Call(MainThreadInterface* thread) override + { + fn(DeletableWrapper::Get(thread, id)); + } + +private: + int id; + Fn fn; +}; + +template +class AnotherThreadObjectReference { +public: + AnotherThreadObjectReference(std::shared_ptr thread, int objectId) + : thread(thread), objectId(objectId) + {} + + template + AnotherThreadObjectReference(std::shared_ptr thread, Factory factory) + : AnotherThreadObjectReference(thread, thread->NewObjectId()) + { + thread->Post(NewCreateRequest(objectId, std::move(factory))); + } + AnotherThreadObjectReference(AnotherThreadObjectReference&) = delete; + + ~AnotherThreadObjectReference() + { + // Disappearing thread may cause a memory leak + thread->Post(std::make_unique(objectId)); + } + + template + void Call(Fn fn) const + { + using Request = CallRequest; + thread->Post(std::make_unique(objectId, std::move(fn))); + } + + template + void Call(void (T::*fn)(Arg), Arg argument) const + { + Call(std::bind(Apply, std::placeholders::_1, fn, std::move(argument))); + } + +private: + // This has to use non-const reference to support std::bind with non-copyable + // types + template + static void Apply(T* target, void (T::*fn)(Argument), Argument& argument) /* NOLINT (runtime/references) */ + { + (target->*fn)(std::move(argument)); + } + + std::shared_ptr thread; + const int objectId; +}; + +class MainThreadSessionState { +public: + MainThreadSessionState(MainThreadInterface* thread, bool preventShutdown) + : thread(thread), preventShutdown(preventShutdown) + {} + + static std::unique_ptr Create(MainThreadInterface* thread, bool preventShutdown) + { + return std::make_unique(thread, preventShutdown); + } + + void Connect(std::unique_ptr delegate) + { + Agent* agent = thread->InspectorAgent(); + if (agent != nullptr) { + session = agent->Connect(std::move(delegate), preventShutdown); + } + } + + void Dispatch(std::unique_ptr message) + { + session->Dispatch(message->string()); + } + +private: + MainThreadInterface* thread; + bool preventShutdown; + std::unique_ptr session; +}; + +class CrossThreadInspectorSession : public InspectorSession { +public: + CrossThreadInspectorSession(int id, + std::shared_ptr thread, + std::unique_ptr delegate, + bool preventShutdown) + : state(thread, std::bind(MainThreadSessionState::Create, std::placeholders::_1, preventShutdown)) + { + state.Call(&MainThreadSessionState::Connect, std::move(delegate)); + } + + void Dispatch(const StringView& message) override + { + state.Call(&MainThreadSessionState::Dispatch, StringBuffer::create(message)); + } + +private: + AnotherThreadObjectReference state; +}; + +class ThreadSafeDelegate : public InspectorSessionDelegate { +public: + ThreadSafeDelegate(std::shared_ptr thread, int objectId) + : thread(thread), delegate(thread, objectId) + {} + + void SendMessageToFrontend(const v8_inspector::StringView& message) override + { + delegate.Call([m = StringBuffer::create(message)](InspectorSessionDelegate* delegate) { + delegate->SendMessageToFrontend(m->string()); + }); + } + +private: + std::shared_ptr thread; + AnotherThreadObjectReference delegate; +}; + +MainThreadInterface::MainThreadInterface(Agent* agent) : agent(agent) {} + +MainThreadInterface::~MainThreadInterface() +{ + if (handle) { + handle->Reset(); + } +} + +void MainThreadInterface::Post(std::unique_ptr request) +{ + CHECK_NOT_NULL(agent); + Mutex::ScopedLock scopedLock(requestsLock); + bool needsNotify = requests.empty(); + requests.push_back(std::move(request)); + if (needsNotify) { + std::weak_ptr weakSelf { shared_from_this() }; + agent->env()->RequestInterrupt([weakSelf](Environment*) { + if (auto iface = weakSelf.lock()) { + iface->DispatchMessages(); + } + }); + } + incomingMessageCond.Broadcast(scopedLock); +} + +bool MainThreadInterface::WaitForFrontendEvent() +{ + // We allow DispatchMessages reentry as we enter the pause. This is important + // to support debugging the code invoked by an inspector call, such + // as Runtime.evaluate + dispatchingMessages = false; + if (dispatchingMessageQueue.empty()) { + Mutex::ScopedLock scopedLock(requestsLock); + while (requests.empty()) + incomingMessageCond.Wait(scopedLock); + } + return true; +} + +void MainThreadInterface::DispatchMessages() +{ + if (dispatchingMessages) { + return; + } + dispatchingMessages = true; + bool hadMessages = false; + do { + if (dispatchingMessageQueue.empty()) { + Mutex::ScopedLock scopedLock(requestsLock); + requests.swap(dispatchingMessageQueue); + } + hadMessages = !dispatchingMessageQueue.empty(); + while (!dispatchingMessageQueue.empty()) { + MessageQueue::value_type task; + std::swap(dispatchingMessageQueue.front(), task); + dispatchingMessageQueue.pop_front(); + + v8::SealHandleScope sealHandleScope(agent->env()->isolate); + task->Call(this); + } + } while (hadMessages); + dispatchingMessages = false; +} + +std::shared_ptr MainThreadInterface::GetHandle() +{ + if (handle == nullptr) { + handle = std::make_shared(this); + } + return handle; +} + +void MainThreadInterface::AddObject(int id, std::unique_ptr object) +{ + CHECK_NOT_NULL(object); + managedObjects[id] = std::move(object); +} + +void MainThreadInterface::RemoveObject(int handle) +{ + CHECK_EQ(1, managedObjects.erase(handle)); +} + +Deletable* MainThreadInterface::GetObject(int id) +{ + Deletable* pointer = GetObjectIfExists(id); + // This would mean the object is requested after it was disposed, which is + // a coding error. + CHECK_NOT_NULL(pointer); + return pointer; +} + +Deletable* MainThreadInterface::GetObjectIfExists(int id) +{ + auto iterator = managedObjects.find(id); + if (iterator == managedObjects.end()) { + return nullptr; + } + return iterator->second.get(); +} + +std::unique_ptr MainThreadHandle::Connect(std::unique_ptr delegate, + bool preventShutdown) +{ + return std::unique_ptr( + new CrossThreadInspectorSession(++nextSessionId, shared_from_this(), std::move(delegate), preventShutdown)); +} + +bool MainThreadHandle::Post(std::unique_ptr request) +{ + Mutex::ScopedLock scopedLock(blockLock); + if (!mainThread) { + return false; + } + mainThread->Post(std::move(request)); + return true; +} + +void MainThreadHandle::Reset() +{ + Mutex::ScopedLock scopedLock(blockLock); + mainThread = nullptr; +} +} // namespace + +namespace { +using jsvm::InspectPublishUid; +using jsvm::inspector::CheckedUvLoopClose; +using jsvm::inspector::CSPRNG; +using jsvm::inspector::FormatWsAddress; +using jsvm::inspector::GetHumanReadableProcessName; +using jsvm::inspector::InspectorSocketServer; + +// K_KILL closes connections and stops the server, K_STOP only stops the server +enum class TransportAction { K_KILL, K_SEND_MESSAGE, K_STOP }; + +std::string ScriptPath(uv_loop_t* loop, const std::string& scriptName) +{ + std::string scriptPath; + + if (!scriptName.empty()) { + uv_fs_t req; + req.ptr = nullptr; + if (0 == uv_fs_realpath(loop, &req, scriptName.c_str(), nullptr)) { + CHECK_NOT_NULL(req.ptr); + scriptPath = std::string(static_cast(req.ptr)); + } + uv_fs_req_cleanup(&req); + } + + return scriptPath; +} + +// UUID RFC: https://www.ietf.org/rfc/rfc4122.txt +// Used ver 4 - with numbers +std::string GenerateID() +{ + uint16_t buffer[8]; + CHECK(CSPRNG(buffer, sizeof(buffer))); + + char uuid[256]; + int ret = snprintf_s(uuid, sizeof(uuid), sizeof(uuid) - 1, "%04x%04x-%04x-%04x-%04x-%04x%04x%04x", + buffer[0], // time_low + buffer[1], // time_mid + buffer[2], // time_low + (buffer[3] & 0x0fff) | 0x4000, // time_hi_and_version + (buffer[4] & 0x3fff) | 0x8000, // clk_seq_hi clk_seq_low + buffer[5], // node + buffer[6], buffer[7]); + CHECK(ret >= 0); + return uuid; +} + +class RequestToServer { +public: + RequestToServer(TransportAction action, int sessionId, std::unique_ptr message) + : action(action), sessionId(sessionId), message(std::move(message)) + {} + + void Dispatch(InspectorSocketServer* server) const + { + switch (action) { + case TransportAction::K_KILL: + server->TerminateConnections(); + [[fallthrough]]; + case TransportAction::K_STOP: + server->Stop(); + break; + case TransportAction::K_SEND_MESSAGE: + server->Send(sessionId, StringViewToUtf8(message->string())); + break; + } + } + +private: + TransportAction action; + int sessionId; + std::unique_ptr message; +}; + +class RequestQueue; + +class RequestQueueData { +public: + using MessageQueue = std::deque; + + explicit RequestQueueData(uv_loop_t* loop) : handle(std::make_shared(this)) + { + int err = uv_async_init(loop, &async, [](uv_async_t* async) { + RequestQueueData* wrapper = jsvm::inspector::ContainerOf(&RequestQueueData::async, async); + wrapper->DoDispatch(); + }); + CHECK_EQ(0, err); + } + + static void CloseAndFree(RequestQueueData* queue); + + void Post(int sessionId, TransportAction action, std::unique_ptr message) + { + Mutex::ScopedLock scopedLock(stateLock); + bool notify = messages.empty(); + messages.emplace_back(action, sessionId, std::move(message)); + if (notify) { + CHECK_EQ(0, uv_async_send(&async)); + incomingMessageCond.Broadcast(scopedLock); + } + } + + void Wait() + { + Mutex::ScopedLock scopedLock(stateLock); + if (messages.empty()) { + incomingMessageCond.Wait(scopedLock); + } + } + + void SetServer(InspectorSocketServer* serverParam) + { + server = serverParam; + } + + std::shared_ptr GetHandle() + { + return handle; + } + +private: + ~RequestQueueData() = default; + + MessageQueue GetMessages() + { + Mutex::ScopedLock scopedLock(stateLock); + MessageQueue messagesQ; + messages.swap(messagesQ); + return messagesQ; + } + + void DoDispatch() + { + if (server == nullptr) { + return; + } + for (const auto& request : GetMessages()) { + request.Dispatch(server); + } + } + + std::shared_ptr handle; + uv_async_t async; + InspectorSocketServer* server = nullptr; + MessageQueue messages; + Mutex stateLock; // Locked before mutating the queue. + ConditionVariable incomingMessageCond; +}; + +class RequestQueue { +public: + explicit RequestQueue(RequestQueueData* data) : data(data) {} + + void Reset() + { + Mutex::ScopedLock scopedLock(lock); + data = nullptr; + } + + void Post(int sessionId, TransportAction action, std::unique_ptr message) + { + Mutex::ScopedLock scopedLock(lock); + if (data != nullptr) { + data->Post(sessionId, action, std::move(message)); + } + } + + bool Expired() + { + Mutex::ScopedLock scopedLock(lock); + return data == nullptr; + } + +private: + RequestQueueData* data; + Mutex lock; +}; + +class IoSessionDelegate : public InspectorSessionDelegate { +public: + explicit IoSessionDelegate(std::shared_ptr queue, int id) : requestQueue(queue), id(id) {} + void SendMessageToFrontend(const v8_inspector::StringView& message) override + { + requestQueue->Post(id, TransportAction::K_SEND_MESSAGE, StringBuffer::create(message)); + } + +private: + std::shared_ptr requestQueue; + int id; +}; + +// Passed to InspectorSocketServer to handle WS inspector protocol events, +// mostly session start, message received, and session end. +class InspectorIoDelegate : public jsvm::inspector::SocketServerDelegate { +public: + InspectorIoDelegate(std::shared_ptr queue, + std::shared_ptr mainThread, + const std::string& targetId, + const std::string& scriptPath, + const std::string& scriptName); + ~InspectorIoDelegate() override = default; + + void StartSession(int sessionId, const std::string& inTargetId) override; + void MessageReceived(int sessionId, const std::string& message) override; + void EndSession(int sessionId) override; + + std::vector GetTargetIds() override; + std::string GetTargetTitle(const std::string& id) override; + std::string GetTargetUrl(const std::string& id) override; + void AssignServer(InspectorSocketServer* server) override + { + requestQueue->SetServer(server); + } + +private: + std::shared_ptr requestQueue; + std::shared_ptr mainThread; + std::unordered_map> sessions; + const std::string scriptName; + const std::string scriptPath; + const std::string targetId; +}; + +InspectorIoDelegate::InspectorIoDelegate(std::shared_ptr queue, + std::shared_ptr mainThread, + const std::string& targetId, + const std::string& scriptPath, + const std::string& scriptName) + : requestQueue(queue), mainThread(mainThread), scriptName(scriptName), scriptPath(scriptPath), targetId(targetId) +{} + +void InspectorIoDelegate::StartSession(int sessionId, const std::string& inTargetId) +{ + auto session = mainThread->Connect( + std::make_unique(requestQueue->GetHandle(), sessionId), true); + if (session) { + sessions[sessionId] = std::move(session); + if (fprintf(stderr, "Debugger attached.\n") < 0) { + return; + } + } +} + +void InspectorIoDelegate::MessageReceived(int sessionId, const std::string& message) +{ + auto session = sessions.find(sessionId); + if (session != sessions.end()) { + session->second->Dispatch(Utf8ToStringView(message)->string()); + } +} + +void InspectorIoDelegate::EndSession(int sessionId) +{ + sessions.erase(sessionId); +} + +std::vector InspectorIoDelegate::GetTargetIds() +{ + return { targetId }; +} + +std::string InspectorIoDelegate::GetTargetTitle(const std::string& id) +{ + return scriptName.empty() ? GetHumanReadableProcessName() : scriptName; +} + +std::string InspectorIoDelegate::GetTargetUrl(const std::string& id) +{ + return "file://" + scriptPath; +} + +// static +void RequestQueueData::CloseAndFree(RequestQueueData* queue) +{ + queue->handle->Reset(); + queue->handle.reset(); + uv_close(reinterpret_cast(&queue->async), [](uv_handle_t* handle) { + uv_async_t* async = reinterpret_cast(handle); + RequestQueueData* wrapper = jsvm::inspector::ContainerOf(&RequestQueueData::async, async); + delete wrapper; + }); +} +} // namespace + +class InspectorIo { +public: + // Start the inspector agent thread, waiting for it to initialize. + // Returns empty pointer if thread was not started. + static std::unique_ptr Start(std::shared_ptr mainThread, + const std::string& path, + std::shared_ptr> hostPortParam, + const jsvm::InspectPublishUid& inspectPublishUid); + + // Will block till the transport thread shuts down + ~InspectorIo(); + + void StopAcceptingNewConnections(); + std::string GetWsUrl() const; + +private: + InspectorIo(std::shared_ptr handle, + const std::string& path, + std::shared_ptr> hostPortParam, + const jsvm::InspectPublishUid& inspectPublishUid); + + // Wrapper for agent->ThreadMain() + static void ThreadMain(void* io); + + // Runs a uv_loop_t + void ThreadMain(); + + // This is a thread-safe object that will post async tasks. It lives as long + // as an Inspector object lives (almost as long as an Isolate). + std::shared_ptr mainThread; + // Used to post on a frontend interface thread, lives while the server is + // running + std::shared_ptr requestQueue; + std::shared_ptr> hostPort; + jsvm::InspectPublishUid inspectPublishUid; + + // The IO thread runs its own uv_loop to implement the TCP server off + // the main thread. + uv_thread_t thread; + + // For setting up interthread communications + Mutex threadStartLock; + jsvm::ConditionVariable threadStartCondition; + std::string scriptName; + // May be accessed from any thread + const std::string id; +}; + +// static +std::unique_ptr InspectorIo::Start(std::shared_ptr mainThread, + const std::string& path, + std::shared_ptr> hostPortParam, + const InspectPublishUid& inspectPublishUid) +{ + auto io = std::make_unique(mainThread, path, hostPortParam, inspectPublishUid); + if (io->requestQueue->Expired()) { // Thread is not running + return nullptr; + } + return io; +} + +InspectorIo::InspectorIo(std::shared_ptr mainThread, + const std::string& path, + std::shared_ptr> hostPortParam, + const InspectPublishUid& inspectPublishUid) + : mainThread(mainThread), hostPort(hostPortParam), inspectPublishUid(inspectPublishUid), thread(), scriptName(path), + id(GenerateID()) +{ + Mutex::ScopedLock scopedLock(threadStartLock); + CHECK_EQ(uv_thread_create(&thread, InspectorIo::ThreadMain, this), 0); + threadStartCondition.Wait(scopedLock); +} + +InspectorIo::~InspectorIo() +{ + requestQueue->Post(0, TransportAction::K_KILL, nullptr); + int err = uv_thread_join(&thread); + CHECK_EQ(err, 0); +} + +void InspectorIo::StopAcceptingNewConnections() +{ + requestQueue->Post(0, TransportAction::K_STOP, nullptr); +} + +// static +void InspectorIo::ThreadMain(void* io) +{ + static_cast(io)->ThreadMain(); +} + +void InspectorIo::ThreadMain() +{ + uv_loop_t loop; + loop.data = nullptr; + int err = uv_loop_init(&loop); + CHECK_EQ(err, 0); + std::shared_ptr queue = + std::make_shared(&loop, RequestQueueData::CloseAndFree); + std::string scriptPath = ScriptPath(&loop, scriptName); + std::unique_ptr delegate( + new InspectorIoDelegate(queue, mainThread, id, scriptPath, scriptName)); + std::string host; + int port; + int pid; + { + ExclusiveAccess::Scoped scopedHostPort(hostPort); + host = scopedHostPort->GetHost(); + port = scopedHostPort->GetPort(); + pid = scopedHostPort->GetPid(); + } + InspectorSocketServer server(std::move(delegate), &loop, std::move(host), port, inspectPublishUid, stderr, pid); + requestQueue = queue->GetHandle(); + // Its lifetime is now that of the server delegate + queue.reset(); + { + Mutex::ScopedLock scopedLock(threadStartLock); + if (server.Start()) { + ExclusiveAccess::Scoped scopedHostPort(hostPort); + scopedHostPort->SetPort(server.GetPort()); + } + threadStartCondition.Broadcast(scopedLock); + } + uv_run(&loop, UV_RUN_DEFAULT); + CheckedUvLoopClose(&loop); +} + +std::string InspectorIo::GetWsUrl() const +{ + ExclusiveAccess::Scoped scopedHostPort(hostPort); + return FormatWsAddress(scopedHostPort->GetHost(), scopedHostPort->GetPort(), id, true); +} + +namespace { + +using jsvm::inspector::TwoByteValue; + +using v8::Context; +using v8::Function; +using v8::HandleScope; +using v8::Isolate; +using v8::Local; +using v8::Message; +using v8::Object; +using v8::Value; + +using v8_inspector::StringBuffer; +using v8_inspector::StringView; +using v8_inspector::V8Inspector; +using v8_inspector::V8InspectorClient; + +std::unique_ptr ToProtocolString(Isolate* isolate, Local value) +{ + TwoByteValue buffer(isolate, value); + return StringBuffer::create(StringView(*buffer, buffer.GetLength())); +} + +const int CONTEXT_GROUP_ID = 1; + +std::string GetWorkerLabel(Environment* env) +{ + std::ostringstream result; + result << "Worker[" + << "env->thread_id()" + << "]"; + return result.str(); +} + +class ChannelImpl final : public v8_inspector::V8Inspector::Channel { +public: + explicit ChannelImpl(const std::unique_ptr& inspector, + std::unique_ptr delegate, + std::shared_ptr mainThread, + bool preventShutdown) + : delegate(std::move(delegate)), preventShutdown(preventShutdown) + { + session = + inspector->connect(CONTEXT_GROUP_ID, this, StringView(), V8Inspector::ClientTrustLevel::kFullyTrusted); + } + + ~ChannelImpl() = default; + + void DispatchProtocolMessage(const StringView& message) + { + session->DispatchProtocolMessage(message); + } + + void SchedulePauseOnNextStatement(const std::string& reason) + { + std::unique_ptr buffer = Utf8ToStringView(reason); + session->SchedulePauseOnNextStatement(buffer->string(), buffer->string()); + } + + bool PreventShutdown() + { + return preventShutdown; + } + +private: + void SendResponse(int callId, std::unique_ptr message) override + { + SendMessageToFrontend(message->string()); + } + + void SendNotification(std::unique_ptr message) override + { + SendMessageToFrontend(message->string()); + } + + void FlushProtocolNotifications() override {} + + void SendMessageToFrontend(const StringView& message) + { + delegate->SendMessageToFrontend(message); + } + + void SendMessageToFrontend(const std::string& message) + { + SendMessageToFrontend(Utf8ToStringView(message)->string()); + } + + std::unique_ptr delegate; + std::unique_ptr session; + bool preventShutdown; +}; + +class SameThreadInspectorSession : public InspectorSession { +public: + SameThreadInspectorSession(int sessionId, std::shared_ptr client) + : sessionId(sessionId), client(client) + {} + ~SameThreadInspectorSession() override; + void Dispatch(const v8_inspector::StringView& message) override; + +private: + int sessionId; + std::weak_ptr client; +}; + +} // namespace + +class InspectorClient : public V8InspectorClient { +public: + explicit InspectorClient(Environment* env, bool isMain) : env(env), isMain(isMain) + { + client = V8Inspector::create(env->isolate, this); + std::string name = isMain ? GetHumanReadableProcessName() : GetWorkerLabel(env); + ContextInfo info(name); + info.isDefault = true; + ContextCreated(env->context(), info); + } + + void RunMessageLoopOnPause(int contextGroupId) override + { + waitingForResume = true; + RunMessageLoop(); + } + + void WaitForSessionsDisconnect() + { + waitingForSessionsDisconnect = true; + RunMessageLoop(); + } + + void WaitForFrontend() + { + waitingForFrontend = true; + RunMessageLoop(); + } + + void MaxAsyncCallStackDepthChanged(int depth) override + { + if (waitingForSessionsDisconnect) { + // V8 isolate is mostly done and is only letting Inspector protocol + // clients gather data. + return; + } + } + + void ContextCreated(Local context, const ContextInfo& info) + { + auto nameBuffer = Utf8ToStringView(info.name); + auto originBuffer = Utf8ToStringView(info.origin); + std::unique_ptr auxDataBuffer; + + v8_inspector::V8ContextInfo v8info(context, CONTEXT_GROUP_ID, nameBuffer->string()); + v8info.origin = originBuffer->string(); + + if (info.isDefault) { + auxDataBuffer = Utf8ToStringView("{\"isDefault\":true}"); + } else { + auxDataBuffer = Utf8ToStringView("{\"isDefault\":false}"); + } + v8info.auxData = auxDataBuffer->string(); + + client->ContextCreated(v8info); + } + + void ContextDestroyed(Local context) + { + client->ContextDestroyed(context); + } + + void QuitMessageLoopOnPause() override + { + waitingForResume = false; + } + + void RunIfWaitingForDebugger(int contextGroupId) override + { + waitingForFrontend = false; + } + + int ConnectFrontend(std::unique_ptr delegate, bool preventShutdown) + { + int sessionId = nextSessionId++; + channels[sessionId] = + std::make_unique(client, std::move(delegate), GetThreadHandle(), preventShutdown); + return sessionId; + } + + void DisconnectFrontend(int sessionId) + { + auto it = channels.find(sessionId); + if (it == channels.end()) { + return; + } + channels.erase(it); + if (waitingForSessionsDisconnect && !isMain) { + waitingForSessionsDisconnect = false; + } + } + + void DispatchMessageFromFrontend(int sessionId, const StringView& message) + { + channels[sessionId]->DispatchProtocolMessage(message); + } + + Local EnsureDefaultContextInGroup(int contextGroupId) override + { + return env->context(); + } + + void ReportUncaughtException(Local error, Local message) + { + Isolate* isolate = env->isolate; + Local context = env->context(); + + int scriptId = message->GetScriptOrigin().ScriptId(); + + Local stackTrace = message->GetStackTrace(); + + if (!stackTrace.IsEmpty() && stackTrace->GetFrameCount() > 0 && + scriptId == stackTrace->GetFrame(isolate, 0)->GetScriptId()) { + scriptId = 0; + } + + const uint8_t details[] = "Uncaught"; + + client->exceptionThrown(context, StringView(details, sizeof(details) - 1), error, + ToProtocolString(isolate, message->Get())->string(), + ToProtocolString(isolate, message->GetScriptResourceName())->string(), + message->GetLineNumber(context).FromMaybe(0), + message->GetStartColumn(context).FromMaybe(0), client->createStackTrace(stackTrace), + scriptId); + } + + void StartRepeatingTimer(double interval, TimerCallback callback, void* data) override {} + + void CancelTimer(void* data) override {} + + void SchedulePauseOnNextStatement(const std::string& reason) + { + for (const auto& idChannel : channels) { + idChannel.second->SchedulePauseOnNextStatement(reason); + } + } + + bool HasConnectedSessions() + { + for (const auto& idChannel : channels) { + // Other sessions are "invisible" more most purposes + if (idChannel.second->PreventShutdown()) { + return true; + } + } + return false; + } + + std::shared_ptr GetThreadHandle() + { + if (!interface) { + interface = std::make_shared(static_cast(env->GetInspectorAgent())); + } + return interface->GetHandle(); + } + + bool IsActive() + { + return !channels.empty(); + } + +private: + bool ShouldRunMessageLoop() + { + if (waitingForFrontend) { + return true; + } + if (waitingForSessionsDisconnect || waitingForResume) { + return HasConnectedSessions(); + } + return false; + } + + void RunMessageLoop() + { + if (runningNestedLoop) { + return; + } + + runningNestedLoop = true; + + while (ShouldRunMessageLoop()) { + if (interface) { + interface->WaitForFrontendEvent(); + } + env->RunAndClearInterrupts(); + } + runningNestedLoop = false; + } + + double CurrentTimeMS() override + { + return env->platform()->CurrentClockTimeMillis(); + } + + Environment* env; + bool isMain; + bool runningNestedLoop = false; + std::unique_ptr client; + std::unordered_map> channels; + int nextSessionId = 1; + bool waitingForResume = false; + bool waitingForFrontend = false; + bool waitingForSessionsDisconnect = false; + // Allows accessing Inspector from non-main threads + std::shared_ptr interface; +}; + +Agent::Agent(Environment* env) : parentEnv(env) {} + +Agent::~Agent() = default; + +bool Agent::Start(const std::string& pathParam, + std::shared_ptr> hostPortParam, + bool isMain, + bool waitForConnect) +{ + path = pathParam; + CHECK_NOT_NULL(hostPortParam); + hostPort = hostPortParam; + + client = std::make_shared(parentEnv, isMain); + + if (!StartIoThread()) { + return false; + } + + if (waitForConnect) { + client->WaitForFrontend(); + } + return true; +} + +int FindAvailablePort() +{ + constexpr int startPort = 9229; + constexpr int endPort = 9999; + constexpr int invalidPort = -1; + int sockfd = -1; + + for (auto port = startPort; port <= endPort; ++port) { + sockfd = socket(AF_INET, SOCK_STREAM, 0); + if (sockfd < 0) { + continue; + } + struct sockaddr_in addr; + addr.sin_family = AF_INET; + addr.sin_addr.s_addr = htonl(INADDR_ANY); + addr.sin_port = htons(port); + + if (bind(sockfd, reinterpret_cast(&addr), sizeof(addr)) < 0) { + close(sockfd); + if (errno == EADDRINUSE) { + continue; + } else { + break; + } + } + close(sockfd); + return port; + } + return invalidPort; +} + +bool Agent::Start(const std::string& pathParam, int pid) +{ + int port = FindAvailablePort(); + if (port < 0) { + return false; + } + auto hostPort = std::make_shared>("localhost", port, pid); + return Start(pathParam, hostPort, true, false); +} + +bool Agent::StartIoThread() +{ + if (io != nullptr) { + return true; + } + + if (!client) { + return false; + } + + CHECK_NOT_NULL(client); + + io = InspectorIo::Start(client->GetThreadHandle(), path, hostPort, { false, true }); + if (io == nullptr) { + return false; + } + return true; +} + +void Agent::Stop() +{ + io.reset(); +} + +std::unique_ptr Agent::Connect(std::unique_ptr delegate, + bool preventShutdown) +{ + if (!client) { + return std::unique_ptr {}; + } + + CHECK_NOT_NULL(client); + + int sessionId = client->connectFrontend(std::move(delegate), preventShutdown); + return std::make_unique(sessionId, client); +} + +void Agent::WaitForDisconnect() +{ + CHECK_NOT_NULL(client); + if (client->HasConnectedSessions()) { + if (fprintf(stderr, "Waiting for the debugger to disconnect...\n") < 0) { + return; + } + if (fflush(stderr) != 0) { + return; + } + } + + client->ContextDestroyed(parentEnv->context()); + + if (io != nullptr) { + io->StopAcceptingNewConnections(); + client->WaitForSessionsDisconnect(); + } +} + +void Agent::PauseOnNextJavascriptStatement(const std::string& reason) +{ + client->SchedulePauseOnNextStatement(reason); +} + +bool Agent::IsActive() +{ + if (client == nullptr) { + return false; + } + return io != nullptr || client->IsActive(); +} + +void Agent::WaitForConnect() +{ + CHECK_NOT_NULL(client); + client->WaitForFrontend(); +} + +SameThreadInspectorSession::~SameThreadInspectorSession() +{ + auto clientLock = client.lock(); + if (clientLock) { + clientLock->DisconnectFrontend(sessionId); + } +} + +void SameThreadInspectorSession::Dispatch(const v8_inspector::StringView& message) +{ + auto clientLock = client.lock(); + if (clientLock) { + clientLock->DispatchMessageFromFrontend(sessionId, message); + } +} + +} // namespace v8impl + +jsvm::InspectorAgent* jsvm::InspectorAgent::New(JSVM_Env env) +{ + return new v8impl::Agent(env); +} diff --git a/src/inspector/js_native_api_v8_inspector.h b/src/inspector/js_native_api_v8_inspector.h new file mode 100644 index 0000000000000000000000000000000000000000..238b4bb8a443dfb211ccc254396df842751212fc --- /dev/null +++ b/src/inspector/js_native_api_v8_inspector.h @@ -0,0 +1,139 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef JS_NATIVE_API_V8_INSPECTOR_H +#define JS_NATIVE_API_V8_INSPECTOR_H + +#include +#include + +#include "js_native_api_v8.h" +#include "jsvm_host_port.h" +#include "jsvm_inspector_agent.h" +#include "v8.h" + +#ifndef ENABLE_INSPECTOR +#error("This header can only be used when inspector is enabled") +#endif + +namespace v8_inspector { +class StringView; +} // namespace v8_inspector + +namespace jsvm { +namespace inspector { +class InspectorSessionDelegate; +class InspectorSession; + +class InspectorSession { +public: + virtual ~InspectorSession() = default; + virtual void Dispatch(const v8_inspector::StringView& message) = 0; +}; + +class InspectorSessionDelegate { +public: + virtual ~InspectorSessionDelegate() = default; + virtual void SendMessageToFrontend(const v8_inspector::StringView& message) = 0; +}; +} // namespace inspector +} // namespace jsvm + +namespace v8impl { + +using jsvm::ExclusiveAccess; +using jsvm::HostPort; +using jsvm::inspector::InspectorSession; +using jsvm::inspector::InspectorSessionDelegate; + +class IsolateData; +using Environment = JSVM_Env__; + +class InspectorClient; +class InspectorIo; + +struct ContextInfo { + explicit ContextInfo(const std::string& name) : name(name) {} + const std::string name; + std::string origin; + bool isDefault = false; +}; + +class Agent : public jsvm::InspectorAgent { +public: + explicit Agent(Environment* env); + ~Agent(); + +public: + bool Start(const std::string& pathParam, const std::string& hostName, int port, int pid = -1) override + { + auto hostPort = std::make_shared>(hostName, port, pid); + return Start(pathParam, hostPort, true, false); + } + + bool Start(const std::string& pathParam, int pid) override; + + // Stop and destroy io_ + void Stop() override; + + // Returns true if the inspector is actually in use. + bool IsActive() override; + + // Blocks till frontend connects and sends "runIfWaitingForDebugger" + void WaitForConnect() override; + + // Blocks till all the sessions with "WaitForDisconnectOnShutdown" disconnect + void WaitForDisconnect() override; + + void PauseOnNextJavascriptStatement(const std::string& reason) override; + +public: + // Called to create inspector sessions that can be used from the same thread. + // The inspector responds by using the delegate to send messages back. + std::unique_ptr Connect(std::unique_ptr delegate, bool preventShutdown); + + // Can only be called from the main thread. + bool StartIoThread(); + + std::shared_ptr> GetHostPort() + { + return hostPort; + } + + inline Environment* env() const + { + return parentEnv; + } + +private: + // Create client_, may create io if option enabled + bool Start(const std::string& pathParam, + std::shared_ptr> hostPortParam, + bool isMain, + bool waitForConnect); + + Environment* parentEnv; + // Encapsulates majority of the Inspector functionality + std::shared_ptr client; + // Interface for transports, e.g. WebSocket server + std::unique_ptr io; + std::string path; + + std::shared_ptr> hostPort; +}; + +} // namespace v8impl + +#endif \ No newline at end of file diff --git a/src/inspector/jsvm_host_port.h b/src/inspector/jsvm_host_port.h new file mode 100644 index 0000000000000000000000000000000000000000..42676679c367aff23647bda3362bdfa14184e34b --- /dev/null +++ b/src/inspector/jsvm_host_port.h @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef SRC_JSVM_HOST_PORT_H_ +#define SRC_JSVM_HOST_PORT_H_ + +#include "jsvm_dfx.h" +#include "jsvm_mutex.h" +#include "jsvm_util.h" + +namespace jsvm { + +class HostPort { +public: + HostPort(const std::string& hostName, int port, int pid = -1) : hostName(hostName), port(port), pid(pid) {} + HostPort(const HostPort&) = default; + HostPort& operator=(const HostPort&) = default; + HostPort(HostPort&&) = default; + HostPort& operator=(HostPort&&) = default; + + void SetHost(const std::string& host) + { + hostName = host; + } + + void SetPort(int portParam) + { + port = portParam; + } + + const std::string& GetHost() const + { + return hostName; + } + + int GetPort() const + { + CHECK_GE(port, 0); + return port; + } + + int GetPid() const + { + return pid; + } + + void Update(const HostPort& other) + { + if (!other.hostName.empty()) { + hostName = other.hostName; + } + if (other.port >= 0) { + port = other.port; + } + } + +private: + std::string hostName; + int port; + int pid; +}; + +struct InspectPublishUid { + bool console; + bool http; +}; + +} // namespace jsvm + +#endif // SRC_JSVM_HOST_PORT_H_ diff --git a/src/inspector/jsvm_mutex.h b/src/inspector/jsvm_mutex.h new file mode 100644 index 0000000000000000000000000000000000000000..85140c624ecf3f3700b3d4b1d1d9863ce378fe09 --- /dev/null +++ b/src/inspector/jsvm_mutex.h @@ -0,0 +1,389 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef SRC_JSVM_MUTEX_H_ +#define SRC_JSVM_MUTEX_H_ + +#include // std::shared_ptr +#include // std::forward + +#include "jsvm_util.h" +#include "uv.h" + +namespace jsvm { + +template +class ConditionVariableBase; +template +class MutexBase; +struct LibuvMutexTraits; +struct LibuvRwlockTraits; + +using ConditionVariable = ConditionVariableBase; +using Mutex = MutexBase; +using RwLock = MutexBase; + +template +class ExclusiveAccess { +public: + ExclusiveAccess() = default; + + template + explicit ExclusiveAccess(Args&&... args) : item(std::forward(args)...) + {} + + ExclusiveAccess(const ExclusiveAccess&) = delete; + ExclusiveAccess& operator=(const ExclusiveAccess&) = delete; + + class Scoped { + public: + // ExclusiveAccess will commonly be used in conjunction with std::shared_ptr + // and without this constructor it's too easy to forget to keep a reference + // around to the shared_ptr while operating on the ExclusiveAccess object. + explicit Scoped(const std::shared_ptr& shared) + : shared(shared), scopedLock(shared->mutex), pointer(&shared->item) + {} + + explicit Scoped(ExclusiveAccess* exclusiveAccess) + : shared(), scopedLock(exclusiveAccess->mutex), pointer(&exclusiveAccess->item) + {} + + T& operator*() const + { + return *pointer; + } + T* operator->() const + { + return pointer; + } + + Scoped(const Scoped&) = delete; + Scoped& operator=(const Scoped&) = delete; + + private: + std::shared_ptr shared; + typename MutexT::ScopedLock scopedLock; + T* const pointer; + }; + +private: + friend class ScopedLock; + MutexT mutex; + T item; +}; + +template +class MutexBase { +public: + inline MutexBase(); + + inline ~MutexBase(); + + MutexBase(const MutexBase&) = delete; + + MutexBase& operator=(const MutexBase&) = delete; + + inline void Lock(); + + inline void Unlock(); + + inline void RdLock(); + + inline void RdUnlock(); + + class ScopedUnlock; + class ScopedLock; + + class ScopedLock { + public: + inline explicit ScopedLock(const MutexBase& mutex); + + inline explicit ScopedLock(const ScopedUnlock& scopedUnlock); + + ScopedLock(const ScopedLock&) = delete; + + ScopedLock& operator=(const ScopedLock&) = delete; + + inline ~ScopedLock(); + + private: + template + friend class ConditionVariableBase; + friend class ScopedUnlock; + const MutexBase& mutex; + }; + + class ScopedReadLock { + public: + inline explicit ScopedReadLock(const MutexBase& mutex); + + inline ~ScopedReadLock(); + + ScopedReadLock(const ScopedReadLock&) = delete; + + ScopedReadLock& operator=(const ScopedReadLock&) = delete; + + private: + template + friend class ConditionVariableBase; + const MutexBase& mutex; + }; + + using ScopedWriteLock = ScopedLock; + + class ScopedUnlock { + public: + inline explicit ScopedUnlock(const ScopedLock& scopedLock); + inline ~ScopedUnlock(); + + ScopedUnlock(const ScopedUnlock&) = delete; + ScopedUnlock& operator=(const ScopedUnlock&) = delete; + + private: + friend class ScopedLock; + const MutexBase& mutex; + }; + +private: + template + friend class ConditionVariableBase; + mutable typename Traits::MutexT mutex; +}; + +template +class ConditionVariableBase { +public: + inline ConditionVariableBase(); + + inline ~ConditionVariableBase(); + + using ScopedLock = typename MutexBase::ScopedLock; + + ConditionVariableBase(const ConditionVariableBase&) = delete; + ConditionVariableBase& operator=(const ConditionVariableBase&) = delete; + + inline void Broadcast(const ScopedLock&); + + inline void Signal(const ScopedLock&); + + inline void Wait(const ScopedLock& scopedLock); + +private: + typename Traits::CondT cond; +}; + +struct LibuvMutexTraits { + using CondT = uv_cond_t; + using MutexT = uv_mutex_t; + + static inline int CondInit(CondT* cond) + { + return uv_cond_init(cond); + } + + static inline int MutexInit(MutexT* mutex) + { + return uv_mutex_init(mutex); + } + + static inline void CondBroadcast(CondT* cond) + { + uv_cond_broadcast(cond); + } + + static inline void CondDestroy(CondT* cond) + { + uv_cond_destroy(cond); + } + + static inline void CondSignal(CondT* cond) + { + uv_cond_signal(cond); + } + + static inline void CondWait(CondT* cond, MutexT* mutex) + { + uv_cond_wait(cond, mutex); + } + + static inline void MutexDestroy(MutexT* mutex) + { + uv_mutex_destroy(mutex); + } + + static inline void MutexLock(MutexT* mutex) + { + uv_mutex_lock(mutex); + } + + static inline void MutexUnlock(MutexT* mutex) + { + uv_mutex_unlock(mutex); + } + + static inline void MutexRdlock(MutexT* mutex) + { + uv_mutex_lock(mutex); + } + + static inline void MutexRdunlock(MutexT* mutex) + { + uv_mutex_unlock(mutex); + } +}; + +struct LibuvRwlockTraits { + using MutexT = uv_rwlock_t; + + static inline int MutexInit(MutexT* mutex) + { + return uv_rwlock_init(mutex); + } + + static inline void MutexDestroy(MutexT* mutex) + { + uv_rwlock_destroy(mutex); + } + + static inline void MutexLock(MutexT* mutex) + { + uv_rwlock_wrlock(mutex); + } + + static inline void MutexUnlock(MutexT* mutex) + { + uv_rwlock_wrunlock(mutex); + } + + static inline void MutexRdlock(MutexT* mutex) + { + uv_rwlock_rdlock(mutex); + } + + static inline void MutexRdunlock(MutexT* mutex) + { + uv_rwlock_rdunlock(mutex); + } +}; + +template +ConditionVariableBase::ConditionVariableBase() +{ + CHECK_EQ(0, Traits::CondInit(&cond)); +} + +template +ConditionVariableBase::~ConditionVariableBase() +{ + Traits::CondDestroy(&cond); +} + +template +void ConditionVariableBase::Broadcast(const ScopedLock&) +{ + Traits::CondBroadcast(&cond); +} + +template +void ConditionVariableBase::Signal(const ScopedLock&) +{ + Traits::CondSignal(&cond); +} + +template +void ConditionVariableBase::Wait(const ScopedLock& scopedLock) +{ + Traits::CondWait(&cond, &scopedLock.mutex.mutex); +} + +template +MutexBase::MutexBase() +{ + CHECK_EQ(0, Traits::MutexInit(&mutex)); +} + +template +MutexBase::~MutexBase() +{ + Traits::MutexDestroy(&mutex); +} + +template +void MutexBase::Lock() +{ + Traits::MutexLock(&mutex); +} + +template +void MutexBase::Unlock() +{ + Traits::MutexUnlock(&mutex); +} + +template +void MutexBase::RdLock() +{ + Traits::MutexRdlock(&mutex); +} + +template +void MutexBase::RdUnlock() +{ + Traits::MutexRdunlock(&mutex); +} + +template +MutexBase::ScopedLock::ScopedLock(const MutexBase& mutex) : mutex(mutex) +{ + Traits::MutexLock(&mutex.mutex); +} + +template +MutexBase::ScopedLock::ScopedLock(const ScopedUnlock& scopedUnlock) : MutexBase(scopedUnlock.mutex) +{} + +template +MutexBase::ScopedLock::~ScopedLock() +{ + Traits::MutexUnlock(&mutex.mutex); +} + +template +MutexBase::ScopedReadLock::ScopedReadLock(const MutexBase& mutex) : mutex(mutex) +{ + Traits::MutexRdlock(&mutex.mutex); +} + +template +MutexBase::ScopedReadLock::~ScopedReadLock() +{ + Traits::MutexRdunlock(&mutex.mutex); +} + +template +MutexBase::ScopedUnlock::ScopedUnlock(const ScopedLock& scopedLock) : mutex(scopedLock.mutex) +{ + Traits::MutexUnlock(&mutex.mutex); +} + +template +MutexBase::ScopedUnlock::~ScopedUnlock() +{ + Traits::MutexLock(&mutex.mutex); +} + +} // namespace jsvm + +#endif // SRC_JSVM_MUTEX_H_ diff --git a/src/inspector/v8_inspector_protocol_json.h b/src/inspector/v8_inspector_protocol_json.h new file mode 100644 index 0000000000000000000000000000000000000000..3f62f7598da0fb269edb04c54038593919035f20 --- /dev/null +++ b/src/inspector/v8_inspector_protocol_json.h @@ -0,0 +1,757 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef V8_INSPECTOR_PROTOCOL_JSON_H +#define V8_INSPECTOR_PROTOCOL_JSON_H +namespace jsvm { +namespace inspector { +constexpr uint8_t PROTOCOL_JSON[] = { + 1, 66, 204, 120, 218, 237, 125, 235, 115, 220, 70, 146, 231, 191, 130, 208, 110, 132, 200, 139, 102, 123, 188, + 27, 55, 183, 235, 253, 36, 145, 178, 205, 9, 75, 100, 136, 242, 248, 34, 182, 29, 209, 232, 6, 154, 132, + 213, 93, 232, 67, 1, 164, 122, 230, 252, 191, 95, 190, 234, 1, 160, 10, 13, 144, 148, 173, 155, 241, 23, + 91, 108, 0, 245, 204, 202, 204, 202, 199, 47, 255, 254, 226, 62, 175, 116, 81, 170, 23, 223, 252, 253, 197, + 46, 253, 165, 172, 94, 124, 243, 226, 235, 23, 179, 23, 187, 66, 209, 191, 255, 244, 226, 215, 217, 139, 172, + 220, 165, 133, 210, 47, 190, 249, 239, 191, 203, 191, 225, 201, 121, 169, 116, 185, 205, 225, 221, 44, 215, 235, + 170, 216, 215, 212, 204, 139, 15, 119, 133, 78, 248, 173, 4, 255, 149, 239, 171, 124, 157, 214, 121, 150, 156, + 37, 141, 206, 147, 247, 141, 170, 139, 93, 158, 148, 85, 242, 67, 121, 155, 64, 187, 117, 158, 102, 115, 106, + 199, 188, 250, 226, 155, 186, 106, 114, 250, 37, 87, 89, 174, 214, 69, 142, 189, 191, 144, 111, 95, 252, 60, + 123, 81, 31, 246, 57, 143, 168, 200, 220, 104, 222, 230, 90, 167, 183, 253, 65, 201, 227, 100, 199, 207, 177, + 55, 108, 0, 158, 148, 171, 95, 242, 117, 13, 127, 239, 171, 114, 159, 87, 117, 33, 173, 170, 116, 135, 143, + 117, 217, 84, 235, 126, 123, 210, 79, 194, 143, 189, 230, 116, 93, 21, 234, 22, 254, 206, 85, 179, 195, 33, + 127, 218, 109, 225, 175, 95, 210, 251, 148, 191, 135, 63, 84, 94, 63, 148, 213, 71, 248, 215, 154, 135, 117, + 150, 238, 11, 248, 75, 215, 101, 197, 131, 79, 247, 251, 117, 186, 190, 195, 127, 86, 184, 0, 210, 166, 206, + 215, 77, 85, 212, 7, 248, 103, 89, 223, 229, 149, 183, 102, 56, 172, 217, 11, 108, 22, 126, 254, 249, 215, + 153, 157, 192, 54, 191, 207, 183, 241, 241, 195, 83, 108, 113, 104, 6, 219, 18, 255, 122, 72, 43, 37, 191, + 87, 85, 201, 93, 175, 26, 252, 187, 80, 155, 178, 213, 101, 157, 127, 170, 163, 61, 226, 195, 126, 111, 222, + 215, 77, 213, 31, 238, 143, 239, 127, 72, 202, 77, 2, 115, 54, 59, 8, 228, 83, 220, 22, 10, 91, 42, + 233, 173, 116, 107, 136, 38, 218, 242, 182, 80, 253, 157, 252, 1, 126, 76, 96, 166, 171, 188, 2, 90, 164, + 46, 170, 156, 183, 21, 254, 72, 235, 228, 54, 87, 121, 69, 244, 91, 35, 101, 155, 254, 79, 190, 62, 91, + 165, 58, 207, 78, 7, 134, 80, 168, 58, 191, 133, 253, 240, 198, 176, 46, 183, 205, 78, 5, 232, 19, 127, + 254, 236, 227, 248, 249, 215, 159, 145, 232, 118, 187, 84, 101, 45, 50, 95, 111, 243, 180, 146, 45, 210, 189, + 209, 93, 148, 185, 78, 20, 144, 28, 44, 232, 220, 159, 77, 86, 232, 116, 21, 224, 1, 23, 252, 187, 78, + 132, 192, 133, 31, 204, 18, 32, 214, 251, 92, 213, 58, 217, 52, 21, 82, 176, 125, 65, 166, 3, 15, 170, + 114, 151, 172, 114, 232, 9, 230, 191, 47, 43, 154, 112, 73, 235, 177, 222, 22, 240, 109, 107, 0, 185, 10, + 246, 255, 70, 133, 187, 215, 112, 152, 180, 79, 70, 248, 202, 118, 11, 12, 0, 122, 209, 101, 178, 73, 171, + 118, 103, 201, 234, 0, 175, 166, 74, 11, 249, 45, 212, 82, 190, 124, 149, 101, 121, 182, 196, 85, 41, 54, + 5, 31, 64, 24, 25, 44, 47, 79, 208, 95, 92, 255, 139, 222, 80, 47, 181, 110, 160, 243, 135, 187, 28, + 182, 63, 127, 232, 46, 8, 178, 208, 20, 63, 196, 237, 221, 167, 21, 180, 88, 3, 199, 14, 52, 127, 140, + 231, 49, 21, 221, 165, 26, 86, 23, 250, 178, 141, 254, 107, 149, 111, 250, 12, 20, 73, 5, 215, 217, 178, + 251, 11, 60, 237, 183, 194, 115, 90, 123, 45, 15, 12, 207, 207, 63, 237, 75, 13, 11, 251, 23, 96, 121, + 55, 244, 94, 66, 156, 226, 22, 183, 116, 157, 238, 211, 85, 177, 45, 144, 205, 206, 147, 203, 58, 73, 183, + 219, 242, 65, 195, 198, 212, 53, 62, 7, 186, 132, 109, 223, 149, 247, 240, 199, 66, 173, 170, 60, 253, 184, + 47, 129, 124, 53, 236, 93, 157, 239, 247, 248, 78, 125, 87, 149, 205, 237, 29, 116, 4, 236, 16, 7, 49, + 195, 62, 183, 37, 30, 119, 120, 43, 93, 127, 76, 234, 42, 93, 231, 240, 77, 94, 175, 69, 176, 140, 20, + 35, 175, 109, 143, 151, 253, 173, 114, 15, 147, 2, 90, 195, 141, 207, 171, 48, 47, 99, 153, 4, 147, 251, + 22, 119, 44, 208, 22, 62, 3, 90, 135, 135, 227, 218, 250, 161, 180, 76, 190, 195, 191, 228, 129, 97, 26, + 194, 50, 214, 101, 54, 69, 202, 81, 131, 129, 97, 202, 6, 186, 33, 38, 64, 63, 246, 92, 74, 151, 75, + 67, 2, 115, 254, 244, 58, 173, 128, 33, 45, 61, 226, 146, 5, 159, 223, 152, 126, 58, 92, 249, 29, 241, + 189, 49, 188, 153, 31, 39, 39, 127, 242, 184, 222, 49, 110, 27, 105, 61, 200, 115, 67, 237, 31, 231, 170, + 102, 151, 120, 126, 215, 165, 46, 30, 179, 87, 64, 197, 32, 140, 119, 176, 212, 189, 190, 142, 236, 95, 107, + 13, 71, 47, 71, 124, 30, 102, 160, 239, 83, 21, 96, 44, 118, 26, 21, 62, 78, 30, 10, 20, 12, 73, + 169, 204, 234, 61, 109, 46, 30, 45, 142, 160, 30, 56, 239, 85, 237, 94, 237, 108, 64, 75, 82, 100, 241, + 215, 126, 238, 159, 217, 222, 172, 61, 126, 182, 182, 135, 119, 158, 188, 170, 170, 244, 128, 210, 193, 253, 8, + 66, 172, 172, 118, 44, 69, 240, 71, 226, 73, 227, 15, 227, 122, 50, 219, 72, 72, 231, 246, 14, 41, 252, + 85, 170, 237, 33, 185, 79, 183, 5, 202, 150, 98, 155, 211, 112, 238, 139, 170, 110, 210, 109, 178, 3, 229, + 18, 207, 22, 188, 183, 79, 65, 41, 111, 9, 2, 175, 123, 111, 253, 54, 141, 90, 227, 32, 222, 133, 214, + 6, 127, 52, 10, 154, 183, 78, 230, 27, 90, 6, 224, 23, 165, 98, 221, 197, 91, 191, 33, 77, 208, 124, + 254, 88, 222, 215, 61, 183, 50, 65, 219, 156, 207, 132, 30, 217, 197, 64, 147, 33, 61, 214, 91, 27, 97, + 52, 42, 229, 171, 16, 188, 61, 95, 168, 11, 119, 89, 130, 254, 54, 233, 61, 60, 129, 101, 109, 52, 203, + 61, 96, 181, 102, 160, 115, 115, 76, 150, 168, 176, 160, 166, 184, 189, 231, 61, 70, 93, 249, 190, 72, 147, + 148, 148, 173, 162, 108, 244, 246, 176, 80, 26, 149, 153, 8, 163, 78, 72, 101, 9, 223, 192, 162, 155, 163, + 215, 64, 187, 231, 119, 168, 28, 244, 133, 6, 60, 74, 214, 248, 12, 79, 194, 192, 158, 167, 120, 120, 240, + 10, 81, 231, 59, 141, 87, 80, 123, 62, 161, 133, 23, 191, 250, 119, 10, 104, 163, 215, 209, 18, 127, 93, + 38, 124, 158, 98, 93, 117, 152, 200, 123, 208, 46, 234, 252, 138, 143, 160, 215, 65, 149, 215, 77, 165, 254, + 154, 110, 155, 208, 149, 54, 199, 163, 212, 228, 86, 49, 197, 119, 243, 108, 150, 20, 76, 243, 150, 208, 81, + 91, 171, 229, 121, 66, 170, 194, 0, 33, 30, 27, 210, 58, 85, 175, 243, 247, 57, 177, 184, 128, 230, 248, + 87, 58, 220, 116, 206, 221, 9, 255, 235, 91, 119, 168, 73, 155, 42, 84, 134, 234, 41, 48, 37, 80, 49, + 73, 229, 166, 53, 162, 229, 89, 40, 232, 2, 230, 132, 244, 195, 157, 32, 41, 130, 74, 59, 79, 222, 193, + 136, 88, 99, 76, 147, 37, 142, 122, 41, 43, 0, 45, 160, 62, 205, 23, 130, 133, 186, 109, 64, 39, 5, + 1, 34, 47, 27, 2, 251, 23, 105, 145, 24, 9, 73, 8, 238, 214, 99, 46, 240, 43, 108, 211, 10, 6, + 161, 155, 53, 104, 107, 122, 211, 108, 103, 201, 170, 1, 109, 163, 198, 57, 192, 197, 244, 144, 108, 139, 143, + 249, 246, 16, 19, 40, 17, 193, 188, 42, 65, 145, 77, 85, 91, 48, 35, 65, 133, 9, 213, 251, 109, 60, + 147, 166, 183, 194, 237, 225, 163, 161, 251, 244, 237, 182, 92, 165, 200, 27, 240, 44, 227, 255, 113, 121, 208, + 24, 176, 45, 117, 83, 97, 171, 176, 95, 107, 252, 101, 5, 111, 160, 153, 192, 90, 14, 242, 123, 250, 96, + 87, 102, 13, 221, 122, 30, 82, 189, 59, 131, 149, 129, 213, 70, 35, 206, 25, 73, 154, 214, 93, 220, 78, + 163, 61, 82, 38, 54, 212, 228, 224, 83, 20, 27, 194, 95, 232, 84, 207, 147, 111, 129, 12, 150, 60, 206, + 37, 81, 209, 18, 199, 184, 228, 199, 26, 55, 200, 126, 201, 215, 169, 116, 141, 114, 101, 161, 184, 187, 255, + 146, 179, 200, 132, 101, 4, 3, 127, 60, 147, 237, 5, 226, 192, 139, 83, 1, 210, 8, 180, 117, 165, 233, + 182, 37, 39, 25, 87, 10, 239, 186, 164, 208, 227, 87, 11, 117, 159, 86, 5, 223, 233, 82, 236, 31, 72, + 220, 110, 203, 132, 67, 174, 88, 120, 141, 182, 24, 16, 13, 63, 70, 252, 224, 97, 171, 100, 202, 9, 181, + 162, 167, 9, 36, 80, 87, 158, 220, 47, 94, 118, 199, 244, 234, 29, 147, 60, 173, 214, 119, 111, 133, 252, + 58, 196, 77, 207, 64, 117, 128, 135, 180, 191, 198, 60, 49, 254, 208, 140, 87, 245, 173, 233, 3, 174, 195, + 181, 8, 39, 233, 131, 95, 234, 222, 32, 206, 249, 189, 112, 187, 196, 127, 120, 224, 253, 246, 204, 174, 187, + 85, 160, 123, 158, 183, 250, 127, 220, 161, 62, 255, 29, 106, 214, 229, 172, 195, 103, 212, 113, 211, 76, 214, + 237, 166, 6, 33, 183, 99, 18, 64, 5, 128, 76, 167, 40, 134, 95, 252, 236, 109, 237, 79, 192, 48, 209, + 56, 165, 117, 190, 91, 109, 15, 231, 119, 141, 250, 248, 228, 155, 151, 14, 42, 12, 42, 255, 4, 55, 5, + 236, 0, 25, 96, 102, 59, 133, 61, 167, 143, 134, 212, 160, 14, 105, 122, 171, 179, 58, 212, 57, 30, 244, + 171, 205, 70, 231, 117, 184, 103, 243, 14, 244, 75, 47, 137, 132, 91, 89, 38, 143, 252, 8, 7, 149, 195, + 53, 128, 6, 51, 98, 44, 118, 167, 122, 215, 221, 31, 82, 212, 2, 110, 67, 86, 184, 102, 135, 221, 236, + 75, 144, 78, 48, 113, 67, 24, 91, 249, 64, 15, 73, 73, 167, 42, 195, 143, 63, 229, 171, 87, 178, 101, + 47, 92, 247, 116, 100, 110, 14, 187, 85, 185, 213, 97, 179, 84, 162, 249, 105, 2, 141, 21, 91, 148, 31, + 196, 185, 210, 4, 5, 167, 119, 91, 125, 130, 204, 255, 0, 63, 26, 9, 151, 249, 125, 14, 77, 238, 93, + 73, 150, 232, 27, 226, 113, 111, 211, 61, 252, 251, 13, 156, 32, 52, 201, 93, 252, 244, 234, 253, 183, 248, + 247, 167, 58, 175, 128, 254, 249, 111, 95, 164, 231, 242, 4, 20, 253, 33, 67, 185, 121, 77, 198, 227, 185, + 42, 142, 136, 191, 184, 145, 184, 68, 69, 161, 201, 63, 148, 81, 209, 116, 46, 175, 104, 103, 157, 75, 144, + 111, 65, 247, 251, 124, 141, 2, 63, 217, 90, 233, 133, 92, 16, 189, 28, 3, 182, 205, 227, 247, 50, 184, + 253, 152, 113, 193, 191, 143, 220, 201, 128, 240, 111, 243, 218, 42, 161, 122, 2, 159, 73, 21, 158, 138, 117, + 83, 85, 200, 99, 132, 167, 140, 53, 131, 27, 38, 69, 212, 119, 91, 192, 117, 11, 84, 116, 116, 67, 141, + 55, 101, 183, 154, 192, 253, 245, 154, 73, 206, 201, 88, 173, 19, 125, 87, 54, 219, 12, 53, 115, 144, 49, + 26, 148, 40, 214, 202, 45, 109, 146, 13, 214, 152, 128, 23, 138, 187, 204, 100, 135, 68, 95, 107, 182, 254, + 85, 138, 201, 128, 247, 106, 157, 67, 151, 67, 134, 232, 244, 19, 159, 88, 125, 142, 219, 122, 83, 252, 45, + 124, 149, 130, 247, 138, 29, 176, 6, 13, 47, 160, 204, 64, 126, 69, 6, 118, 207, 22, 207, 237, 36, 39, + 56, 21, 216, 79, 80, 106, 212, 26, 126, 95, 29, 18, 242, 124, 193, 53, 36, 221, 139, 186, 168, 79, 23, + 202, 205, 16, 125, 10, 112, 169, 185, 43, 183, 217, 60, 185, 110, 106, 188, 167, 0, 143, 219, 161, 214, 9, + 172, 200, 12, 156, 76, 36, 240, 99, 205, 19, 154, 112, 187, 48, 250, 199, 207, 70, 192, 180, 214, 192, 12, + 34, 160, 7, 252, 168, 138, 255, 211, 248, 118, 155, 22, 219, 184, 101, 243, 111, 104, 32, 29, 5, 128, 219, + 185, 112, 29, 181, 104, 17, 175, 8, 13, 136, 194, 43, 21, 55, 101, 189, 145, 119, 240, 148, 154, 187, 3, + 26, 103, 82, 33, 170, 246, 5, 58, 188, 217, 147, 173, 84, 120, 82, 205, 224, 18, 190, 106, 13, 91, 156, + 220, 216, 250, 19, 112, 195, 246, 90, 29, 52, 38, 49, 173, 124, 87, 149, 205, 190, 175, 161, 209, 219, 230, + 246, 113, 139, 239, 176, 97, 6, 26, 223, 55, 181, 57, 21, 32, 2, 203, 228, 68, 60, 22, 85, 186, 47, + 208, 87, 1, 55, 77, 205, 54, 1, 124, 199, 107, 230, 14, 206, 13, 28, 220, 133, 98, 235, 205, 146, 95, + 149, 75, 9, 141, 99, 121, 58, 201, 125, 89, 168, 245, 182, 201, 64, 211, 165, 35, 137, 122, 221, 171, 235, + 203, 254, 92, 152, 207, 122, 247, 125, 115, 134, 81, 208, 39, 240, 137, 225, 18, 112, 239, 119, 98, 81, 188, + 94, 102, 41, 51, 143, 50, 102, 64, 160, 155, 20, 38, 7, 115, 169, 209, 71, 182, 213, 67, 98, 196, 222, + 190, 189, 107, 84, 177, 13, 233, 230, 151, 42, 225, 39, 201, 14, 181, 149, 252, 211, 58, 167, 71, 154, 92, + 60, 15, 42, 201, 26, 218, 23, 25, 20, 238, 118, 10, 151, 27, 102, 9, 162, 62, 227, 196, 178, 146, 126, + 35, 163, 7, 48, 53, 35, 120, 230, 201, 213, 125, 94, 85, 64, 129, 58, 89, 130, 30, 116, 141, 207, 175, + 212, 27, 211, 205, 18, 21, 161, 122, 226, 84, 248, 200, 191, 62, 132, 13, 69, 63, 89, 19, 139, 101, 165, + 5, 29, 50, 230, 106, 176, 122, 184, 232, 201, 95, 110, 174, 222, 25, 50, 33, 6, 237, 118, 68, 139, 211, + 145, 140, 45, 211, 134, 102, 28, 196, 215, 104, 246, 203, 31, 162, 131, 219, 243, 115, 175, 83, 231, 90, 246, + 238, 237, 48, 248, 199, 218, 93, 124, 179, 29, 108, 228, 149, 186, 129, 77, 120, 179, 217, 132, 44, 17, 118, + 201, 74, 222, 117, 216, 81, 71, 9, 200, 178, 117, 129, 180, 65, 31, 35, 103, 199, 157, 70, 139, 85, 67, + 6, 101, 56, 156, 61, 34, 153, 182, 106, 200, 82, 161, 153, 190, 160, 202, 171, 93, 161, 144, 87, 57, 77, + 38, 221, 160, 228, 128, 47, 232, 152, 67, 223, 39, 114, 241, 1, 70, 190, 43, 182, 219, 66, 131, 222, 13, + 74, 211, 233, 216, 133, 235, 112, 246, 15, 240, 159, 139, 124, 91, 167, 49, 233, 194, 219, 18, 179, 230, 60, + 0, 79, 218, 123, 26, 130, 119, 110, 220, 126, 142, 180, 148, 216, 45, 184, 200, 107, 224, 17, 58, 192, 130, + 205, 30, 101, 252, 198, 8, 67, 231, 155, 110, 163, 45, 201, 5, 154, 217, 181, 220, 20, 156, 167, 181, 223, + 241, 123, 94, 22, 119, 171, 48, 58, 34, 185, 93, 18, 231, 51, 158, 39, 230, 74, 142, 74, 6, 95, 122, + 144, 93, 228, 232, 99, 38, 207, 149, 251, 210, 158, 5, 86, 37, 244, 160, 232, 51, 62, 167, 174, 16, 145, + 91, 21, 183, 13, 244, 172, 217, 98, 98, 7, 234, 134, 230, 245, 92, 168, 35, 58, 43, 59, 174, 186, 74, + 97, 246, 152, 158, 146, 19, 216, 86, 144, 33, 64, 190, 167, 243, 228, 39, 10, 57, 128, 227, 36, 170, 57, + 218, 179, 161, 179, 133, 130, 150, 141, 254, 5, 220, 139, 45, 201, 154, 150, 205, 244, 57, 209, 187, 130, 86, + 192, 170, 88, 215, 31, 202, 111, 197, 80, 222, 39, 97, 52, 99, 99, 236, 3, 156, 246, 202, 27, 244, 195, + 93, 1, 19, 67, 182, 111, 140, 11, 40, 151, 65, 45, 84, 103, 112, 135, 6, 150, 117, 234, 140, 239, 48, + 72, 218, 154, 49, 12, 32, 124, 190, 108, 191, 1, 51, 138, 51, 100, 14, 46, 243, 8, 239, 70, 219, 190, + 244, 107, 247, 16, 176, 14, 125, 19, 14, 60, 51, 212, 47, 230, 49, 115, 212, 229, 102, 77, 134, 46, 214, + 225, 138, 1, 69, 61, 106, 170, 186, 204, 156, 177, 150, 26, 4, 218, 130, 17, 121, 189, 13, 26, 164, 194, + 139, 170, 135, 230, 99, 188, 97, 220, 193, 73, 190, 219, 215, 7, 220, 234, 53, 168, 74, 56, 22, 52, 216, + 88, 131, 198, 233, 160, 134, 103, 222, 234, 139, 24, 191, 141, 33, 226, 0, 126, 95, 29, 94, 244, 174, 118, + 98, 183, 193, 102, 222, 26, 203, 123, 136, 187, 63, 195, 98, 123, 221, 61, 98, 161, 107, 32, 172, 93, 160, + 39, 52, 231, 111, 241, 234, 155, 176, 231, 64, 207, 140, 139, 42, 77, 248, 35, 14, 187, 146, 195, 150, 101, + 5, 175, 15, 155, 175, 240, 106, 182, 80, 110, 100, 135, 196, 122, 141, 82, 184, 169, 177, 243, 6, 104, 142, + 253, 52, 163, 213, 217, 186, 132, 165, 99, 179, 226, 213, 230, 135, 168, 25, 141, 94, 75, 156, 156, 37, 219, + 153, 97, 6, 254, 160, 58, 129, 133, 1, 203, 162, 97, 20, 175, 203, 236, 48, 100, 63, 51, 102, 51, 232, + 141, 46, 50, 134, 191, 172, 202, 172, 32, 7, 6, 119, 142, 78, 126, 208, 221, 254, 155, 120, 206, 215, 196, + 59, 191, 158, 45, 20, 253, 249, 111, 244, 39, 252, 119, 62, 159, 255, 44, 70, 121, 108, 139, 226, 207, 144, + 155, 17, 35, 198, 85, 155, 100, 122, 243, 172, 178, 98, 185, 236, 143, 126, 83, 84, 58, 104, 120, 60, 120, + 103, 55, 104, 7, 109, 17, 62, 154, 47, 35, 214, 210, 190, 145, 67, 72, 150, 150, 165, 109, 247, 228, 237, + 50, 108, 138, 201, 15, 248, 124, 5, 34, 97, 15, 170, 18, 153, 36, 75, 142, 172, 99, 74, 156, 39, 151, + 173, 65, 39, 108, 133, 216, 111, 225, 96, 205, 216, 40, 129, 119, 24, 114, 30, 22, 138, 2, 28, 210, 58, + 23, 187, 38, 211, 255, 66, 113, 24, 25, 83, 56, 168, 147, 196, 84, 104, 72, 243, 228, 149, 58, 0, 205, + 174, 116, 14, 119, 104, 197, 161, 28, 110, 124, 10, 244, 79, 105, 84, 90, 91, 40, 234, 73, 26, 163, 208, + 87, 61, 159, 118, 254, 221, 169, 236, 26, 218, 130, 167, 56, 190, 179, 49, 139, 242, 180, 141, 5, 126, 142, + 47, 189, 142, 113, 203, 15, 29, 187, 143, 139, 9, 152, 39, 63, 106, 188, 44, 180, 36, 212, 112, 0, 247, + 163, 89, 226, 79, 206, 64, 251, 44, 66, 40, 42, 28, 90, 2, 200, 59, 140, 33, 97, 128, 83, 71, 15, + 235, 7, 12, 47, 140, 139, 102, 23, 130, 232, 11, 228, 165, 182, 159, 94, 178, 99, 103, 10, 13, 185, 79, + 3, 115, 247, 159, 70, 101, 131, 55, 238, 232, 247, 237, 233, 210, 133, 58, 160, 231, 150, 123, 205, 161, 60, + 66, 146, 126, 84, 139, 241, 194, 180, 76, 155, 123, 190, 121, 191, 210, 7, 181, 62, 103, 223, 76, 104, 238, + 99, 201, 7, 126, 133, 239, 110, 218, 107, 18, 9, 74, 165, 211, 75, 253, 115, 136, 109, 138, 99, 96, 3, + 151, 183, 55, 254, 150, 21, 162, 69, 182, 130, 162, 34, 75, 221, 210, 113, 119, 229, 189, 119, 113, 9, 144, + 7, 190, 208, 138, 139, 245, 238, 42, 81, 93, 109, 213, 142, 72, 245, 85, 72, 243, 107, 103, 28, 46, 240, + 34, 48, 6, 246, 69, 163, 29, 180, 46, 214, 13, 40, 5, 158, 177, 143, 149, 0, 220, 214, 85, 126, 91, + 40, 12, 247, 199, 208, 50, 16, 136, 219, 108, 230, 241, 129, 133, 90, 229, 119, 233, 125, 193, 193, 73, 75, + 191, 199, 37, 46, 31, 94, 72, 234, 244, 224, 71, 161, 144, 209, 204, 6, 125, 159, 95, 92, 27, 14, 163, + 129, 89, 211, 173, 58, 53, 65, 40, 232, 155, 129, 147, 127, 151, 163, 168, 200, 36, 182, 13, 53, 142, 53, + 237, 226, 190, 42, 65, 210, 236, 52, 111, 159, 124, 3, 35, 157, 193, 17, 6, 102, 205, 60, 220, 122, 4, + 220, 221, 189, 216, 237, 242, 172, 72, 107, 144, 40, 220, 97, 225, 5, 67, 219, 238, 196, 20, 254, 0, 226, + 136, 124, 19, 237, 213, 48, 204, 201, 133, 203, 176, 145, 116, 161, 22, 234, 131, 76, 122, 5, 4, 114, 246, + 144, 86, 25, 139, 45, 208, 241, 97, 184, 179, 238, 42, 225, 32, 217, 44, 164, 49, 192, 6, 237, 95, 203, + 133, 114, 214, 105, 182, 20, 73, 136, 5, 137, 68, 114, 18, 211, 123, 109, 35, 246, 174, 208, 154, 166, 223, + 238, 97, 161, 88, 86, 161, 153, 130, 199, 71, 49, 76, 21, 198, 131, 25, 105, 70, 54, 38, 86, 71, 188, + 44, 29, 10, 247, 176, 214, 93, 77, 59, 154, 110, 31, 210, 131, 102, 65, 10, 173, 161, 24, 176, 209, 141, + 38, 228, 209, 208, 142, 245, 100, 255, 11, 239, 191, 132, 151, 105, 35, 40, 102, 108, 242, 2, 53, 5, 141, + 163, 165, 130, 35, 247, 215, 255, 96, 90, 161, 224, 169, 99, 43, 46, 218, 216, 239, 105, 153, 222, 133, 229, + 102, 96, 131, 118, 141, 174, 189, 157, 164, 197, 5, 221, 18, 123, 124, 121, 83, 231, 251, 75, 85, 151, 47, + 103, 236, 211, 120, 40, 208, 124, 217, 33, 20, 226, 95, 180, 149, 180, 147, 211, 12, 114, 61, 39, 150, 233, + 242, 197, 207, 49, 229, 195, 119, 141, 117, 98, 60, 209, 100, 232, 248, 228, 96, 184, 96, 236, 230, 235, 92, + 18, 190, 46, 75, 60, 121, 64, 176, 146, 220, 240, 251, 166, 184, 187, 84, 29, 194, 99, 56, 98, 132, 242, + 165, 93, 116, 12, 1, 210, 249, 92, 163, 8, 48, 240, 38, 204, 186, 155, 93, 91, 124, 56, 75, 119, 244, + 44, 212, 198, 138, 121, 165, 222, 135, 219, 189, 97, 106, 196, 65, 210, 255, 3, 102, 207, 102, 47, 22, 68, + 178, 123, 122, 246, 245, 75, 69, 156, 182, 74, 117, 77, 174, 1, 51, 57, 219, 200, 27, 151, 162, 65, 154, + 59, 81, 179, 56, 80, 240, 208, 209, 227, 220, 200, 133, 133, 242, 38, 119, 82, 204, 243, 57, 5, 178, 58, + 51, 230, 169, 176, 103, 55, 52, 99, 145, 97, 73, 131, 10, 222, 66, 33, 191, 162, 112, 52, 96, 245, 188, + 152, 192, 115, 128, 177, 240, 237, 150, 205, 53, 102, 132, 226, 135, 134, 115, 130, 28, 11, 196, 205, 66, 1, + 175, 245, 164, 6, 112, 113, 118, 249, 66, 99, 214, 201, 144, 201, 116, 220, 57, 71, 73, 162, 74, 49, 83, + 143, 178, 63, 249, 238, 17, 178, 222, 93, 170, 88, 12, 19, 71, 94, 201, 53, 202, 40, 44, 100, 244, 70, + 187, 166, 132, 164, 187, 184, 166, 103, 48, 67, 136, 61, 177, 101, 155, 28, 138, 63, 130, 187, 84, 117, 136, + 185, 213, 92, 123, 162, 186, 71, 77, 2, 104, 244, 185, 201, 21, 70, 229, 223, 247, 41, 21, 133, 32, 174, + 165, 29, 157, 102, 43, 145, 54, 95, 76, 51, 252, 23, 250, 61, 220, 170, 63, 197, 187, 193, 123, 27, 250, + 212, 121, 22, 110, 175, 41, 122, 11, 190, 124, 188, 153, 49, 98, 198, 55, 54, 70, 237, 69, 218, 229, 99, + 12, 138, 126, 216, 222, 175, 29, 210, 170, 173, 214, 77, 44, 231, 34, 223, 215, 119, 209, 32, 3, 160, 175, + 204, 196, 44, 120, 154, 50, 49, 61, 77, 92, 239, 35, 165, 0, 14, 68, 0, 132, 59, 120, 43, 46, 255, + 12, 159, 146, 97, 165, 219, 250, 60, 185, 145, 28, 48, 160, 151, 229, 159, 140, 228, 163, 3, 69, 198, 37, + 51, 50, 19, 37, 64, 233, 98, 216, 10, 70, 49, 187, 65, 158, 136, 179, 50, 24, 213, 214, 89, 154, 215, + 91, 248, 100, 85, 126, 186, 78, 107, 140, 149, 9, 249, 26, 246, 91, 188, 19, 152, 72, 250, 100, 37, 95, + 0, 57, 240, 39, 172, 134, 238, 241, 190, 141, 177, 216, 152, 213, 246, 109, 9, 55, 73, 77, 138, 32, 218, + 204, 145, 252, 63, 22, 123, 155, 191, 246, 21, 178, 16, 62, 188, 11, 101, 236, 236, 212, 74, 83, 109, 121, + 211, 73, 241, 81, 185, 227, 110, 220, 215, 28, 163, 187, 105, 89, 234, 234, 128, 237, 2, 141, 221, 231, 118, + 76, 54, 108, 34, 89, 29, 64, 151, 204, 43, 52, 80, 97, 83, 47, 177, 107, 232, 238, 37, 167, 251, 98, + 196, 45, 28, 100, 61, 3, 29, 76, 25, 46, 89, 86, 102, 237, 249, 109, 80, 54, 94, 162, 124, 107, 188, + 232, 236, 105, 119, 214, 125, 108, 81, 109, 198, 12, 157, 162, 189, 102, 125, 80, 162, 193, 217, 221, 128, 65, + 61, 119, 57, 8, 90, 153, 16, 174, 12, 57, 119, 204, 242, 91, 207, 237, 216, 8, 186, 200, 206, 231, 25, + 165, 56, 233, 0, 193, 126, 244, 246, 208, 110, 160, 238, 196, 56, 98, 244, 138, 91, 126, 242, 141, 116, 182, + 201, 219, 163, 109, 161, 233, 246, 100, 54, 125, 5, 87, 164, 207, 176, 75, 11, 101, 18, 155, 80, 183, 199, + 181, 70, 225, 128, 9, 252, 232, 185, 40, 140, 95, 5, 77, 146, 237, 245, 36, 142, 122, 135, 115, 128, 107, + 215, 183, 100, 70, 196, 147, 83, 129, 252, 133, 71, 234, 37, 8, 121, 55, 89, 147, 249, 228, 185, 174, 203, + 106, 32, 154, 230, 137, 82, 105, 164, 32, 178, 19, 28, 147, 99, 210, 206, 1, 235, 145, 72, 252, 42, 127, + 131, 214, 225, 224, 61, 62, 161, 132, 9, 150, 209, 54, 85, 231, 105, 209, 109, 120, 93, 240, 58, 56, 234, + 47, 68, 15, 116, 56, 253, 176, 29, 53, 131, 151, 233, 20, 111, 159, 94, 227, 246, 91, 241, 14, 122, 158, + 193, 172, 101, 81, 161, 172, 19, 93, 151, 123, 49, 4, 249, 185, 186, 156, 20, 83, 180, 130, 139, 114, 27, + 113, 36, 186, 230, 152, 56, 196, 176, 33, 111, 40, 67, 215, 81, 205, 26, 133, 55, 6, 140, 185, 97, 33, + 3, 49, 22, 8, 27, 82, 54, 143, 217, 84, 188, 171, 1, 41, 147, 199, 163, 241, 105, 206, 94, 127, 146, + 148, 149, 81, 220, 80, 112, 211, 58, 20, 119, 137, 38, 240, 134, 142, 13, 185, 41, 142, 16, 96, 209, 126, + 125, 148, 53, 169, 243, 77, 32, 36, 167, 221, 166, 10, 230, 232, 185, 11, 229, 42, 135, 85, 205, 249, 24, + 88, 101, 31, 51, 87, 188, 223, 127, 2, 217, 102, 35, 93, 221, 75, 63, 255, 206, 27, 28, 61, 238, 175, + 15, 63, 6, 82, 247, 134, 207, 124, 251, 196, 187, 115, 147, 228, 5, 13, 7, 88, 61, 133, 230, 86, 244, + 63, 86, 31, 147, 43, 69, 216, 14, 133, 6, 13, 198, 217, 219, 11, 2, 4, 152, 177, 187, 232, 19, 136, + 12, 209, 62, 181, 23, 22, 73, 103, 240, 142, 4, 139, 139, 148, 112, 4, 231, 220, 31, 68, 125, 11, 101, + 211, 6, 245, 210, 36, 206, 28, 128, 197, 203, 90, 89, 157, 67, 132, 26, 118, 134, 127, 138, 231, 67, 98, + 223, 60, 175, 9, 52, 232, 250, 125, 47, 189, 58, 59, 15, 77, 64, 12, 119, 219, 242, 182, 0, 245, 204, + 95, 46, 106, 86, 55, 213, 61, 172, 25, 197, 175, 98, 20, 93, 153, 102, 122, 128, 81, 142, 203, 111, 232, + 115, 203, 244, 136, 75, 240, 8, 216, 136, 73, 67, 209, 129, 166, 203, 105, 224, 35, 208, 83, 248, 190, 65, + 191, 26, 29, 207, 122, 162, 96, 16, 122, 196, 40, 208, 16, 63, 79, 222, 48, 145, 45, 161, 143, 37, 208, + 24, 108, 143, 233, 109, 105, 45, 80, 150, 36, 39, 141, 154, 7, 250, 125, 170, 239, 98, 142, 19, 184, 249, + 222, 125, 134, 229, 26, 204, 58, 97, 231, 173, 81, 197, 40, 174, 49, 182, 245, 83, 144, 89, 254, 144, 155, + 207, 42, 55, 199, 5, 211, 184, 80, 159, 65, 249, 201, 70, 40, 19, 154, 48, 226, 78, 28, 137, 175, 105, + 113, 250, 43, 101, 226, 145, 196, 43, 53, 154, 229, 179, 124, 227, 4, 26, 186, 125, 74, 252, 44, 203, 1, + 107, 163, 38, 107, 82, 170, 56, 100, 221, 198, 17, 160, 131, 195, 172, 179, 53, 155, 83, 92, 147, 184, 56, + 137, 188, 184, 41, 184, 6, 206, 248, 130, 75, 87, 198, 218, 152, 208, 116, 105, 140, 86, 108, 48, 111, 201, + 254, 241, 250, 55, 7, 161, 134, 66, 70, 204, 96, 37, 76, 181, 200, 142, 4, 15, 182, 247, 254, 183, 56, + 76, 24, 49, 96, 15, 82, 242, 143, 118, 142, 162, 68, 171, 95, 173, 131, 230, 49, 250, 153, 166, 248, 21, + 172, 83, 106, 255, 66, 234, 108, 11, 12, 49, 42, 220, 14, 132, 56, 166, 225, 62, 208, 7, 192, 105, 224, + 237, 80, 75, 178, 184, 162, 56, 239, 222, 203, 35, 246, 206, 94, 44, 118, 40, 127, 107, 67, 161, 35, 236, + 187, 45, 149, 31, 30, 206, 189, 36, 231, 28, 134, 36, 254, 20, 67, 12, 172, 55, 153, 119, 103, 112, 55, + 94, 167, 205, 237, 93, 237, 255, 184, 80, 37, 58, 62, 187, 63, 147, 9, 215, 254, 137, 246, 109, 160, 195, + 116, 27, 31, 3, 234, 107, 75, 5, 103, 116, 57, 24, 45, 90, 247, 87, 242, 58, 208, 228, 174, 141, 217, + 211, 83, 182, 21, 103, 141, 241, 184, 225, 31, 102, 102, 8, 24, 7, 236, 235, 231, 238, 34, 191, 31, 128, + 52, 56, 167, 123, 126, 219, 21, 72, 2, 21, 22, 209, 32, 155, 216, 228, 0, 146, 90, 14, 215, 128, 246, + 221, 218, 18, 166, 49, 28, 149, 63, 132, 7, 132, 164, 229, 15, 38, 192, 110, 144, 73, 191, 170, 110, 233, + 122, 210, 163, 168, 193, 168, 201, 55, 89, 209, 102, 229, 194, 104, 183, 104, 53, 70, 239, 232, 165, 146, 32, + 248, 237, 204, 242, 105, 49, 76, 161, 123, 212, 249, 0, 228, 244, 176, 27, 8, 189, 210, 18, 143, 158, 67, + 15, 8, 227, 5, 154, 216, 66, 165, 9, 234, 207, 91, 47, 165, 225, 27, 227, 194, 149, 247, 124, 192, 136, + 154, 162, 220, 246, 103, 187, 82, 215, 210, 48, 123, 40, 83, 12, 198, 165, 49, 200, 91, 188, 15, 124, 178, + 173, 247, 35, 245, 112, 86, 252, 209, 145, 123, 70, 240, 48, 180, 196, 53, 227, 124, 105, 8, 214, 220, 230, + 236, 70, 236, 167, 247, 18, 145, 219, 142, 72, 81, 76, 209, 207, 35, 67, 109, 129, 94, 52, 117, 9, 215, + 8, 84, 245, 49, 20, 207, 186, 83, 158, 199, 29, 129, 35, 30, 105, 0, 26, 12, 54, 125, 199, 248, 106, + 53, 65, 13, 116, 173, 75, 81, 85, 52, 171, 14, 208, 99, 204, 79, 192, 220, 254, 78, 144, 144, 96, 81, + 41, 249, 206, 248, 159, 48, 221, 99, 191, 223, 162, 218, 157, 92, 84, 135, 164, 106, 20, 92, 183, 14, 190, + 161, 19, 67, 155, 248, 146, 181, 80, 94, 15, 68, 74, 152, 99, 96, 219, 2, 246, 80, 108, 14, 38, 137, + 247, 88, 44, 107, 223, 225, 65, 126, 183, 15, 229, 158, 54, 20, 79, 4, 115, 151, 152, 247, 227, 142, 98, + 150, 188, 229, 148, 72, 0, 104, 196, 88, 104, 57, 252, 220, 199, 63, 41, 153, 131, 152, 197, 69, 58, 132, + 227, 128, 215, 64, 178, 214, 199, 105, 125, 36, 133, 63, 26, 9, 228, 137, 222, 110, 27, 146, 156, 243, 186, + 145, 195, 239, 14, 211, 45, 84, 110, 0, 150, 208, 234, 75, 33, 232, 37, 252, 156, 141, 243, 10, 63, 202, + 95, 78, 227, 98, 6, 158, 69, 243, 105, 132, 101, 121, 46, 150, 132, 134, 71, 84, 132, 150, 9, 9, 187, + 1, 234, 116, 52, 197, 66, 97, 210, 208, 67, 132, 246, 79, 239, 207, 111, 237, 85, 221, 232, 193, 68, 49, + 52, 199, 164, 246, 98, 224, 49, 100, 131, 197, 67, 185, 17, 203, 171, 143, 75, 208, 235, 224, 7, 212, 233, + 124, 208, 28, 159, 171, 91, 28, 32, 190, 114, 160, 230, 64, 81, 63, 169, 34, 24, 0, 252, 26, 94, 58, + 116, 165, 193, 6, 36, 125, 220, 116, 31, 211, 71, 174, 48, 76, 245, 188, 220, 237, 225, 227, 55, 2, 10, + 251, 26, 33, 107, 242, 236, 245, 129, 181, 212, 239, 56, 179, 44, 244, 200, 75, 5, 177, 79, 128, 59, 253, + 128, 120, 181, 111, 52, 7, 218, 51, 145, 119, 178, 223, 167, 38, 38, 153, 109, 229, 117, 52, 145, 56, 15, + 119, 18, 147, 9, 219, 67, 156, 109, 233, 207, 100, 249, 228, 108, 38, 84, 73, 62, 22, 251, 87, 219, 45, + 169, 122, 49, 15, 19, 217, 191, 80, 100, 144, 167, 165, 106, 246, 53, 233, 176, 234, 96, 34, 162, 78, 156, + 150, 61, 115, 250, 196, 12, 209, 54, 189, 60, 185, 188, 94, 159, 14, 8, 91, 24, 200, 17, 93, 158, 60, + 92, 210, 229, 88, 37, 254, 175, 130, 201, 51, 172, 97, 114, 31, 192, 200, 13, 132, 15, 242, 210, 148, 248, + 146, 40, 154, 124, 129, 100, 176, 16, 3, 49, 100, 18, 61, 117, 179, 247, 50, 61, 197, 152, 181, 80, 187, + 166, 166, 235, 213, 46, 85, 36, 28, 135, 20, 13, 104, 47, 98, 71, 18, 128, 18, 47, 187, 128, 129, 115, + 224, 24, 226, 81, 100, 127, 29, 7, 89, 88, 68, 51, 33, 163, 151, 4, 222, 244, 114, 150, 188, 20, 216, + 166, 151, 52, 192, 151, 4, 221, 244, 18, 125, 124, 6, 10, 138, 231, 34, 114, 19, 190, 166, 131, 41, 179, + 92, 27, 223, 25, 204, 163, 216, 55, 219, 222, 156, 226, 230, 42, 179, 154, 65, 60, 62, 179, 51, 17, 251, + 125, 43, 204, 127, 64, 31, 183, 59, 54, 78, 35, 159, 141, 10, 193, 99, 5, 207, 110, 191, 192, 210, 150, + 219, 76, 219, 254, 98, 17, 120, 45, 250, 51, 161, 108, 253, 168, 19, 118, 211, 138, 69, 166, 133, 65, 120, + 36, 204, 182, 29, 162, 124, 60, 162, 88, 212, 237, 94, 56, 18, 167, 96, 112, 136, 67, 157, 234, 143, 18, + 122, 212, 10, 108, 197, 32, 90, 178, 33, 81, 8, 53, 181, 247, 244, 116, 91, 60, 197, 104, 92, 11, 6, + 39, 154, 135, 214, 160, 162, 157, 195, 130, 61, 215, 189, 100, 100, 248, 98, 207, 184, 141, 226, 156, 102, 71, + 214, 132, 65, 30, 51, 207, 49, 194, 232, 175, 189, 173, 189, 106, 234, 200, 206, 162, 78, 92, 110, 66, 123, + 219, 109, 226, 62, 112, 228, 165, 141, 123, 145, 189, 94, 188, 250, 16, 243, 252, 140, 107, 138, 67, 249, 108, + 107, 26, 132, 163, 238, 187, 110, 250, 214, 191, 162, 50, 152, 212, 190, 93, 205, 115, 49, 193, 233, 130, 203, + 47, 223, 77, 204, 77, 141, 64, 6, 142, 58, 189, 87, 35, 33, 150, 155, 46, 92, 198, 4, 147, 115, 200, + 56, 214, 180, 189, 80, 254, 64, 7, 29, 179, 28, 241, 55, 180, 68, 33, 100, 85, 185, 5, 36, 45, 191, + 44, 106, 116, 78, 102, 35, 16, 145, 50, 120, 38, 100, 189, 130, 230, 97, 181, 138, 116, 68, 108, 179, 14, + 135, 54, 139, 58, 59, 56, 160, 17, 198, 243, 240, 189, 3, 230, 161, 3, 107, 203, 166, 44, 126, 56, 100, + 190, 74, 119, 171, 226, 182, 41, 73, 27, 198, 120, 41, 202, 161, 62, 191, 185, 254, 107, 81, 110, 221, 174, + 1, 151, 21, 132, 11, 248, 243, 226, 234, 45, 66, 33, 33, 9, 227, 41, 67, 101, 146, 142, 138, 44, 33, + 21, 31, 232, 58, 180, 175, 232, 27, 83, 31, 97, 95, 149, 187, 66, 231, 239, 115, 84, 49, 248, 133, 255, + 253, 253, 123, 42, 182, 144, 239, 91, 138, 101, 150, 214, 105, 44, 179, 94, 2, 104, 240, 158, 68, 187, 121, + 102, 209, 140, 210, 230, 83, 177, 45, 210, 234, 208, 1, 36, 140, 28, 221, 178, 151, 104, 127, 87, 212, 67, + 217, 238, 223, 23, 109, 119, 223, 229, 197, 0, 104, 209, 4, 28, 177, 39, 221, 209, 126, 143, 27, 217, 35, + 224, 20, 98, 119, 178, 180, 21, 17, 25, 27, 205, 59, 140, 194, 50, 215, 133, 153, 53, 152, 113, 158, 79, + 244, 174, 244, 236, 129, 224, 147, 57, 143, 124, 230, 71, 135, 247, 236, 99, 223, 210, 125, 239, 67, 73, 40, + 131, 67, 29, 116, 27, 223, 208, 133, 10, 97, 113, 240, 203, 142, 5, 109, 178, 165, 175, 11, 132, 228, 197, + 31, 132, 179, 175, 2, 6, 191, 168, 7, 191, 18, 108, 229, 64, 211, 201, 9, 211, 213, 112, 62, 57, 131, + 127, 70, 107, 134, 112, 150, 112, 167, 125, 193, 66, 111, 85, 239, 240, 242, 204, 112, 96, 39, 116, 221, 18, + 219, 102, 122, 171, 143, 192, 47, 210, 40, 206, 7, 171, 134, 60, 114, 36, 195, 253, 230, 12, 49, 212, 159, + 123, 10, 218, 206, 182, 80, 121, 212, 130, 26, 110, 44, 50, 133, 31, 114, 117, 91, 219, 0, 130, 237, 163, + 26, 55, 132, 78, 241, 243, 159, 130, 16, 156, 86, 59, 51, 225, 242, 232, 158, 35, 205, 145, 191, 9, 16, + 219, 155, 126, 179, 62, 219, 14, 133, 68, 72, 0, 127, 43, 38, 130, 159, 207, 146, 155, 239, 95, 157, 253, + 219, 255, 252, 243, 32, 197, 117, 103, 242, 170, 249, 116, 17, 146, 74, 130, 21, 88, 133, 196, 16, 138, 49, + 129, 77, 118, 129, 61, 127, 47, 244, 5, 135, 69, 127, 147, 200, 181, 97, 70, 151, 211, 111, 146, 151, 18, + 47, 253, 242, 255, 190, 44, 116, 73, 55, 80, 248, 39, 23, 18, 130, 235, 237, 134, 239, 94, 223, 72, 24, + 252, 175, 83, 68, 155, 54, 65, 95, 3, 72, 133, 66, 153, 187, 116, 143, 136, 117, 229, 186, 72, 141, 27, + 197, 194, 136, 122, 103, 117, 116, 248, 8, 236, 0, 27, 173, 67, 93, 127, 32, 3, 183, 241, 18, 107, 27, + 199, 34, 131, 145, 163, 49, 37, 147, 192, 194, 66, 140, 232, 8, 254, 245, 230, 230, 207, 146, 10, 63, 173, + 163, 45, 29, 150, 112, 198, 182, 193, 214, 164, 87, 166, 69, 190, 232, 184, 26, 224, 185, 204, 80, 65, 245, + 45, 246, 176, 121, 28, 68, 220, 103, 175, 116, 231, 160, 235, 174, 245, 4, 145, 36, 55, 14, 197, 39, 203, + 243, 118, 168, 129, 65, 67, 13, 58, 51, 236, 224, 12, 76, 41, 110, 128, 135, 39, 58, 179, 222, 148, 68, + 231, 226, 196, 104, 133, 23, 185, 141, 154, 112, 69, 11, 173, 242, 48, 88, 234, 7, 98, 127, 50, 196, 30, + 247, 155, 176, 90, 214, 127, 215, 65, 103, 245, 249, 140, 240, 143, 160, 237, 136, 144, 6, 216, 48, 147, 39, + 230, 77, 178, 195, 161, 27, 203, 65, 67, 78, 27, 92, 8, 108, 185, 181, 48, 12, 120, 60, 69, 23, 33, + 98, 179, 227, 224, 112, 67, 166, 60, 242, 83, 97, 57, 39, 250, 152, 16, 95, 65, 121, 251, 168, 16, 83, + 14, 47, 169, 141, 178, 72, 147, 46, 26, 159, 2, 140, 8, 17, 19, 57, 166, 143, 201, 248, 135, 94, 243, + 135, 94, 243, 135, 94, 243, 135, 94, 227, 228, 253, 15, 64, 107, 232, 65, 31, 45, 241, 29, 194, 34, 69, + 187, 73, 80, 181, 161, 14, 235, 135, 179, 174, 192, 103, 48, 5, 255, 161, 124, 253, 161, 124, 253, 161, 124, + 125, 121, 202, 87, 54, 132, 90, 63, 184, 104, 55, 254, 162, 201, 217, 69, 32, 168, 22, 210, 125, 27, 106, + 235, 177, 195, 111, 65, 235, 127, 97, 154, 99, 187, 46, 229, 247, 121, 186, 191, 174, 202, 77, 177, 21, 219, + 112, 208, 38, 55, 178, 252, 35, 54, 118, 163, 210, 189, 190, 43, 235, 171, 88, 104, 52, 190, 148, 104, 121, + 171, 29, 31, 29, 41, 222, 120, 147, 238, 246, 168, 85, 122, 99, 125, 23, 196, 162, 146, 247, 18, 234, 66, + 222, 76, 20, 70, 122, 37, 223, 147, 135, 148, 224, 202, 10, 12, 60, 85, 12, 63, 71, 177, 0, 232, 92, + 54, 153, 71, 104, 7, 215, 117, 177, 214, 164, 233, 130, 152, 36, 60, 248, 172, 149, 71, 62, 182, 0, 93, + 60, 42, 60, 224, 61, 241, 125, 194, 226, 59, 240, 163, 5, 182, 155, 32, 30, 252, 171, 173, 7, 194, 218, + 194, 131, 119, 152, 108, 153, 192, 229, 17, 90, 28, 205, 168, 202, 213, 96, 69, 152, 34, 96, 206, 197, 102, + 96, 151, 146, 75, 65, 224, 19, 255, 82, 186, 174, 74, 205, 81, 210, 123, 94, 112, 191, 38, 236, 42, 175, + 31, 242, 92, 208, 99, 237, 246, 16, 138, 11, 176, 100, 243, 195, 145, 2, 42, 50, 226, 64, 132, 68, 104, + 115, 162, 249, 170, 17, 34, 106, 21, 228, 232, 191, 67, 63, 5, 214, 221, 132, 168, 106, 122, 206, 121, 8, + 41, 255, 69, 9, 103, 252, 245, 132, 18, 162, 195, 187, 219, 217, 220, 180, 134, 35, 178, 106, 188, 226, 190, + 60, 142, 193, 93, 197, 149, 26, 14, 186, 111, 225, 10, 202, 20, 16, 199, 65, 14, 209, 224, 54, 149, 85, + 134, 137, 214, 125, 174, 6, 68, 125, 6, 15, 73, 144, 202, 106, 201, 187, 18, 56, 66, 133, 108, 17, 41, + 55, 78, 81, 85, 14, 243, 5, 201, 76, 110, 255, 137, 36, 101, 11, 14, 12, 109, 115, 156, 151, 76, 222, + 201, 187, 60, 245, 75, 101, 198, 200, 206, 59, 220, 180, 40, 250, 81, 36, 44, 228, 249, 107, 188, 234, 72, + 154, 101, 151, 74, 51, 130, 58, 126, 120, 21, 174, 104, 214, 45, 249, 76, 85, 17, 55, 185, 173, 231, 76, + 108, 164, 133, 143, 75, 224, 50, 255, 250, 41, 57, 209, 64, 31, 226, 115, 76, 126, 48, 32, 249, 200, 126, + 118, 37, 65, 99, 81, 116, 215, 66, 193, 171, 54, 52, 124, 32, 216, 234, 206, 142, 113, 188, 236, 48, 200, + 240, 12, 165, 74, 208, 194, 94, 221, 105, 232, 184, 139, 225, 239, 241, 221, 160, 204, 106, 25, 88, 132, 157, + 125, 151, 86, 171, 174, 46, 34, 133, 75, 250, 101, 72, 218, 168, 135, 223, 183, 231, 52, 49, 151, 168, 111, + 16, 49, 216, 247, 28, 253, 236, 213, 242, 192, 181, 8, 3, 60, 118, 115, 141, 194, 17, 189, 119, 99, 4, + 184, 99, 24, 119, 161, 237, 8, 161, 147, 26, 132, 143, 138, 70, 17, 76, 138, 58, 190, 15, 48, 87, 126, + 240, 250, 48, 117, 65, 7, 251, 24, 89, 228, 130, 180, 57, 184, 83, 251, 245, 45, 48, 54, 69, 208, 124, + 77, 60, 186, 212, 169, 72, 118, 88, 206, 130, 152, 29, 87, 89, 121, 116, 198, 84, 4, 237, 230, 205, 100, + 116, 250, 46, 20, 167, 112, 19, 199, 1, 3, 157, 239, 35, 236, 145, 115, 99, 156, 228, 241, 5, 6, 23, + 249, 180, 74, 192, 124, 144, 25, 118, 163, 210, 60, 166, 30, 55, 29, 202, 11, 151, 130, 174, 209, 151, 155, + 8, 0, 114, 107, 133, 179, 67, 225, 16, 249, 57, 79, 174, 203, 2, 110, 236, 10, 65, 113, 88, 146, 74, + 34, 6, 237, 162, 81, 157, 204, 119, 154, 96, 28, 49, 189, 128, 76, 34, 38, 219, 71, 39, 255, 254, 111, + 255, 235, 207, 255, 33, 77, 190, 56, 90, 241, 166, 87, 138, 132, 55, 70, 159, 155, 149, 122, 125, 120, 155, + 254, 82, 86, 223, 157, 247, 227, 122, 14, 166, 136, 200, 172, 189, 230, 116, 2, 101, 225, 43, 41, 235, 33, + 197, 139, 133, 238, 28, 4, 60, 38, 252, 113, 246, 35, 26, 76, 172, 3, 220, 108, 91, 161, 93, 210, 59, + 178, 246, 62, 137, 80, 110, 180, 47, 101, 103, 210, 56, 47, 28, 198, 82, 227, 210, 101, 57, 195, 131, 81, + 14, 188, 159, 125, 160, 25, 238, 140, 20, 23, 14, 161, 166, 60, 6, 74, 62, 3, 161, 121, 56, 227, 164, + 176, 29, 80, 109, 117, 128, 22, 169, 54, 19, 25, 8, 54, 219, 244, 86, 0, 27, 214, 82, 50, 211, 44, + 193, 66, 181, 215, 0, 35, 171, 208, 120, 45, 107, 236, 107, 250, 73, 186, 162, 232, 55, 89, 24, 216, 251, + 117, 10, 138, 73, 70, 128, 63, 59, 92, 250, 228, 187, 115, 51, 39, 78, 179, 191, 43, 31, 228, 111, 111, + 18, 20, 176, 195, 128, 224, 32, 161, 97, 201, 209, 192, 198, 163, 198, 114, 53, 116, 9, 174, 56, 103, 227, + 187, 115, 137, 10, 158, 104, 149, 137, 18, 72, 161, 254, 32, 144, 223, 137, 64, 112, 233, 61, 2, 113, 115, + 226, 149, 106, 104, 62, 105, 130, 182, 82, 181, 134, 177, 26, 92, 53, 78, 97, 98, 61, 126, 161, 72, 49, + 130, 185, 239, 128, 31, 1, 117, 80, 178, 78, 81, 31, 38, 131, 222, 33, 167, 252, 32, 136, 98, 78, 28, + 234, 56, 148, 33, 190, 235, 93, 23, 39, 247, 231, 118, 117, 170, 168, 88, 151, 180, 136, 65, 154, 156, 38, + 29, 202, 253, 148, 41, 51, 181, 67, 83, 183, 152, 199, 28, 205, 64, 123, 201, 239, 249, 202, 129, 249, 230, + 165, 1, 229, 48, 225, 75, 206, 16, 205, 185, 34, 86, 249, 193, 220, 123, 146, 123, 117, 250, 17, 107, 195, + 217, 211, 99, 80, 223, 24, 24, 217, 230, 54, 77, 168, 176, 131, 62, 137, 239, 168, 152, 176, 76, 248, 149, + 126, 95, 150, 117, 40, 231, 55, 88, 254, 124, 153, 127, 218, 151, 58, 39, 105, 9, 61, 234, 229, 83, 19, + 148, 214, 233, 30, 118, 31, 179, 2, 242, 170, 88, 135, 227, 223, 109, 34, 156, 226, 183, 128, 218, 61, 188, + 92, 57, 123, 182, 124, 171, 89, 198, 73, 11, 211, 153, 86, 124, 8, 252, 162, 102, 121, 142, 175, 90, 27, + 165, 116, 251, 164, 2, 217, 182, 54, 226, 199, 220, 39, 161, 47, 144, 42, 63, 23, 221, 217, 133, 78, 147, + 42, 125, 112, 189, 219, 20, 76, 87, 171, 186, 194, 6, 250, 227, 158, 47, 212, 31, 196, 251, 155, 19, 111, + 48, 188, 61, 205, 50, 159, 230, 76, 209, 138, 72, 60, 181, 60, 29, 8, 79, 160, 43, 37, 136, 109, 253, + 227, 62, 11, 101, 242, 195, 68, 253, 98, 148, 142, 95, 58, 116, 113, 129, 174, 166, 148, 90, 3, 41, 136, + 89, 192, 26, 255, 209, 80, 179, 164, 87, 16, 230, 163, 152, 29, 54, 112, 1, 216, 229, 106, 64, 58, 232, + 129, 65, 189, 82, 2, 253, 135, 107, 93, 225, 53, 14, 46, 112, 201, 27, 66, 52, 231, 63, 77, 81, 96, + 164, 9, 219, 25, 195, 189, 111, 44, 244, 223, 45, 99, 140, 83, 174, 133, 188, 178, 0, 45, 33, 203, 63, + 137, 150, 70, 245, 206, 252, 87, 83, 41, 216, 178, 46, 27, 78, 178, 54, 203, 98, 238, 36, 166, 29, 110, + 160, 190, 43, 42, 255, 123, 204, 157, 231, 6, 200, 94, 216, 50, 23, 244, 219, 152, 94, 182, 216, 248, 242, + 82, 93, 223, 192, 214, 196, 77, 4, 143, 219, 212, 42, 191, 69, 76, 253, 45, 111, 45, 174, 134, 73, 195, + 117, 153, 118, 91, 66, 75, 214, 216, 134, 179, 121, 144, 173, 190, 109, 119, 64, 240, 199, 26, 52, 10, 139, + 254, 254, 128, 254, 62, 73, 209, 53, 71, 151, 13, 24, 5, 2, 137, 81, 140, 1, 29, 7, 210, 60, 85, + 139, 154, 58, 68, 220, 229, 191, 92, 117, 144, 243, 145, 210, 68, 229, 15, 73, 119, 133, 248, 139, 1, 132, + 174, 254, 138, 14, 148, 248, 54, 115, 139, 24, 57, 91, 130, 38, 36, 64, 162, 195, 200, 24, 34, 99, 160, + 107, 36, 174, 225, 42, 65, 160, 219, 234, 59, 10, 69, 154, 34, 62, 49, 78, 188, 22, 173, 207, 164, 130, + 90, 39, 149, 231, 160, 138, 57, 163, 102, 214, 249, 22, 240, 75, 13, 57, 141, 198, 187, 137, 92, 158, 218, + 115, 120, 137, 138, 129, 10, 183, 230, 224, 30, 183, 186, 127, 6, 95, 211, 93, 81, 159, 35, 247, 233, 187, + 128, 92, 154, 39, 91, 172, 173, 15, 189, 208, 98, 31, 78, 117, 7, 194, 192, 165, 207, 79, 68, 19, 59, + 238, 244, 129, 117, 26, 186, 85, 79, 169, 6, 149, 229, 208, 200, 251, 112, 122, 206, 135, 59, 147, 156, 131, + 115, 98, 109, 10, 51, 107, 177, 219, 29, 48, 217, 76, 152, 190, 89, 110, 129, 167, 160, 38, 249, 5, 226, + 34, 105, 245, 145, 163, 87, 224, 136, 33, 18, 172, 121, 58, 41, 50, 196, 96, 198, 124, 40, 214, 31, 245, + 160, 208, 18, 247, 182, 249, 0, 216, 33, 98, 68, 191, 152, 156, 19, 119, 237, 245, 120, 9, 135, 161, 229, + 46, 139, 249, 78, 174, 167, 186, 76, 232, 232, 132, 163, 10, 4, 234, 108, 239, 157, 82, 109, 209, 117, 97, + 176, 70, 190, 162, 98, 217, 61, 47, 209, 73, 181, 220, 127, 221, 59, 117, 177, 139, 205, 136, 48, 30, 169, + 198, 138, 229, 192, 40, 72, 118, 5, 122, 172, 184, 116, 233, 160, 3, 14, 24, 215, 145, 214, 9, 240, 250, + 81, 109, 59, 39, 82, 215, 88, 175, 253, 19, 139, 71, 211, 50, 170, 103, 56, 57, 181, 41, 185, 170, 131, + 142, 63, 103, 66, 181, 174, 224, 52, 251, 37, 93, 163, 188, 52, 67, 234, 206, 210, 211, 161, 50, 108, 153, + 237, 78, 152, 226, 118, 159, 219, 98, 103, 134, 30, 236, 150, 61, 105, 62, 30, 73, 119, 233, 61, 30, 50, + 152, 250, 121, 239, 50, 151, 182, 95, 22, 212, 23, 160, 245, 20, 19, 224, 219, 199, 113, 252, 201, 216, 134, + 98, 45, 111, 12, 250, 146, 131, 238, 60, 249, 154, 115, 241, 143, 68, 141, 214, 65, 198, 241, 238, 200, 60, + 188, 120, 25, 236, 51, 138, 12, 79, 43, 120, 94, 178, 241, 157, 179, 104, 251, 161, 144, 98, 154, 167, 120, + 68, 10, 45, 54, 77, 219, 202, 168, 35, 29, 230, 184, 243, 145, 216, 41, 31, 169, 170, 5, 88, 37, 209, + 81, 182, 76, 51, 33, 240, 216, 162, 167, 131, 129, 170, 207, 210, 21, 180, 115, 68, 158, 7, 37, 175, 53, + 0, 123, 58, 136, 189, 33, 120, 187, 211, 93, 194, 192, 246, 88, 196, 70, 217, 136, 81, 59, 228, 77, 210, + 71, 18, 26, 183, 81, 230, 139, 96, 204, 83, 160, 229, 227, 160, 11, 85, 24, 115, 254, 198, 91, 4, 130, + 119, 198, 202, 215, 173, 60, 119, 242, 95, 175, 253, 9, 142, 73, 230, 109, 17, 244, 175, 173, 216, 73, 66, + 94, 137, 46, 165, 197, 18, 234, 45, 41, 169, 76, 118, 88, 116, 41, 194, 150, 146, 91, 24, 60, 222, 128, + 196, 32, 28, 84, 152, 57, 132, 129, 186, 121, 236, 38, 246, 194, 167, 143, 157, 181, 88, 172, 126, 159, 250, + 139, 167, 4, 232, 247, 155, 227, 88, 253, 10, 43, 24, 12, 146, 132, 245, 32, 68, 245, 96, 109, 178, 144, + 61, 195, 141, 4, 135, 18, 130, 6, 130, 138, 78, 164, 140, 222, 89, 26, 8, 195, 24, 27, 42, 240, 26, + 100, 255, 155, 13, 236, 216, 208, 230, 18, 55, 8, 146, 149, 197, 218, 75, 36, 106, 155, 197, 105, 251, 85, + 81, 81, 11, 101, 10, 131, 38, 25, 85, 47, 90, 168, 91, 142, 113, 176, 53, 66, 248, 156, 143, 119, 74, + 159, 143, 26, 210, 216, 226, 2, 173, 117, 109, 67, 3, 29, 243, 0, 27, 244, 156, 243, 235, 31, 157, 231, + 199, 58, 32, 140, 86, 50, 79, 222, 10, 188, 51, 222, 83, 40, 94, 141, 238, 240, 222, 87, 168, 123, 172, + 41, 94, 233, 214, 175, 107, 24, 131, 135, 143, 12, 135, 224, 208, 186, 189, 15, 232, 119, 225, 138, 43, 84, + 55, 189, 251, 195, 53, 140, 175, 208, 121, 148, 90, 56, 176, 7, 19, 177, 241, 53, 14, 22, 54, 228, 48, + 79, 250, 27, 214, 43, 144, 229, 150, 197, 102, 247, 248, 141, 33, 248, 186, 180, 209, 163, 171, 121, 242, 198, + 251, 132, 109, 38, 85, 35, 149, 233, 236, 245, 136, 134, 196, 152, 235, 84, 55, 216, 202, 56, 108, 186, 193, + 197, 210, 195, 136, 14, 231, 67, 66, 19, 163, 130, 26, 52, 50, 243, 93, 148, 90, 68, 109, 244, 128, 150, + 55, 93, 80, 128, 192, 75, 154, 66, 158, 189, 68, 86, 243, 18, 111, 119, 230, 135, 105, 38, 115, 142, 117, + 10, 164, 97, 153, 177, 16, 151, 23, 212, 36, 187, 9, 143, 64, 33, 52, 145, 233, 108, 142, 210, 193, 192, + 193, 7, 198, 245, 245, 202, 232, 56, 115, 41, 93, 211, 17, 211, 19, 83, 186, 10, 130, 105, 21, 192, 218, + 199, 33, 1, 250, 22, 169, 14, 76, 87, 9, 203, 89, 42, 65, 182, 4, 210, 192, 187, 180, 49, 208, 37, + 39, 168, 27, 51, 245, 159, 58, 135, 179, 37, 40, 177, 237, 82, 48, 62, 58, 48, 12, 227, 150, 73, 205, + 135, 237, 95, 232, 109, 123, 164, 171, 178, 239, 156, 140, 58, 36, 143, 157, 191, 11, 41, 187, 20, 57, 128, + 252, 24, 23, 68, 2, 135, 48, 14, 82, 229, 24, 200, 134, 81, 5, 93, 125, 143, 153, 145, 118, 69, 65, + 245, 66, 201, 59, 189, 51, 213, 2, 46, 192, 245, 59, 54, 212, 73, 130, 101, 22, 60, 178, 137, 61, 177, + 201, 117, 152, 73, 168, 60, 207, 8, 2, 129, 234, 47, 120, 44, 245, 11, 144, 50, 179, 47, 145, 160, 131, + 94, 26, 9, 211, 20, 170, 252, 214, 217, 92, 35, 130, 41, 27, 82, 158, 142, 215, 209, 65, 196, 49, 238, + 113, 46, 71, 227, 141, 202, 78, 78, 189, 243, 97, 83, 31, 66, 53, 117, 220, 121, 235, 158, 38, 127, 197, + 235, 184, 41, 41, 161, 167, 38, 138, 16, 115, 192, 208, 214, 197, 192, 105, 132, 165, 218, 30, 220, 201, 152, + 132, 171, 118, 136, 167, 191, 156, 55, 76, 148, 1, 64, 123, 3, 124, 136, 38, 126, 99, 130, 112, 250, 129, + 43, 125, 156, 112, 137, 178, 222, 176, 142, 160, 168, 61, 255, 54, 141, 223, 163, 223, 117, 253, 247, 109, 206, + 68, 22, 165, 136, 107, 238, 189, 132, 48, 57, 38, 69, 70, 34, 118, 226, 216, 100, 209, 61, 176, 178, 228, + 68, 170, 199, 112, 112, 190, 146, 212, 46, 76, 130, 164, 11, 216, 12, 165, 61, 62, 91, 168, 101, 128, 61, + 46, 227, 42, 245, 91, 52, 178, 42, 198, 39, 38, 223, 79, 177, 137, 233, 68, 93, 135, 87, 43, 209, 90, + 66, 71, 57, 209, 12, 163, 140, 218, 169, 63, 117, 57, 163, 49, 228, 159, 200, 44, 51, 91, 40, 83, 179, + 192, 233, 231, 188, 231, 62, 63, 52, 149, 154, 115, 6, 29, 119, 70, 40, 83, 0, 139, 56, 213, 52, 216, + 241, 47, 134, 29, 122, 177, 186, 235, 117, 170, 131, 53, 152, 92, 184, 244, 134, 11, 50, 162, 108, 108, 128, + 65, 242, 145, 148, 190, 153, 167, 14, 219, 25, 126, 243, 75, 78, 219, 237, 229, 124, 91, 157, 35, 192, 191, + 39, 252, 162, 141, 16, 240, 52, 247, 74, 222, 240, 195, 224, 37, 246, 218, 149, 131, 101, 72, 208, 130, 139, + 35, 75, 144, 242, 66, 245, 226, 138, 57, 232, 193, 70, 254, 33, 6, 178, 255, 13, 95, 159, 121, 12, 246, + 39, 152, 248, 204, 84, 254, 172, 114, 1, 129, 146, 0, 56, 70, 16, 232, 128, 211, 245, 67, 169, 253, 114, + 15, 210, 172, 171, 250, 144, 92, 193, 65, 160, 20, 18, 227, 97, 166, 240, 69, 92, 14, 119, 197, 55, 97, + 130, 10, 110, 113, 228, 36, 56, 208, 76, 132, 41, 192, 136, 183, 197, 186, 168, 169, 50, 32, 105, 94, 228, + 168, 225, 185, 202, 223, 41, 197, 112, 146, 213, 136, 172, 206, 165, 55, 26, 227, 67, 46, 236, 240, 40, 48, + 220, 236, 187, 231, 125, 188, 137, 89, 79, 196, 223, 103, 45, 39, 62, 82, 95, 36, 21, 238, 167, 124, 117, + 81, 129, 166, 94, 133, 3, 87, 222, 155, 181, 102, 167, 8, 123, 205, 53, 98, 226, 109, 139, 244, 111, 142, + 197, 216, 102, 146, 215, 197, 69, 97, 208, 23, 77, 136, 226, 93, 93, 239, 245, 55, 95, 125, 245, 240, 239, + 235, 249, 45, 76, 190, 89, 205, 139, 242, 171, 135, 124, 149, 209, 55, 103, 171, 34, 43, 198, 27, 143, 232, + 173, 56, 172, 93, 131, 97, 213, 184, 101, 240, 155, 106, 8, 57, 212, 190, 163, 12, 238, 172, 185, 126, 192, + 191, 112, 223, 107, 82, 23, 177, 250, 37, 174, 0, 75, 9, 78, 224, 68, 108, 60, 57, 110, 118, 88, 27, + 135, 148, 188, 75, 241, 11, 182, 227, 62, 228, 233, 71, 254, 27, 255, 197, 191, 229, 2, 195, 12, 51, 249, + 116, 112, 240, 119, 50, 252, 204, 52, 77, 255, 95, 53, 155, 13, 13, 78, 177, 91, 249, 161, 80, 89, 249, + 208, 194, 196, 187, 151, 77, 138, 57, 38, 212, 161, 159, 125, 112, 153, 141, 20, 157, 68, 15, 157, 180, 142, + 8, 133, 217, 64, 137, 17, 20, 246, 163, 18, 122, 249, 91, 28, 155, 248, 26, 164, 6, 135, 182, 50, 133, + 113, 64, 44, 156, 94, 169, 230, 240, 151, 155, 171, 119, 103, 220, 48, 215, 204, 74, 46, 57, 102, 74, 155, + 56, 170, 229, 217, 159, 150, 179, 100, 249, 46, 125, 135, 255, 187, 84, 24, 53, 80, 31, 150, 32, 226, 150, + 103, 238, 47, 226, 80, 188, 227, 32, 182, 107, 172, 47, 161, 7, 134, 222, 74, 119, 232, 9, 170, 22, 211, + 50, 172, 132, 110, 77, 134, 151, 120, 12, 148, 95, 155, 76, 228, 65, 244, 67, 124, 54, 4, 236, 24, 34, + 84, 255, 84, 12, 29, 7, 75, 245, 114, 46, 90, 183, 211, 102, 53, 52, 44, 121, 156, 220, 97, 213, 163, + 228, 198, 150, 220, 67, 198, 187, 228, 49, 45, 105, 236, 102, 207, 80, 227, 1, 1, 241, 238, 234, 195, 27, + 170, 199, 113, 40, 27, 83, 196, 0, 40, 185, 190, 227, 208, 222, 10, 56, 255, 14, 132, 57, 150, 168, 203, + 109, 176, 53, 75, 122, 216, 93, 233, 117, 137, 220, 115, 201, 35, 185, 198, 234, 192, 249, 195, 146, 118, 123, + 121, 45, 245, 245, 236, 175, 171, 28, 174, 185, 199, 245, 73, 15, 40, 83, 78, 169, 112, 19, 57, 158, 93, + 126, 113, 140, 21, 16, 185, 49, 242, 250, 173, 135, 194, 254, 40, 14, 129, 138, 2, 78, 134, 58, 88, 165, + 146, 189, 207, 242, 9, 127, 75, 245, 142, 89, 69, 235, 78, 2, 138, 172, 14, 58, 77, 12, 170, 38, 190, + 144, 156, 160, 238, 77, 97, 239, 101, 117, 202, 190, 147, 209, 155, 57, 37, 246, 224, 62, 34, 112, 252, 132, + 46, 91, 6, 135, 106, 61, 144, 219, 190, 197, 40, 168, 66, 54, 50, 7, 243, 39, 226, 99, 20, 140, 182, + 80, 97, 109, 68, 4, 12, 31, 186, 59, 116, 56, 102, 243, 20, 94, 149, 68, 152, 21, 168, 85, 185, 166, + 135, 100, 161, 88, 210, 103, 192, 139, 86, 77, 141, 41, 15, 90, 74, 78, 218, 58, 144, 113, 64, 207, 16, + 43, 109, 89, 11, 221, 56, 35, 181, 223, 219, 186, 83, 59, 158, 111, 210, 238, 61, 12, 235, 13, 29, 125, + 32, 220, 173, 69, 49, 159, 128, 136, 208, 209, 87, 194, 210, 110, 156, 204, 98, 132, 36, 85, 170, 179, 46, + 85, 157, 14, 129, 170, 70, 107, 172, 237, 153, 193, 4, 8, 134, 126, 247, 65, 107, 211, 213, 10, 127, 164, + 224, 100, 179, 239, 210, 247, 164, 195, 54, 97, 225, 90, 172, 177, 229, 33, 110, 116, 93, 238, 174, 237, 224, + 39, 180, 121, 222, 250, 212, 247, 217, 143, 104, 115, 124, 242, 115, 0, 54, 28, 125, 80, 189, 115, 230, 80, + 124, 56, 200, 14, 24, 238, 156, 191, 63, 225, 94, 102, 184, 7, 155, 226, 86, 204, 38, 11, 117, 89, 187, + 90, 220, 191, 96, 68, 214, 219, 31, 36, 228, 137, 174, 15, 149, 211, 126, 253, 109, 31, 188, 227, 173, 202, + 236, 240, 93, 142, 125, 135, 195, 88, 237, 208, 228, 6, 164, 57, 58, 191, 3, 67, 228, 77, 32, 213, 175, + 161, 73, 169, 106, 72, 193, 173, 94, 15, 82, 120, 79, 38, 145, 180, 137, 211, 197, 231, 26, 199, 176, 204, + 138, 251, 13, 245, 134, 109, 199, 22, 139, 3, 215, 116, 43, 97, 177, 181, 104, 19, 78, 141, 35, 149, 54, + 93, 30, 199, 123, 246, 143, 78, 213, 23, 22, 243, 39, 81, 219, 63, 141, 214, 245, 207, 167, 253, 252, 150, + 194, 17, 45, 48, 27, 80, 50, 131, 24, 88, 73, 177, 193, 112, 74, 7, 25, 232, 72, 145, 240, 232, 209, + 38, 151, 219, 164, 140, 178, 109, 151, 72, 178, 34, 35, 85, 98, 83, 212, 161, 128, 142, 150, 137, 220, 16, + 248, 80, 185, 215, 54, 74, 250, 241, 56, 71, 95, 149, 110, 57, 56, 100, 220, 131, 157, 201, 59, 61, 50, + 5, 98, 17, 101, 29, 136, 101, 105, 73, 122, 28, 193, 198, 6, 251, 6, 58, 243, 70, 218, 138, 50, 109, + 205, 226, 41, 12, 67, 165, 225, 240, 75, 150, 232, 71, 3, 143, 142, 242, 155, 228, 21, 65, 80, 96, 192, + 47, 153, 221, 136, 129, 123, 251, 118, 64, 167, 107, 190, 221, 80, 170, 135, 18, 192, 138, 178, 74, 124, 101, + 242, 179, 50, 44, 211, 99, 152, 119, 133, 117, 252, 31, 65, 139, 61, 219, 0, 37, 168, 108, 123, 232, 232, + 63, 98, 228, 155, 126, 147, 136, 73, 144, 119, 116, 7, 144, 198, 69, 69, 27, 16, 84, 81, 53, 233, 15, + 54, 252, 4, 54, 236, 14, 95, 235, 84, 62, 229, 228, 125, 204, 15, 81, 77, 91, 216, 13, 188, 210, 221, + 10, 88, 143, 51, 242, 215, 120, 14, 15, 195, 149, 30, 65, 20, 247, 145, 27, 98, 107, 24, 221, 98, 77, + 157, 214, 250, 140, 233, 66, 90, 43, 171, 24, 181, 217, 51, 147, 217, 87, 39, 4, 199, 31, 229, 89, 40, + 135, 248, 132, 39, 222, 91, 131, 156, 44, 188, 18, 31, 172, 205, 184, 139, 103, 233, 243, 176, 145, 122, 99, + 235, 250, 89, 21, 53, 5, 187, 69, 36, 172, 103, 173, 30, 234, 217, 68, 24, 177, 213, 41, 75, 78, 200, + 3, 227, 22, 149, 143, 233, 233, 180, 136, 154, 219, 64, 84, 239, 43, 47, 102, 148, 236, 5, 192, 2, 239, + 49, 46, 154, 42, 139, 147, 50, 111, 181, 117, 51, 56, 114, 39, 46, 45, 71, 94, 202, 180, 42, 82, 188, + 85, 41, 159, 45, 212, 137, 229, 250, 163, 6, 126, 100, 101, 245, 212, 209, 235, 199, 141, 94, 127, 150, 209, + 243, 149, 165, 169, 142, 210, 6, 177, 226, 82, 192, 72, 3, 199, 169, 75, 25, 168, 157, 20, 155, 16, 241, + 32, 140, 11, 198, 166, 121, 181, 227, 219, 153, 131, 61, 211, 111, 40, 123, 151, 18, 131, 143, 140, 218, 31, + 41, 2, 137, 32, 70, 118, 146, 53, 21, 39, 122, 80, 3, 190, 226, 234, 235, 149, 170, 63, 174, 133, 26, + 51, 48, 224, 226, 31, 238, 170, 242, 65, 13, 174, 166, 92, 11, 201, 239, 74, 111, 155, 97, 145, 214, 103, + 29, 128, 83, 145, 100, 175, 142, 116, 235, 148, 32, 10, 60, 243, 144, 118, 142, 42, 237, 33, 132, 94, 163, + 211, 68, 56, 163, 112, 68, 115, 59, 14, 141, 129, 127, 90, 242, 155, 75, 123, 101, 28, 69, 196, 78, 14, + 152, 36, 238, 241, 242, 192, 228, 114, 7, 5, 3, 7, 8, 120, 227, 84, 47, 49, 179, 9, 174, 252, 232, + 97, 191, 47, 24, 224, 172, 80, 190, 187, 98, 221, 78, 124, 122, 140, 68, 57, 47, 21, 122, 196, 105, 226, + 174, 247, 163, 42, 241, 111, 34, 72, 124, 153, 139, 165, 141, 243, 41, 162, 151, 62, 128, 11, 88, 190, 205, + 58, 242, 247, 217, 239, 17, 220, 213, 231, 94, 188, 118, 47, 143, 224, 186, 79, 151, 120, 237, 33, 204, 22, + 106, 140, 232, 75, 190, 52, 201, 55, 113, 22, 250, 249, 102, 225, 153, 94, 253, 18, 160, 3, 238, 252, 86, + 173, 70, 27, 123, 53, 79, 222, 112, 52, 67, 23, 88, 207, 92, 98, 46, 179, 229, 204, 243, 194, 24, 103, + 198, 66, 181, 93, 39, 93, 71, 13, 149, 73, 144, 64, 9, 224, 146, 100, 121, 183, 11, 115, 138, 171, 178, + 243, 107, 50, 26, 157, 125, 60, 11, 186, 31, 229, 171, 65, 189, 214, 31, 229, 47, 192, 241, 116, 215, 65, + 251, 59, 186, 138, 30, 239, 251, 137, 122, 63, 218, 14, 53, 208, 102, 178, 109, 254, 40, 67, 237, 155, 227, + 229, 15, 24, 200, 17, 3, 227, 188, 240, 93, 91, 247, 32, 144, 164, 22, 108, 248, 98, 192, 82, 231, 61, + 147, 174, 76, 49, 129, 228, 161, 172, 182, 217, 243, 166, 203, 247, 167, 129, 200, 178, 29, 124, 70, 38, 86, + 12, 85, 147, 253, 237, 125, 101, 106, 154, 248, 161, 82, 142, 216, 97, 108, 104, 127, 111, 225, 26, 14, 215, + 132, 96, 155, 96, 160, 208, 118, 167, 95, 49, 30, 14, 215, 27, 14, 9, 158, 239, 155, 93, 138, 209, 90, + 105, 102, 139, 22, 27, 120, 18, 84, 234, 24, 176, 181, 191, 179, 253, 214, 57, 44, 43, 84, 90, 16, 180, + 41, 93, 231, 187, 51, 9, 220, 234, 173, 153, 31, 91, 146, 252, 168, 36, 198, 18, 55, 103, 198, 154, 112, + 23, 223, 23, 107, 80, 11, 64, 38, 108, 56, 50, 212, 92, 207, 18, 93, 154, 237, 170, 242, 45, 214, 50, + 62, 216, 125, 147, 14, 14, 54, 88, 201, 118, 205, 152, 71, 18, 51, 184, 80, 178, 65, 132, 30, 130, 61, + 157, 73, 251, 176, 46, 247, 197, 237, 96, 121, 136, 232, 194, 164, 255, 63, 86, 220, 240, 121, 193, 145, 162, + 239, 23, 146, 184, 18, 0, 195, 115, 5, 87, 79, 208, 220, 141, 150, 167, 83, 182, 107, 246, 175, 15, 166, + 138, 10, 85, 130, 151, 203, 77, 101, 19, 20, 166, 36, 141, 218, 94, 3, 196, 232, 42, 212, 23, 71, 178, + 105, 145, 60, 6, 62, 199, 199, 6, 205, 207, 29, 112, 33, 184, 91, 206, 221, 36, 189, 203, 43, 58, 203, + 124, 153, 66, 89, 91, 37, 33, 226, 81, 219, 32, 50, 35, 245, 211, 127, 240, 18, 184, 45, 11, 51, 61, + 89, 228, 239, 147, 63, 141, 74, 237, 94, 83, 33, 157, 72, 79, 82, 17, 232, 185, 250, 138, 230, 131, 202, + 117, 228, 242, 34, 222, 199, 128, 48, 155, 84, 199, 41, 214, 254, 76, 192, 160, 105, 27, 109, 200, 177, 169, + 126, 148, 114, 100, 7, 67, 227, 12, 34, 241, 5, 11, 63, 141, 40, 53, 226, 213, 95, 237, 213, 13, 137, + 205, 59, 88, 27, 196, 47, 211, 27, 163, 96, 163, 239, 141, 235, 39, 166, 73, 231, 99, 84, 133, 46, 6, + 181, 227, 190, 168, 33, 187, 125, 184, 75, 247, 251, 92, 13, 234, 70, 195, 226, 210, 54, 245, 22, 152, 82, + 144, 235, 94, 20, 164, 10, 35, 147, 229, 227, 233, 124, 112, 187, 28, 13, 130, 200, 121, 173, 235, 101, 189, + 45, 48, 46, 219, 221, 165, 22, 74, 46, 83, 24, 135, 111, 58, 3, 217, 211, 32, 10, 170, 14, 176, 64, + 239, 26, 166, 242, 26, 57, 242, 66, 73, 184, 18, 200, 172, 188, 94, 79, 132, 96, 235, 51, 232, 15, 209, + 248, 122, 135, 205, 176, 43, 182, 219, 66, 130, 233, 37, 221, 1, 168, 120, 125, 23, 142, 146, 183, 205, 82, + 46, 197, 200, 102, 7, 154, 58, 143, 2, 13, 17, 245, 210, 30, 28, 232, 110, 101, 98, 207, 73, 84, 72, + 166, 26, 149, 171, 198, 36, 236, 223, 19, 54, 224, 177, 89, 236, 159, 63, 123, 125, 64, 70, 244, 27, 109, + 193, 126, 60, 131, 108, 232, 247, 176, 110, 73, 139, 193, 62, 60, 68, 130, 56, 119, 164, 210, 234, 164, 191, + 48, 6, 157, 35, 135, 196, 168, 20, 112, 112, 53, 194, 249, 78, 32, 144, 17, 17, 2, 192, 16, 243, 173, + 53, 27, 123, 156, 121, 158, 124, 75, 227, 192, 130, 217, 244, 3, 71, 245, 25, 43, 114, 218, 170, 17, 216, + 10, 199, 65, 252, 62, 74, 151, 101, 236, 58, 105, 195, 164, 117, 141, 150, 37, 3, 133, 232, 71, 208, 246, + 180, 186, 243, 251, 180, 10, 25, 23, 168, 92, 56, 168, 111, 170, 108, 90, 185, 35, 190, 0, 35, 38, 138, + 153, 77, 121, 70, 243, 53, 171, 56, 123, 154, 104, 227, 17, 197, 74, 152, 63, 219, 152, 38, 132, 198, 5, + 202, 136, 75, 52, 60, 222, 89, 76, 226, 220, 229, 192, 37, 212, 151, 143, 38, 23, 200, 175, 130, 57, 238, + 190, 209, 57, 74, 225, 152, 180, 101, 102, 199, 179, 164, 164, 195, 188, 189, 66, 160, 127, 227, 73, 227, 172, + 55, 206, 89, 49, 95, 48, 94, 157, 185, 98, 193, 53, 227, 158, 233, 184, 18, 32, 237, 133, 226, 172, 98, + 130, 253, 65, 208, 70, 185, 67, 217, 239, 9, 26, 111, 158, 220, 228, 121, 178, 236, 215, 54, 147, 176, 16, + 155, 104, 72, 216, 231, 25, 103, 210, 53, 246, 124, 63, 222, 238, 58, 156, 32, 153, 249, 219, 20, 181, 203, + 116, 54, 116, 160, 114, 202, 67, 90, 32, 36, 161, 184, 214, 59, 148, 154, 101, 98, 157, 33, 68, 113, 241, + 192, 251, 21, 82, 204, 79, 173, 98, 23, 225, 244, 58, 121, 245, 106, 124, 5, 16, 249, 194, 199, 90, 137, + 6, 186, 114, 0, 225, 235, 67, 36, 244, 87, 64, 106, 60, 191, 16, 233, 69, 92, 49, 198, 84, 86, 225, + 168, 109, 63, 227, 203, 51, 255, 17, 250, 229, 193, 57, 206, 167, 248, 94, 25, 0, 56, 22, 13, 98, 6, + 39, 129, 32, 94, 167, 14, 242, 216, 34, 44, 217, 42, 24, 143, 195, 48, 136, 100, 251, 9, 1, 152, 230, + 147, 159, 10, 66, 145, 224, 0, 206, 42, 255, 133, 151, 73, 34, 44, 55, 142, 16, 40, 164, 253, 151, 110, + 5, 140, 184, 10, 126, 228, 134, 238, 116, 126, 41, 168, 131, 157, 241, 161, 215, 114, 217, 208, 163, 56, 114, + 207, 22, 208, 78, 132, 70, 9, 34, 82, 231, 74, 5, 37, 185, 238, 224, 41, 49, 181, 103, 249, 122, 155, + 26, 135, 38, 223, 185, 248, 129, 24, 106, 147, 43, 47, 73, 206, 80, 177, 165, 55, 148, 170, 176, 207, 69, + 203, 45, 91, 99, 133, 5, 223, 210, 27, 62, 60, 102, 52, 23, 110, 4, 1, 251, 134, 55, 186, 174, 84, + 47, 173, 248, 142, 71, 8, 62, 166, 54, 15, 89, 234, 109, 55, 112, 243, 53, 198, 122, 211, 26, 105, 63, + 189, 187, 144, 16, 57, 86, 186, 106, 91, 214, 39, 71, 184, 27, 47, 129, 14, 107, 100, 246, 241, 60, 121, + 133, 52, 221, 250, 45, 217, 49, 50, 14, 101, 64, 186, 26, 99, 185, 47, 149, 201, 132, 155, 164, 218, 219, + 45, 223, 75, 61, 49, 0, 176, 229, 9, 105, 193, 50, 22, 219, 144, 254, 114, 137, 69, 209, 240, 9, 214, + 106, 244, 110, 160, 93, 163, 148, 159, 240, 90, 229, 173, 235, 63, 73, 171, 172, 164, 223, 72, 84, 249, 182, + 170, 228, 234, 30, 84, 211, 2, 147, 214, 48, 206, 241, 26, 159, 95, 41, 123, 124, 150, 132, 2, 59, 145, + 223, 61, 59, 43, 238, 26, 175, 190, 56, 94, 252, 180, 42, 188, 176, 228, 213, 119, 112, 51, 110, 170, 248, + 106, 121, 176, 188, 118, 68, 132, 93, 207, 201, 202, 78, 93, 95, 145, 49, 185, 50, 73, 230, 63, 94, 78, + 68, 222, 25, 82, 7, 162, 131, 89, 210, 103, 172, 1, 241, 170, 32, 77, 138, 123, 151, 0, 84, 168, 144, + 82, 137, 215, 121, 122, 149, 83, 76, 72, 134, 32, 95, 52, 74, 218, 124, 34, 186, 252, 132, 218, 215, 125, + 99, 62, 83, 213, 45, 97, 255, 91, 74, 19, 172, 107, 99, 143, 143, 113, 55, 239, 8, 57, 150, 86, 122, + 76, 47, 226, 55, 124, 148, 173, 232, 179, 22, 236, 194, 28, 71, 175, 3, 246, 2, 163, 119, 200, 134, 40, + 226, 6, 218, 121, 17, 160, 132, 247, 186, 89, 176, 142, 100, 123, 68, 124, 58, 241, 179, 43, 117, 3, 188, + 232, 205, 102, 19, 74, 110, 181, 156, 163, 100, 230, 199, 78, 61, 107, 38, 7, 77, 1, 177, 16, 115, 250, + 216, 203, 211, 173, 26, 180, 249, 163, 137, 171, 199, 43, 159, 225, 236, 146, 166, 29, 39, 64, 132, 43, 222, + 82, 28, 12, 185, 92, 31, 48, 139, 199, 185, 231, 130, 254, 188, 32, 221, 45, 128, 52, 118, 120, 163, 204, + 4, 137, 68, 104, 142, 246, 90, 46, 244, 85, 78, 187, 45, 165, 37, 61, 135, 147, 241, 77, 221, 54, 160, + 30, 192, 151, 134, 205, 194, 46, 251, 14, 47, 242, 76, 21, 61, 210, 17, 80, 51, 140, 227, 166, 11, 96, + 186, 109, 251, 233, 81, 173, 177, 99, 207, 138, 13, 229, 28, 147, 254, 172, 40, 6, 72, 225, 13, 246, 36, + 159, 223, 206, 187, 9, 69, 206, 87, 213, 25, 52, 168, 5, 101, 163, 178, 20, 13, 158, 167, 148, 229, 195, + 19, 216, 53, 117, 67, 1, 66, 84, 234, 85, 211, 138, 162, 118, 182, 236, 159, 198, 229, 35, 75, 7, 247, + 69, 197, 17, 52, 130, 128, 60, 147, 195, 111, 244, 231, 101, 59, 47, 113, 57, 179, 254, 126, 218, 45, 3, + 172, 131, 208, 132, 163, 64, 9, 146, 163, 203, 209, 146, 192, 156, 213, 73, 76, 86, 24, 179, 11, 155, 96, + 52, 159, 130, 171, 144, 222, 195, 246, 102, 143, 46, 180, 49, 9, 219, 10, 201, 187, 95, 208, 239, 217, 174, + 13, 143, 191, 25, 144, 83, 47, 103, 213, 47, 224, 96, 162, 167, 164, 173, 96, 133, 1, 225, 32, 97, 141, + 221, 189, 19, 24, 175, 121, 196, 135, 153, 90, 29, 182, 234, 154, 186, 247, 49, 60, 216, 166, 218, 138, 234, + 228, 227, 241, 246, 32, 80, 3, 104, 235, 48, 236, 66, 215, 145, 25, 59, 249, 249, 224, 145, 185, 140, 56, + 179, 96, 192, 126, 220, 0, 182, 214, 10, 146, 121, 170, 228, 142, 199, 48, 16, 119, 98, 71, 184, 25, 74, + 213, 40, 91, 11, 195, 238, 11, 133, 65, 238, 138, 90, 204, 153, 32, 188, 157, 182, 108, 4, 152, 141, 120, + 48, 154, 147, 141, 87, 216, 72, 153, 68, 41, 47, 11, 205, 222, 230, 19, 101, 121, 248, 112, 68, 77, 245, + 174, 246, 168, 219, 192, 9, 222, 196, 223, 240, 188, 24, 192, 215, 8, 30, 160, 150, 75, 8, 69, 28, 111, + 250, 27, 168, 19, 68, 82, 98, 73, 220, 110, 21, 75, 210, 157, 51, 222, 214, 155, 72, 18, 215, 5, 191, + 229, 87, 226, 246, 174, 71, 92, 44, 133, 203, 252, 98, 169, 94, 54, 233, 5, 144, 105, 99, 53, 130, 199, + 142, 188, 5, 63, 212, 19, 68, 231, 172, 163, 47, 165, 52, 202, 66, 253, 100, 156, 181, 174, 125, 202, 183, + 231, 209, 100, 18, 156, 76, 24, 108, 126, 221, 21, 31, 239, 138, 208, 178, 82, 58, 16, 12, 251, 212, 6, + 19, 149, 8, 24, 127, 166, 76, 238, 121, 172, 188, 106, 139, 163, 161, 97, 163, 165, 20, 63, 3, 139, 51, + 3, 24, 97, 126, 248, 221, 234, 210, 246, 234, 82, 74, 181, 103, 140, 95, 0, 2, 10, 69, 147, 80, 125, + 71, 143, 55, 246, 234, 67, 59, 198, 104, 141, 86, 207, 17, 132, 254, 15, 100, 43, 88, 63, 155, 0, 240, + 22, 243, 183, 16, 0, 35, 148, 210, 206, 221, 96, 105, 162, 112, 74, 84, 145, 145, 67, 161, 31, 162, 119, + 55, 176, 33, 96, 145, 203, 1, 82, 61, 246, 90, 86, 54, 126, 44, 39, 21, 60, 101, 170, 183, 145, 96, + 185, 186, 47, 170, 82, 153, 26, 88, 143, 186, 122, 254, 211, 89, 213, 255, 176, 228, 252, 30, 150, 156, 223, + 229, 238, 111, 78, 48, 2, 150, 35, 75, 19, 93, 230, 117, 133, 137, 169, 30, 34, 211, 211, 72, 2, 125, + 135, 208, 127, 63, 255, 129, 132, 7, 149, 89, 179, 123, 144, 110, 144, 87, 33, 186, 49, 106, 29, 48, 232, + 19, 21, 140, 96, 57, 157, 232, 247, 117, 17, 50, 125, 213, 141, 167, 27, 5, 116, 94, 225, 99, 194, 212, + 212, 118, 9, 253, 64, 199, 167, 45, 14, 136, 157, 237, 219, 80, 189, 178, 155, 188, 174, 89, 74, 154, 178, + 199, 228, 170, 109, 4, 158, 29, 183, 107, 139, 89, 249, 85, 126, 230, 251, 100, 82, 194, 0, 223, 159, 109, + 65, 131, 218, 26, 90, 70, 52, 47, 140, 54, 39, 214, 195, 159, 221, 167, 85, 193, 205, 160, 254, 96, 64, + 78, 109, 99, 185, 73, 171, 59, 24, 168, 3, 204, 173, 97, 12, 85, 51, 228, 37, 229, 7, 232, 28, 136, + 93, 63, 125, 33, 200, 31, 253, 163, 210, 233, 38, 71, 157, 140, 42, 110, 96, 37, 236, 243, 155, 235, 96, + 230, 12, 49, 107, 96, 157, 55, 176, 21, 88, 71, 35, 185, 70, 237, 232, 144, 156, 192, 7, 167, 150, 173, + 137, 111, 105, 87, 220, 222, 9, 42, 123, 242, 178, 161, 78, 206, 240, 28, 188, 196, 2, 190, 84, 228, 217, + 224, 214, 225, 175, 39, 167, 179, 196, 56, 199, 240, 223, 32, 233, 63, 48, 13, 159, 156, 210, 2, 195, 15, + 166, 34, 193, 201, 169, 212, 0, 150, 202, 2, 36, 247, 16, 188, 8, 255, 38, 250, 241, 220, 47, 174, 132, + 245, 234, 64, 24, 187, 58, 129, 209, 218, 74, 33, 45, 161, 236, 144, 191, 19, 111, 192, 243, 68, 194, 138, + 181, 33, 135, 47, 214, 128, 103, 52, 94, 88, 219, 47, 204, 118, 231, 173, 178, 13, 47, 53, 186, 250, 151, + 96, 202, 91, 127, 65, 22, 188, 85, 30, 51, 213, 37, 99, 225, 67, 63, 187, 45, 173, 7, 101, 251, 101, + 89, 212, 128, 1, 93, 114, 160, 127, 48, 15, 72, 208, 166, 80, 191, 230, 183, 36, 132, 36, 180, 108, 129, + 53, 9, 36, 204, 124, 232, 181, 53, 0, 201, 13, 163, 195, 210, 161, 63, 234, 80, 165, 0, 127, 116, 158, + 67, 152, 202, 169, 82, 156, 15, 131, 117, 73, 109, 62, 174, 72, 75, 191, 187, 232, 97, 63, 229, 218, 12, + 10, 85, 19, 189, 46, 247, 166, 124, 218, 30, 43, 71, 175, 177, 32, 82, 98, 98, 141, 198, 47, 0, 30, + 244, 27, 160, 206, 16, 158, 73, 102, 42, 191, 254, 141, 50, 105, 87, 135, 58, 31, 46, 175, 71, 83, 8, + 182, 134, 165, 54, 184, 108, 245, 168, 38, 59, 75, 124, 29, 135, 253, 49, 107, 236, 231, 133, 111, 48, 25, + 115, 124, 88, 69, 18, 141, 170, 240, 253, 244, 97, 11, 198, 163, 66, 30, 68, 7, 246, 134, 188, 225, 84, + 219, 163, 177, 10, 112, 9, 31, 88, 11, 91, 13, 187, 234, 47, 10, 199, 40, 144, 94, 136, 218, 138, 196, + 42, 228, 219, 156, 192, 233, 25, 111, 103, 70, 164, 133, 87, 200, 154, 190, 133, 237, 132, 109, 89, 168, 245, + 93, 90, 76, 180, 48, 152, 236, 79, 55, 218, 43, 232, 246, 248, 136, 187, 88, 63, 56, 244, 19, 14, 160, + 161, 188, 210, 175, 56, 189, 244, 148, 102, 241, 95, 189, 20, 241, 66, 138, 143, 147, 7, 210, 130, 113, 115, + 138, 230, 211, 69, 253, 243, 223, 24, 159, 65, 243, 3, 109, 233, 18, 107, 101, 231, 217, 212, 181, 70, 61, + 171, 224, 79, 219, 176, 10, 227, 97, 24, 159, 36, 120, 218, 176, 47, 211, 192, 186, 188, 148, 246, 86, 173, + 185, 54, 200, 64, 240, 144, 24, 146, 41, 187, 221, 39, 39, 116, 52, 140, 82, 211, 58, 26, 167, 143, 8, + 213, 25, 64, 60, 104, 5, 30, 183, 146, 245, 67, 67, 238, 36, 233, 183, 23, 108, 194, 54, 197, 23, 53, + 6, 23, 240, 235, 239, 36, 243, 201, 124, 252, 67, 254, 9, 11, 38, 220, 160, 168, 123, 23, 12, 2, 55, + 204, 31, 189, 129, 112, 47, 35, 112, 71, 93, 179, 233, 158, 96, 127, 221, 61, 141, 56, 187, 152, 165, 73, + 120, 14, 89, 165, 159, 205, 185, 180, 45, 203, 143, 32, 113, 252, 126, 221, 152, 158, 197, 7, 164, 100, 97, + 142, 84, 113, 53, 186, 75, 107, 153, 65, 237, 175, 14, 76, 92, 122, 40, 234, 150, 229, 192, 180, 184, 91, + 254, 198, 147, 118, 166, 30, 192, 104, 81, 247, 140, 214, 252, 14, 195, 61, 134, 27, 31, 92, 232, 210, 174, + 83, 71, 179, 33, 100, 85, 18, 81, 158, 175, 32, 142, 103, 96, 121, 34, 13, 45, 2, 195, 254, 222, 84, + 185, 106, 35, 22, 120, 145, 164, 67, 129, 210, 143, 84, 74, 168, 203, 129, 189, 137, 14, 63, 188, 73, 118, + 14, 236, 171, 247, 230, 33, 136, 127, 46, 108, 210, 168, 107, 182, 54, 196, 208, 188, 142, 144, 132, 95, 102, + 34, 150, 237, 212, 154, 73, 163, 46, 55, 63, 165, 5, 154, 139, 190, 45, 43, 19, 243, 30, 176, 183, 97, + 80, 175, 51, 226, 195, 191, 234, 148, 170, 233, 148, 232, 52, 78, 28, 70, 247, 3, 55, 198, 117, 85, 76, + 70, 0, 206, 178, 174, 83, 76, 68, 107, 119, 30, 113, 156, 131, 38, 175, 109, 62, 166, 191, 237, 9, 89, + 234, 123, 217, 234, 225, 21, 27, 237, 33, 150, 89, 28, 201, 231, 250, 103, 115, 187, 127, 129, 190, 197, 127, + 32, 215, 221, 23, 239, 38, 253, 231, 139, 67, 254, 71, 242, 14, 77, 186, 139, 0, 187, 253, 34, 173, 95, + 112, 214, 40, 219, 15, 3, 222, 40, 129, 236, 2, 94, 190, 139, 198, 156, 112, 37, 47, 254, 183, 203, 185, + 228, 12, 24, 205, 169, 106, 130, 67, 91, 229, 89, 81, 225, 188, 92, 193, 187, 168, 20, 217, 165, 159, 194, + 221, 190, 77, 63, 21, 187, 102, 7, 179, 220, 163, 250, 179, 233, 247, 137, 57, 112, 226, 137, 41, 147, 229, + 159, 150, 204, 183, 217, 205, 6, 34, 12, 174, 91, 50, 94, 139, 93, 138, 104, 232, 216, 202, 66, 249, 67, + 63, 17, 216, 143, 211, 163, 229, 127, 243, 154, 113, 250, 121, 219, 190, 53, 32, 240, 188, 66, 217, 164, 122, + 110, 185, 253, 38, 88, 98, 220, 245, 8, 235, 96, 55, 8, 205, 95, 31, 202, 243, 116, 47, 78, 220, 241, + 221, 105, 54, 156, 13, 205, 174, 54, 78, 63, 43, 173, 6, 252, 130, 38, 191, 146, 80, 170, 64, 34, 246, + 106, 22, 179, 19, 147, 83, 181, 80, 149, 217, 178, 233, 75, 26, 96, 120, 48, 9, 54, 42, 27, 248, 249, + 108, 87, 106, 155, 254, 236, 206, 118, 46, 57, 241, 253, 153, 250, 252, 34, 203, 94, 23, 100, 199, 12, 25, + 38, 2, 193, 240, 200, 75, 119, 123, 132, 220, 132, 79, 117, 178, 226, 143, 29, 194, 27, 107, 64, 156, 129, + 172, 88, 61, 104, 69, 29, 177, 29, 112, 187, 245, 52, 0, 19, 122, 53, 19, 135, 21, 203, 7, 172, 200, + 182, 22, 255, 57, 218, 87, 171, 217, 66, 73, 111, 26, 203, 243, 220, 163, 107, 1, 100, 119, 153, 102, 88, + 249, 77, 102, 225, 101, 70, 165, 31, 41, 254, 41, 93, 99, 149, 180, 82, 57, 159, 149, 56, 95, 108, 9, + 72, 143, 241, 147, 92, 159, 177, 187, 68, 170, 192, 164, 10, 190, 38, 182, 89, 168, 125, 3, 31, 123, 25, + 213, 21, 58, 178, 124, 143, 53, 150, 160, 195, 8, 174, 85, 119, 52, 116, 104, 128, 101, 102, 13, 166, 107, + 27, 123, 176, 188, 118, 206, 94, 54, 144, 240, 182, 142, 217, 180, 10, 135, 2, 172, 20, 213, 78, 198, 96, + 100, 108, 92, 70, 195, 140, 235, 24, 154, 173, 165, 213, 49, 206, 84, 174, 149, 151, 217, 172, 42, 243, 141, + 167, 149, 120, 0, 86, 27, 171, 40, 82, 106, 109, 119, 28, 104, 62, 88, 74, 106, 2, 250, 31, 177, 72, + 164, 215, 51, 203, 109, 211, 29, 174, 96, 32, 94, 79, 20, 74, 182, 12, 27, 71, 84, 75, 87, 29, 29, + 93, 78, 195, 129, 38, 46, 16, 185, 142, 205, 226, 64, 8, 155, 244, 190, 172, 130, 65, 128, 60, 124, 46, + 63, 143, 100, 0, 155, 13, 124, 8, 147, 133, 115, 34, 31, 46, 23, 8, 92, 156, 180, 110, 170, 214, 189, + 179, 136, 255, 39, 235, 10, 158, 204, 215, 229, 238, 171, 175, 191, 254, 243, 127, 254, 249, 223, 255, 243, 116, + 30, 12, 120, 55, 58, 53, 138, 217, 93, 121, 239, 84, 234, 77, 131, 188, 108, 78, 91, 105, 6, 124, 36, + 98, 224, 24, 120, 73, 127, 126, 19, 8, 165, 189, 93, 45, 23, 234, 185, 201, 205, 129, 117, 199, 74, 135, + 2, 40, 133, 253, 206, 40, 44, 146, 84, 143, 118, 12, 38, 18, 13, 7, 78, 180, 251, 0, 190, 3, 154, + 198, 66, 97, 22, 55, 149, 231, 90, 118, 103, 53, 87, 180, 49, 68, 114, 148, 230, 199, 27, 229, 136, 2, + 67, 242, 151, 215, 120, 241, 128, 198, 152, 247, 126, 40, 77, 208, 228, 149, 122, 151, 63, 92, 148, 107, 98, + 14, 203, 167, 81, 212, 227, 189, 157, 237, 91, 61, 238, 123, 140, 79, 211, 240, 96, 104, 119, 165, 87, 253, + 137, 63, 233, 243, 33, 223, 222, 38, 218, 47, 37, 17, 192, 181, 182, 89, 17, 232, 26, 6, 79, 136, 132, + 50, 96, 40, 176, 80, 240, 23, 125, 122, 156, 115, 233, 231, 96, 93, 29, 71, 211, 81, 8, 48, 127, 13, + 24, 78, 199, 89, 249, 144, 12, 246, 229, 190, 217, 114, 80, 78, 55, 19, 153, 48, 61, 22, 202, 147, 194, + 111, 188, 90, 123, 173, 32, 19, 98, 120, 22, 46, 32, 161, 56, 95, 231, 110, 119, 138, 115, 87, 17, 149, + 194, 57, 134, 133, 154, 193, 88, 144, 231, 78, 73, 84, 52, 86, 152, 176, 97, 233, 149, 30, 27, 169, 15, + 50, 134, 70, 232, 32, 204, 166, 45, 57, 97, 150, 68, 205, 134, 232, 103, 205, 253, 106, 131, 184, 64, 124, + 67, 162, 203, 50, 105, 250, 29, 248, 42, 79, 157, 142, 25, 169, 130, 90, 127, 64, 99, 159, 160, 142, 7, + 107, 139, 183, 8, 179, 143, 28, 228, 17, 42, 185, 24, 181, 110, 208, 19, 5, 183, 232, 131, 183, 200, 30, + 183, 225, 8, 152, 231, 21, 199, 251, 244, 128, 106, 203, 83, 37, 246, 17, 84, 43, 250, 5, 133, 38, 210, + 201, 46, 205, 242, 35, 152, 143, 129, 146, 226, 112, 137, 143, 44, 228, 37, 47, 28, 7, 9, 121, 225, 248, + 216, 151, 91, 178, 72, 61, 230, 80, 105, 139, 15, 22, 35, 61, 143, 100, 180, 187, 242, 20, 219, 146, 185, + 32, 200, 79, 180, 169, 171, 77, 233, 149, 149, 120, 72, 43, 37, 108, 178, 168, 248, 191, 159, 118, 136, 119, + 100, 48, 252, 107, 129, 249, 33, 89, 77, 165, 71, 210, 202, 154, 144, 220, 31, 231, 112, 241, 73, 247, 154, + 239, 38, 42, 51, 47, 48, 252, 15, 99, 124, 72, 89, 120, 87, 84, 30, 91, 45, 27, 178, 3, 33, 49, + 225, 47, 63, 183, 83, 218, 143, 102, 179, 31, 247, 181, 181, 175, 191, 191, 47, 205, 204, 70, 20, 217, 166, + 9, 218, 199, 94, 131, 14, 55, 108, 28, 78, 221, 141, 143, 18, 195, 23, 57, 15, 36, 175, 61, 236, 228, + 131, 133, 55, 98, 156, 9, 114, 150, 147, 250, 208, 192, 45, 20, 24, 0, 215, 252, 182, 86, 182, 13, 98, + 61, 146, 86, 85, 98, 124, 26, 85, 219, 166, 129, 99, 57, 228, 111, 146, 37, 239, 59, 214, 123, 37, 66, + 195, 127, 208, 72, 240, 31, 66, 114, 75, 6, 102, 226, 203, 2, 125, 215, 1, 89, 18, 151, 189, 131, 176, + 65, 81, 133, 10, 93, 67, 69, 199, 29, 242, 12, 136, 188, 30, 44, 141, 91, 152, 185, 65, 32, 90, 50, + 48, 248, 100, 4, 35, 217, 243, 16, 138, 58, 29, 100, 27, 41, 230, 42, 20, 144, 122, 70, 248, 25, 8, + 232, 84, 170, 51, 185, 248, 219, 195, 111, 190, 57, 65, 237, 67, 126, 156, 255, 143, 211, 111, 22, 234, 101, + 10, 239, 31, 118, 101, 163, 255, 133, 99, 218, 206, 224, 252, 194, 44, 207, 138, 236, 165, 109, 23, 155, 109, + 20, 142, 207, 222, 7, 103, 201, 75, 252, 123, 224, 35, 20, 169, 73, 235, 155, 103, 80, 182, 172, 76, 122, + 159, 223, 151, 31, 143, 176, 190, 70, 49, 140, 142, 151, 162, 36, 224, 41, 244, 109, 156, 7, 98, 161, 249, + 128, 149, 224, 61, 253, 236, 227, 223, 62, 220, 29, 226, 109, 15, 136, 143, 56, 2, 41, 5, 82, 101, 92, + 84, 157, 90, 242, 113, 4, 83, 237, 142, 4, 166, 184, 218, 71, 92, 152, 97, 121, 204, 206, 211, 121, 127, + 112, 241, 218, 211, 18, 131, 56, 23, 88, 151, 85, 29, 144, 33, 81, 118, 99, 185, 74, 15, 101, 243, 24, + 235, 9, 104, 35, 163, 140, 129, 145, 220, 176, 193, 185, 171, 252, 33, 132, 67, 108, 175, 62, 241, 153, 199, + 14, 239, 43, 108, 19, 56, 154, 185, 59, 5, 97, 177, 35, 172, 220, 71, 193, 30, 156, 26, 188, 88, 87, + 229, 225, 200, 228, 130, 19, 203, 204, 167, 79, 242, 240, 59, 7, 153, 109, 47, 241, 87, 164, 123, 15, 126, + 212, 189, 247, 199, 24, 146, 180, 224, 165, 13, 15, 98, 4, 86, 218, 208, 18, 235, 115, 212, 75, 142, 172, + 112, 203, 22, 98, 62, 76, 30, 80, 132, 175, 249, 115, 10, 227, 67, 251, 84, 59, 20, 80, 172, 110, 239, + 77, 189, 226, 193, 94, 228, 2, 224, 236, 99, 206, 102, 71, 160, 250, 249, 167, 20, 109, 26, 179, 110, 208, + 176, 188, 118, 114, 154, 8, 50, 25, 195, 62, 130, 126, 200, 214, 227, 211, 99, 190, 228, 227, 182, 126, 44, + 125, 166, 123, 104, 139, 191, 129, 50, 52, 33, 61, 35, 172, 100, 211, 222, 243, 77, 143, 220, 185, 119, 249, + 46, 13, 223, 103, 229, 58, 72, 103, 199, 208, 117, 216, 218, 67, 202, 6, 45, 35, 65, 240, 93, 112, 235, + 71, 240, 236, 109, 68, 200, 26, 75, 111, 209, 39, 79, 172, 194, 194, 253, 142, 168, 28, 130, 217, 228, 33, + 160, 43, 254, 94, 30, 7, 3, 4, 34, 104, 119, 160, 48, 241, 199, 241, 96, 36, 221, 236, 69, 174, 241, + 92, 53, 187, 91, 122, 119, 210, 44, 210, 142, 169, 45, 25, 108, 231, 136, 202, 46, 27, 242, 107, 111, 251, + 223, 149, 89, 142, 234, 153, 220, 111, 34, 156, 195, 219, 90, 210, 229, 206, 169, 240, 212, 232, 189, 2, 98, + 41, 171, 44, 152, 143, 131, 148, 89, 149, 160, 213, 221, 149, 15, 108, 104, 32, 237, 154, 203, 238, 129, 230, + 92, 194, 161, 38, 68, 226, 41, 213, 3, 185, 191, 31, 225, 108, 109, 191, 229, 2, 130, 252, 11, 118, 86, + 168, 6, 20, 65, 10, 131, 228, 31, 95, 233, 183, 205, 250, 238, 149, 190, 46, 53, 213, 6, 106, 93, 152, + 196, 21, 157, 157, 3, 177, 223, 150, 85, 56, 110, 144, 95, 73, 214, 252, 206, 1, 116, 98, 204, 235, 24, + 220, 150, 126, 244, 85, 156, 174, 6, 250, 254, 14, 19, 188, 29, 61, 212, 188, 145, 102, 36, 18, 8, 24, + 32, 177, 117, 188, 201, 87, 192, 42, 187, 116, 22, 110, 247, 49, 145, 101, 116, 187, 13, 221, 171, 170, 90, + 118, 158, 13, 42, 94, 197, 194, 1, 21, 172, 69, 138, 70, 177, 242, 126, 236, 116, 93, 6, 66, 52, 224, + 199, 104, 199, 88, 96, 90, 234, 48, 123, 72, 0, 252, 90, 43, 135, 94, 234, 227, 128, 68, 67, 255, 116, + 185, 89, 40, 164, 216, 243, 238, 55, 124, 177, 227, 4, 76, 89, 82, 204, 223, 193, 114, 106, 146, 197, 255, + 34, 108, 82, 106, 181, 22, 60, 66, 84, 211, 27, 47, 117, 205, 250, 99, 78, 187, 231, 70, 236, 79, 47, + 190, 152, 166, 164, 204, 145, 93, 53, 114, 174, 237, 125, 108, 79, 166, 191, 202, 197, 45, 156, 90, 83, 207, + 85, 136, 137, 0, 98, 202, 253, 94, 92, 51, 126, 169, 32, 159, 7, 232, 100, 159, 139, 9, 121, 219, 232, + 187, 25, 105, 30, 4, 81, 142, 202, 6, 149, 163, 195, 180, 24, 4, 145, 44, 24, 187, 188, 187, 238, 243, + 23, 1, 158, 247, 19, 21, 134, 232, 143, 148, 105, 158, 46, 120, 90, 250, 53, 216, 202, 104, 125, 196, 79, + 19, 46, 42, 145, 92, 178, 146, 81, 86, 54, 228, 107, 16, 158, 213, 227, 161, 220, 249, 229, 197, 139, 56, + 134, 45, 167, 77, 209, 43, 35, 16, 115, 57, 130, 12, 37, 2, 93, 224, 169, 152, 132, 131, 145, 137, 244, + 33, 163, 96, 227, 213, 56, 70, 206, 51, 39, 77, 70, 142, 155, 157, 74, 191, 206, 111, 28, 144, 171, 168, + 183, 131, 47, 48, 60, 248, 88, 209, 139, 251, 244, 150, 247, 232, 67, 25, 219, 87, 244, 69, 59, 101, 67, + 182, 52, 193, 210, 213, 102, 165, 198, 6, 81, 202, 183, 131, 160, 58, 178, 123, 99, 52, 62, 111, 159, 140, + 201, 196, 238, 125, 91, 77, 15, 163, 138, 0, 21, 2, 141, 113, 236, 164, 213, 143, 75, 47, 174, 80, 34, + 248, 20, 123, 82, 113, 117, 180, 192, 176, 146, 239, 202, 189, 132, 55, 66, 121, 97, 161, 24, 150, 242, 144, + 24, 134, 29, 94, 11, 140, 196, 241, 98, 35, 175, 212, 77, 144, 191, 123, 57, 214, 94, 39, 62, 186, 15, + 1, 29, 39, 232, 133, 224, 88, 131, 77, 69, 121, 168, 25, 29, 66, 237, 176, 146, 35, 65, 153, 203, 133, + 50, 91, 42, 81, 151, 152, 67, 59, 63, 18, 160, 17, 197, 152, 201, 233, 52, 25, 12, 104, 140, 82, 109, + 175, 31, 71, 196, 217, 120, 26, 90, 65, 9, 101, 241, 231, 103, 214, 16, 3, 234, 104, 29, 81, 123, 110, + 1, 46, 227, 135, 177, 238, 189, 164, 35, 97, 56, 30, 129, 90, 10, 27, 8, 241, 244, 136, 48, 68, 89, + 65, 73, 99, 24, 73, 244, 32, 181, 238, 128, 134, 235, 80, 164, 46, 15, 114, 220, 120, 162, 135, 34, 133, + 119, 110, 149, 231, 221, 151, 179, 105, 203, 79, 1, 57, 124, 133, 224, 229, 232, 241, 244, 65, 239, 251, 51, + 156, 117, 185, 22, 51, 186, 54, 223, 194, 223, 90, 245, 63, 3, 225, 190, 131, 36, 36, 123, 245, 45, 108, + 213, 136, 21, 203, 34, 91, 251, 152, 85, 179, 100, 98, 214, 200, 171, 33, 117, 148, 153, 200, 18, 26, 190, + 57, 48, 124, 118, 88, 33, 153, 115, 49, 15, 162, 240, 30, 35, 53, 237, 185, 137, 105, 147, 248, 123, 98, + 198, 119, 121, 145, 112, 101, 78, 130, 131, 163, 112, 229, 14, 181, 181, 220, 184, 167, 79, 36, 37, 202, 246, + 179, 188, 93, 202, 25, 34, 51, 73, 205, 168, 143, 209, 77, 148, 211, 135, 46, 81, 194, 161, 6, 53, 10, + 225, 206, 20, 120, 128, 138, 132, 1, 84, 177, 49, 178, 33, 221, 33, 36, 242, 104, 157, 14, 136, 248, 228, + 241, 194, 66, 175, 75, 165, 66, 89, 3, 28, 227, 198, 213, 90, 189, 177, 206, 31, 2, 31, 47, 7, 172, + 99, 3, 97, 111, 65, 110, 242, 48, 102, 112, 100, 105, 224, 100, 114, 76, 227, 47, 42, 137, 161, 207, 83, + 50, 114, 89, 214, 31, 181, 4, 46, 233, 108, 45, 148, 12, 207, 230, 206, 114, 83, 214, 61, 243, 206, 95, + 241, 13, 168, 245, 26, 15, 79, 74, 112, 228, 89, 11, 44, 3, 139, 31, 131, 8, 244, 195, 245, 185, 4, + 7, 203, 36, 82, 4, 51, 59, 161, 57, 211, 195, 255, 3, 143, 42, 151, 58 +}; + +} +} // namespace jsvm + +#endif