Diff
Modified: trunk/Source/_javascript_Core/ChangeLog (244500 => 244501)
--- trunk/Source/_javascript_Core/ChangeLog 2019-04-22 16:31:41 UTC (rev 244500)
+++ trunk/Source/_javascript_Core/ChangeLog 2019-04-22 16:38:11 UTC (rev 244501)
@@ -1,3 +1,70 @@
+2019-04-22 Basuke Suzuki <basuke.suz...@sony.com>
+
+ [PlayStation] Restructuring Remote Inspector classes to support multiple platform.
+ https://bugs.webkit.org/show_bug.cgi?id=197030
+
+ Reviewed by Don Olmstead.
+
+ Restructuring the PlayStation's RemoteInspector backend which uses native socket for the communication to be ready for WinCairo.
+
+ What we did is basically:
+ - Renamed `remote/playstation/` to `remote/socket/`. This directory is now platform independent implementation of socket backend.
+ - Renamed `RemoteInspectorSocket` class to `RemoteInspectorSocketEndpoint`. This class is platform independent and core of the backend.
+ - Merged `RemoteInspectorSocket{Client|Server}` classes into `RemoteInspectorSocketEndpoint` class because the differences are little.
+ - Defined a new interface functions in `Inspector::Socket` (new) namespace.
+ - Moved POSIX socket implementation into `posix\RemoteInspectorSocketPOSIX.{h|cpp}`.
+
+ * PlatformPlayStation.cmake:
+ * inspector/remote/RemoteInspector.h:
+ * inspector/remote/playstation/RemoteInspectorSocketClient.h: Merged into RemoteInspectorSocketEndpoint.
+ * inspector/remote/playstation/RemoteInspectorSocketClientPlayStation.cpp: Merged into RemoteInspectorSocketEndpoint.
+ * inspector/remote/playstation/RemoteInspectorSocketPlayStation.cpp: Removed.
+ * inspector/remote/playstation/RemoteInspectorSocketServer.h: Merged into RemoteInspectorSocketEndpoint.
+ * inspector/remote/playstation/RemoteInspectorSocketServerPlayStation.cpp: Merged into RemoteInspectorSocketEndpoint.
+ * inspector/remote/socket/RemoteInspectorConnectionClient.cpp: Renamed from inspector\remote\playstation\RemoteInspectorConnectionClientPlayStation.cpp.
+ * inspector/remote/socket/RemoteInspectorConnectionClient.h: Renamed from inspector\remote\playstation\RemoteInspectorConnectionClient.h.
+ (Inspector::RemoteInspectorConnectionClient::didAccept):
+ * inspector/remote/socket/RemoteInspectorMessageParser.cpp: Renamed from inspector\remote\playstation\RemoteInspectorMessageParserPlayStation.cpp.
+ * inspector/remote/socket/RemoteInspectorMessageParser.h: Renamed from inspector\remote\playstation\RemoteInspectorMessageParser.h.
+ * inspector/remote/socket/RemoteInspectorServer.cpp: Renamed from inspector\remote\playstation\RemoteInspectorServerPlayStation.cpp.
+ (Inspector::RemoteInspectorServer::didAccept):
+ (Inspector::RemoteInspectorServer::start):
+ * inspector/remote/socket/RemoteInspectorServer.h: Renamed from inspector\remote\playstation\RemoteInspectorServer.h.
+ * inspector/remote/socket/RemoteInspectorSocket.cpp: Renamed from inspector\remote\playstation\RemoteInspectorPlayStation.cpp.
+ (Inspector::RemoteInspector::start):
+ * inspector/remote/socket/RemoteInspectorSocket.h: Copied from inspector\remote\playstation\RemoteInspectorSocket.h.
+ * inspector/remote/socket/RemoteInspectorSocketEndpoint.cpp: Added.
+ (Inspector::RemoteInspectorSocketEndpoint::RemoteInspectorSocketEndpoint):
+ (Inspector::RemoteInspectorSocketEndpoint::~RemoteInspectorSocketEndpoint):
+ (Inspector::RemoteInspectorSocketEndpoint::wakeupWorkerThread):
+ (Inspector::RemoteInspectorSocketEndpoint::connectInet):
+ (Inspector::RemoteInspectorSocketEndpoint::listenInet):
+ (Inspector::RemoteInspectorSocketEndpoint::isListening):
+ (Inspector::RemoteInspectorSocketEndpoint::workerThread):
+ (Inspector::RemoteInspectorSocketEndpoint::createClient):
+ (Inspector::RemoteInspectorSocketEndpoint::recvIfEnabled):
+ (Inspector::RemoteInspectorSocketEndpoint::sendIfEnabled):
+ (Inspector::RemoteInspectorSocketEndpoint::send):
+ (Inspector::RemoteInspectorSocketEndpoint::acceptInetSocketIfEnabled):
+ * inspector/remote/socket/RemoteInspectorSocketEndpoint.h: Renamed from inspector\remote\playstation\RemoteInspectorSocket.h.
+ * inspector/remote/socket/posix/RemoteInspectorSocketPOSIX.cpp: Added.
+ (Inspector::Socket::connect):
+ (Inspector::Socket::listen):
+ (Inspector::Socket::accept):
+ (Inspector::Socket::createPair):
+ (Inspector::Socket::setup):
+ (Inspector::Socket::isValid):
+ (Inspector::Socket::isListening):
+ (Inspector::Socket::read):
+ (Inspector::Socket::write):
+ (Inspector::Socket::close):
+ (Inspector::Socket::preparePolling):
+ (Inspector::Socket::poll):
+ (Inspector::Socket::isReadable):
+ (Inspector::Socket::isWritable):
+ (Inspector::Socket::markWaitingWritable):
+ (Inspector::Socket::clearWaitingWritable):
+
2019-04-20 Yusuke Suzuki <ysuz...@apple.com>
Unreviewed, suppress warnings in non Darwin environments
Modified: trunk/Source/_javascript_Core/PlatformPlayStation.cmake (244500 => 244501)
--- trunk/Source/_javascript_Core/PlatformPlayStation.cmake 2019-04-22 16:31:41 UTC (rev 244500)
+++ trunk/Source/_javascript_Core/PlatformPlayStation.cmake 2019-04-22 16:38:11 UTC (rev 244501)
@@ -1,5 +1,5 @@
list(APPEND _javascript_Core_PRIVATE_INCLUDE_DIRECTORIES
- "${_javascript_CORE_DIR}/inspector/remote/playstation"
+ "${_javascript_CORE_DIR}/inspector/remote/socket"
)
list(APPEND _javascript_Core_PRIVATE_FRAMEWORK_HEADERS
@@ -9,12 +9,11 @@
inspector/remote/RemoteInspectionTarget.h
inspector/remote/RemoteInspector.h
- inspector/remote/playstation/RemoteInspectorConnectionClient.h
- inspector/remote/playstation/RemoteInspectorMessageParser.h
- inspector/remote/playstation/RemoteInspectorServer.h
- inspector/remote/playstation/RemoteInspectorSocket.h
- inspector/remote/playstation/RemoteInspectorSocketClient.h
- inspector/remote/playstation/RemoteInspectorSocketServer.h
+ inspector/remote/socket/RemoteInspectorConnectionClient.h
+ inspector/remote/socket/RemoteInspectorMessageParser.h
+ inspector/remote/socket/RemoteInspectorServer.h
+ inspector/remote/socket/RemoteInspectorSocket.h
+ inspector/remote/socket/RemoteInspectorSocketEndpoint.h
)
list(APPEND _javascript_Core_SOURCES
@@ -26,13 +25,13 @@
inspector/remote/RemoteInspectionTarget.cpp
inspector/remote/RemoteInspector.cpp
- inspector/remote/playstation/RemoteInspectorConnectionClientPlayStation.cpp
- inspector/remote/playstation/RemoteInspectorMessageParserPlayStation.cpp
- inspector/remote/playstation/RemoteInspectorPlayStation.cpp
- inspector/remote/playstation/RemoteInspectorServerPlayStation.cpp
- inspector/remote/playstation/RemoteInspectorSocketClientPlayStation.cpp
- inspector/remote/playstation/RemoteInspectorSocketPlayStation.cpp
- inspector/remote/playstation/RemoteInspectorSocketServerPlayStation.cpp
+ inspector/remote/socket/RemoteInspectorConnectionClient.cpp
+ inspector/remote/socket/RemoteInspectorMessageParser.cpp
+ inspector/remote/socket/RemoteInspectorServer.cpp
+ inspector/remote/socket/RemoteInspectorSocket.cpp
+ inspector/remote/socket/RemoteInspectorSocketEndpoint.cpp
+
+ inspector/remote/socket/posix/RemoteInspectorSocketPOSIX.cpp
)
if (${WTF_LIBRARY_TYPE} STREQUAL "STATIC")
Modified: trunk/Source/_javascript_Core/inspector/remote/RemoteInspector.h (244500 => 244501)
--- trunk/Source/_javascript_Core/inspector/remote/RemoteInspector.h 2019-04-22 16:31:41 UTC (rev 244500)
+++ trunk/Source/_javascript_Core/inspector/remote/RemoteInspector.h 2019-04-22 16:38:11 UTC (rev 244501)
@@ -54,7 +54,7 @@
#if PLATFORM(PLAYSTATION)
#include "RemoteConnectionToTarget.h"
#include "RemoteInspectorConnectionClient.h"
-#include "RemoteInspectorSocketClient.h"
+#include "RemoteInspectorSocketEndpoint.h"
#include <wtf/JSONValues.h>
#include <wtf/RefCounted.h>
#include <wtf/RefPtr.h>
@@ -236,7 +236,7 @@
#endif
#if PLATFORM(PLAYSTATION)
- std::unique_ptr<RemoteInspectorSocketClient> m_socketConnection;
+ std::unique_ptr<RemoteInspectorSocketEndpoint> m_socketConnection;
static PlatformSocketType s_connectionIdentifier;
Optional<ClientID> m_clientID;
#endif
Copied: trunk/Source/_javascript_Core/inspector/remote/socket/RemoteInspectorConnectionClient.cpp (from rev 244500, trunk/Source/_javascript_Core/inspector/remote/playstation/RemoteInspectorConnectionClientPlayStation.cpp) (0 => 244501)
--- trunk/Source/_javascript_Core/inspector/remote/socket/RemoteInspectorConnectionClient.cpp (rev 0)
+++ trunk/Source/_javascript_Core/inspector/remote/socket/RemoteInspectorConnectionClient.cpp 2019-04-22 16:38:11 UTC (rev 244501)
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2019 Sony Interactive Entertainment Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "RemoteInspectorConnectionClient.h"
+
+#if ENABLE(REMOTE_INSPECTOR)
+
+#include "RemoteInspectorSocketEndpoint.h"
+#include <wtf/JSONValues.h>
+#include <wtf/RunLoop.h>
+
+namespace Inspector {
+
+void RemoteInspectorConnectionClient::didReceiveWebInspectorEvent(ClientID clientID, Vector<uint8_t>&& data)
+{
+ ASSERT(!isMainThread());
+
+ if (data.isEmpty())
+ return;
+
+ String jsonData = String::fromUTF8(data);
+
+ RefPtr<JSON::Value> messageValue;
+ if (!JSON::Value::parseJSON(jsonData, messageValue))
+ return;
+
+ RefPtr<JSON::Object> messageObject;
+ if (!messageValue->asObject(messageObject))
+ return;
+
+ String methodName;
+ if (!messageObject->getString("event"_s, methodName))
+ return;
+
+ struct Event event;
+ event.clientID = clientID;
+
+ uint64_t connectionID;
+ if (messageObject->getInteger("connectionID"_s, connectionID))
+ event.connectionID = connectionID;
+
+ uint64_t targetID;
+ if (messageObject->getInteger("targetID"_s, targetID))
+ event.targetID = targetID;
+
+ String message;
+ if (messageObject->getString("message"_s, message))
+ event.message = message;
+
+ RunLoop::main().dispatch([this, methodName, event = WTFMove(event)] {
+ auto& methods = dispatchMap();
+ if (methods.contains(methodName)) {
+ auto call = methods.get(methodName);
+ (this->*call)(event);
+ } else
+ LOG_ERROR("Unknown event: %s", methodName.utf8().data());
+ });
+}
+
+} // namespace Inspector
+
+#endif // ENABLE(REMOTE_INSPECTOR)
Copied: trunk/Source/_javascript_Core/inspector/remote/socket/RemoteInspectorConnectionClient.h (from rev 244500, trunk/Source/_javascript_Core/inspector/remote/playstation/RemoteInspectorConnectionClient.h) (0 => 244501)
--- trunk/Source/_javascript_Core/inspector/remote/socket/RemoteInspectorConnectionClient.h (rev 0)
+++ trunk/Source/_javascript_Core/inspector/remote/socket/RemoteInspectorConnectionClient.h 2019-04-22 16:38:11 UTC (rev 244501)
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2019 Sony Interactive Entertainment Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#if ENABLE(REMOTE_INSPECTOR)
+
+#include "RemoteInspectorSocketEndpoint.h"
+#include <wtf/WeakPtr.h>
+#include <wtf/text/WTFString.h>
+
+namespace Inspector {
+
+class RemoteInspectorConnectionClient : public CanMakeWeakPtr<RemoteInspectorConnectionClient> {
+public:
+ void didReceiveWebInspectorEvent(ClientID, Vector<uint8_t>&&);
+ virtual void didAccept(ClientID, Socket::Domain) { };
+ virtual void didClose(ClientID) = 0;
+
+ struct Event {
+ ClientID clientID;
+ Optional<uint64_t> connectionID;
+ Optional<uint64_t> targetID;
+ Optional<String> message;
+ };
+
+ using CallHandler = void (RemoteInspectorConnectionClient::*)(const struct Event&);
+ virtual HashMap<String, CallHandler>& dispatchMap() = 0;
+};
+
+} // namespace Inspector
+
+#endif // ENABLE(REMOTE_INSPECTOR)
Copied: trunk/Source/_javascript_Core/inspector/remote/socket/RemoteInspectorMessageParser.cpp (from rev 244500, trunk/Source/_javascript_Core/inspector/remote/playstation/RemoteInspectorMessageParserPlayStation.cpp) (0 => 244501)
--- trunk/Source/_javascript_Core/inspector/remote/socket/RemoteInspectorMessageParser.cpp (rev 0)
+++ trunk/Source/_javascript_Core/inspector/remote/socket/RemoteInspectorMessageParser.cpp 2019-04-22 16:38:11 UTC (rev 244501)
@@ -0,0 +1,117 @@
+/*
+ * Copyright (C) 2019 Sony Interactive Entertainment Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "RemoteInspectorMessageParser.h"
+
+#include <wtf/ByteOrder.h>
+
+#if ENABLE(REMOTE_INSPECTOR)
+
+namespace Inspector {
+
+/*
+| <--- one message for send / didReceiveData ---> |
++--------------+----------------------------------+--------------
+| size | data | (next message)
+| 4byte (NBO) | variable length |
++--------------+----------------------------------+--------------
+ | <------------ size ------------> |
+*/
+
+MessageParser::MessageParser(ClientID clientID, size_t bufferSize)
+ : m_clientID(clientID)
+{
+ m_buffer.reserveCapacity(bufferSize);
+}
+
+Vector<uint8_t> MessageParser::createMessage(const uint8_t* data, size_t size)
+{
+ if (!data || !size || size > UINT_MAX)
+ return Vector<uint8_t>();
+
+ auto messageBuffer = Vector<uint8_t>(size + sizeof(uint32_t));
+ uint32_t uintSize = static_cast<uint32_t>(size);
+ uint32_t nboSize = htonl(uintSize);
+ memcpy(&messageBuffer[0], &nboSize, sizeof(uint32_t));
+ memcpy(&messageBuffer[sizeof(uint32_t)], data, uintSize);
+ return messageBuffer;
+}
+
+void MessageParser::pushReceivedData(const uint8_t* data, size_t size)
+{
+ if (!data || !size)
+ return;
+
+ m_buffer.reserveCapacity(m_buffer.size() + size);
+ m_buffer.append(data, size);
+
+ if (!parse())
+ clearReceivedData();
+}
+
+void MessageParser::clearReceivedData()
+{
+ m_buffer.clear();
+}
+
+bool MessageParser::parse()
+{
+ while (!m_buffer.isEmpty()) {
+ if (m_buffer.size() < sizeof(uint32_t)) {
+ // Wait for more data.
+ return true;
+ }
+
+ uint32_t dataSize = 0;
+ memcpy(&dataSize, &m_buffer[0], sizeof(uint32_t));
+ dataSize = ntohl(dataSize);
+ if (!dataSize) {
+ LOG_ERROR("Message Parser received an invalid message size");
+ return false;
+ }
+
+ size_t messageSize = (sizeof(uint32_t) + dataSize);
+ if (m_buffer.size() < messageSize) {
+ // Wait for more data.
+ return true;
+ }
+
+ // FIXME: This should avoid re-creating a new data Vector.
+ auto dataBuffer = Vector<uint8_t>(dataSize);
+ memcpy(&dataBuffer[0], &m_buffer[sizeof(uint32_t)], dataSize);
+
+ if (m_didParseMessageListener)
+ m_didParseMessageListener(m_clientID, WTFMove(dataBuffer));
+
+ m_buffer.remove(0, messageSize);
+ }
+
+ return true;
+}
+
+} // namespace Inspector
+
+#endif // ENABLE(REMOTE_INSPECTOR)
Copied: trunk/Source/_javascript_Core/inspector/remote/socket/RemoteInspectorMessageParser.h (from rev 244500, trunk/Source/_javascript_Core/inspector/remote/playstation/RemoteInspectorMessageParser.h) (0 => 244501)
--- trunk/Source/_javascript_Core/inspector/remote/socket/RemoteInspectorMessageParser.h (rev 0)
+++ trunk/Source/_javascript_Core/inspector/remote/socket/RemoteInspectorMessageParser.h 2019-04-22 16:38:11 UTC (rev 244501)
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2019 Sony Interactive Entertainment Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#if ENABLE(REMOTE_INSPECTOR)
+
+#include "RemoteInspectorSocketEndpoint.h"
+#include <wtf/Vector.h>
+
+namespace Inspector {
+
+class MessageParser {
+public:
+ static Vector<uint8_t> createMessage(const uint8_t*, size_t);
+
+ MessageParser(ClientID, size_t);
+ void pushReceivedData(const uint8_t*, size_t);
+ void setDidParseMessageListener(Function<void(ClientID, Vector<uint8_t>)>&& listener) { m_didParseMessageListener = WTFMove(listener); }
+
+ void clearReceivedData();
+
+private:
+ bool parse();
+
+ Function<void(ClientID, Vector<uint8_t>&&)> m_didParseMessageListener;
+ Vector<uint8_t> m_buffer;
+ ClientID m_clientID;
+};
+
+} // namespace Inspector
+
+#endif // ENABLE(REMOTE_INSPECTOR)
Copied: trunk/Source/_javascript_Core/inspector/remote/socket/RemoteInspectorServer.cpp (from rev 244500, trunk/Source/_javascript_Core/inspector/remote/playstation/RemoteInspectorServerPlayStation.cpp) (0 => 244501)
--- trunk/Source/_javascript_Core/inspector/remote/socket/RemoteInspectorServer.cpp (rev 0)
+++ trunk/Source/_javascript_Core/inspector/remote/socket/RemoteInspectorServer.cpp 2019-04-22 16:38:11 UTC (rev 244501)
@@ -0,0 +1,238 @@
+/*
+ * Copyright (C) 2019 Sony Interactive Entertainment Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "RemoteInspectorServer.h"
+
+#if ENABLE(REMOTE_INSPECTOR)
+
+#include <wtf/JSONValues.h>
+#include <wtf/MainThread.h>
+
+namespace Inspector {
+
+void RemoteInspectorServer::addServerConnection(PlatformSocketType identifier)
+{
+ if (!m_server)
+ return;
+
+ if (auto id = m_server->createClient(identifier)) {
+ LockHolder lock(m_connectionsLock);
+ m_inspectorConnections.append(id.value());
+ }
+}
+
+void RemoteInspectorServer::didAccept(ClientID clientID, Socket::Domain type)
+{
+ ASSERT(!isMainThread());
+
+ if (type == Socket::Domain::Network) {
+ if (m_clientConnection) {
+ LOG_ERROR("Inspector server can accept only 1 client");
+ return;
+ }
+ m_clientConnection = clientID;
+ } else if (type == Socket::Domain::Local) {
+ LockHolder lock(m_connectionsLock);
+ m_inspectorConnections.append(clientID);
+ }
+}
+
+void RemoteInspectorServer::didClose(ClientID clientID)
+{
+ ASSERT(!isMainThread());
+
+ if (clientID == m_clientConnection) {
+ // Connection from the remote client closed.
+ callOnMainThread([this] {
+ clientConnectionClosed();
+ });
+ return;
+ }
+
+ // Connection from WebProcess closed.
+ callOnMainThread([this, clientID] {
+ connectionClosed(clientID);
+ });
+}
+
+HashMap<String, RemoteInspectorConnectionClient::CallHandler>& RemoteInspectorServer::dispatchMap()
+{
+ static NeverDestroyed<HashMap<String, CallHandler>> dispatchMap = HashMap<String, CallHandler>({
+ {"SetTargetList"_s, static_cast<CallHandler>(&RemoteInspectorServer::setTargetList)},
+ {"SetupInspectorClient"_s, static_cast<CallHandler>(&RemoteInspectorServer::setupInspectorClient)},
+ {"Setup"_s, static_cast<CallHandler>(&RemoteInspectorServer::setup)},
+ {"FrontendDidClose"_s, static_cast<CallHandler>(&RemoteInspectorServer::close)},
+ {"SendMessageToFrontend"_s, static_cast<CallHandler>(&RemoteInspectorServer::sendMessageToFrontend)},
+ {"SendMessageToBackend"_s, static_cast<CallHandler>(&RemoteInspectorServer::sendMessageToBackend)},
+ });
+
+ return dispatchMap;
+}
+
+void RemoteInspectorServer::sendWebInspectorEvent(ClientID clientID, const String& event)
+{
+ const CString message = event.utf8();
+ m_server->send(clientID, reinterpret_cast<const uint8_t*>(message.data()), message.length());
+}
+
+RemoteInspectorServer& RemoteInspectorServer::singleton()
+{
+ static NeverDestroyed<RemoteInspectorServer> server;
+ return server;
+}
+
+bool RemoteInspectorServer::start(uint16_t port)
+{
+ m_server = RemoteInspectorSocketEndpoint::create(this, "RemoteInspectorServer");
+
+ if (!m_server->listenInet(port)) {
+ m_server = nullptr;
+ return false;
+ }
+
+ return true;
+}
+
+void RemoteInspectorServer::setTargetList(const Event& event)
+{
+ ASSERT(isMainThread());
+
+ if (!m_clientConnection || !event.message)
+ return;
+
+ auto targetListEvent = JSON::Object::create();
+ targetListEvent->setString("event"_s, "SetTargetList"_s);
+ targetListEvent->setInteger("connectionID"_s, event.clientID);
+ targetListEvent->setString("message"_s, event.message.value());
+ sendWebInspectorEvent(m_clientConnection.value(), targetListEvent->toJSONString());
+}
+
+void RemoteInspectorServer::setupInspectorClient(const Event&)
+{
+ ASSERT(isMainThread());
+
+ auto setupEvent = JSON::Object::create();
+ setupEvent->setString("event"_s, "GetTargetList"_s);
+
+ LockHolder lock(m_connectionsLock);
+ for (auto connection : m_inspectorConnections)
+ sendWebInspectorEvent(connection, setupEvent->toJSONString());
+}
+
+void RemoteInspectorServer::setup(const Event& event)
+{
+ ASSERT(isMainThread());
+
+ if (!event.targetID || !event.connectionID)
+ return;
+
+ m_inspectionTargets.add(std::make_pair(event.connectionID.value(), event.targetID.value()));
+
+ auto setupEvent = JSON::Object::create();
+ setupEvent->setString("event"_s, "Setup"_s);
+ setupEvent->setInteger("targetID"_s, event.targetID.value());
+ sendWebInspectorEvent(event.connectionID.value(), setupEvent->toJSONString());
+}
+
+void RemoteInspectorServer::sendCloseEvent(uint64_t connectionID, uint64_t targetID)
+{
+ ASSERT(isMainThread());
+
+ auto closeEvent = JSON::Object::create();
+ closeEvent->setString("event"_s, "FrontendDidClose"_s);
+ closeEvent->setInteger("targetID"_s, targetID);
+ sendWebInspectorEvent(connectionID, closeEvent->toJSONString());
+}
+
+void RemoteInspectorServer::close(const Event& event)
+{
+ ASSERT(isMainThread());
+
+ sendCloseEvent(event.connectionID.value(), event.targetID.value());
+ m_inspectionTargets.remove(std::make_pair(event.connectionID.value(), event.targetID.value()));
+}
+
+void RemoteInspectorServer::clientConnectionClosed()
+{
+ ASSERT(isMainThread());
+
+ for (auto connectionTargetPair : m_inspectionTargets)
+ sendCloseEvent(connectionTargetPair.first, connectionTargetPair.second);
+
+ m_inspectionTargets.clear();
+ m_clientConnection = WTF::nullopt;
+}
+
+void RemoteInspectorServer::connectionClosed(uint64_t clientID)
+{
+ ASSERT(isMainThread());
+
+ LockHolder lock(m_connectionsLock);
+ if (m_inspectorConnections.removeFirst(clientID) && m_clientConnection) {
+ auto closedEvent = JSON::Object::create();
+ closedEvent->setString("event"_s, "SetTargetList"_s);
+ closedEvent->setInteger("connectionID"_s, clientID);
+ auto targetList = JSON::Array::create();
+ closedEvent->setString("message"_s, targetList->toJSONString());
+ sendWebInspectorEvent(m_clientConnection.value(), closedEvent->toJSONString());
+ }
+}
+
+void RemoteInspectorServer::sendMessageToBackend(const Event& event)
+{
+ ASSERT(isMainThread());
+
+ if (!event.connectionID || !event.targetID || !event.message)
+ return;
+
+ auto sendEvent = JSON::Object::create();
+ sendEvent->setString("event"_s, "SendMessageToTarget"_s);
+ sendEvent->setInteger("targetID"_s, event.targetID.value());
+ sendEvent->setString("message"_s, event.message.value());
+ sendWebInspectorEvent(event.connectionID.value(), sendEvent->toJSONString());
+}
+
+void RemoteInspectorServer::sendMessageToFrontend(const Event& event)
+{
+ if (!m_clientConnection)
+ return;
+
+ ASSERT(isMainThread());
+
+ if (!event.targetID || !event.message)
+ return;
+
+ auto sendEvent = JSON::Object::create();
+ sendEvent->setString("event"_s, "SendMessageToFrontend"_s);
+ sendEvent->setInteger("targetID"_s, event.targetID.value());
+ sendEvent->setInteger("connectionID"_s, event.clientID);
+ sendEvent->setString("message"_s, event.message.value());
+ sendWebInspectorEvent(m_clientConnection.value(), sendEvent->toJSONString());
+}
+
+} // namespace Inspector
+
+#endif // ENABLE(REMOTE_INSPECTOR)
Copied: trunk/Source/_javascript_Core/inspector/remote/socket/RemoteInspectorServer.h (from rev 244500, trunk/Source/_javascript_Core/inspector/remote/playstation/RemoteInspectorServer.h) (0 => 244501)
--- trunk/Source/_javascript_Core/inspector/remote/socket/RemoteInspectorServer.h (rev 0)
+++ trunk/Source/_javascript_Core/inspector/remote/socket/RemoteInspectorServer.h 2019-04-22 16:38:11 UTC (rev 244501)
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2019 Sony Interactive Entertainment Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#if ENABLE(REMOTE_INSPECTOR)
+
+#include "RemoteInspector.h"
+
+#include "RemoteInspectorConnectionClient.h"
+#include <wtf/HashMap.h>
+#include <wtf/HashSet.h>
+#include <wtf/Lock.h>
+
+namespace Inspector {
+
+class RemoteInspectorServer : public RemoteInspectorConnectionClient {
+public:
+ JS_EXPORT_PRIVATE static RemoteInspectorServer& singleton();
+
+ JS_EXPORT_PRIVATE bool start(uint16_t);
+ bool isRunning() const { return !!m_server; }
+
+ JS_EXPORT_PRIVATE void addServerConnection(PlatformSocketType);
+
+private:
+ void connectionClosed(uint64_t connectionID);
+
+ void setTargetList(const struct Event&);
+ void setupInspectorClient(const struct Event&);
+ void setup(const struct Event&);
+ void close(const struct Event&);
+ void sendMessageToFrontend(const struct Event&);
+ void sendMessageToBackend(const struct Event&);
+
+ void sendCloseEvent(uint64_t connectionID, uint64_t targetID);
+ void clientConnectionClosed();
+
+ void didAccept(ClientID, Socket::Domain) override;
+ void didClose(ClientID) override;
+
+ void sendWebInspectorEvent(ClientID, const String&);
+
+ HashMap<String, CallHandler>& dispatchMap();
+
+ HashSet<std::pair<uint64_t, uint64_t>> m_inspectionTargets;
+ std::unique_ptr<RemoteInspectorSocketEndpoint> m_server;
+
+ // Connections to the WebProcess.
+ Vector<ClientID> m_inspectorConnections;
+ Lock m_connectionsLock;
+
+ // Connections from RemoteInspectorClient.
+ Optional<ClientID> m_clientConnection;
+};
+
+} // namespace Inspector
+
+#endif // ENABLE(REMOTE_INSPECTOR)
Copied: trunk/Source/_javascript_Core/inspector/remote/socket/RemoteInspectorSocket.cpp (from rev 244500, trunk/Source/_javascript_Core/inspector/remote/playstation/RemoteInspectorPlayStation.cpp) (0 => 244501)
--- trunk/Source/_javascript_Core/inspector/remote/socket/RemoteInspectorSocket.cpp (rev 0)
+++ trunk/Source/_javascript_Core/inspector/remote/socket/RemoteInspectorSocket.cpp 2019-04-22 16:38:11 UTC (rev 244501)
@@ -0,0 +1,300 @@
+/*
+ * Copyright (C) 2019 Sony Interactive Entertainment Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "RemoteInspector.h"
+
+#if ENABLE(REMOTE_INSPECTOR)
+
+#include "RemoteAutomationTarget.h"
+#include "RemoteConnectionToTarget.h"
+#include "RemoteInspectionTarget.h"
+#include <wtf/JSONValues.h>
+#include <wtf/MainThread.h>
+#include <wtf/NeverDestroyed.h>
+#include <wtf/RunLoop.h>
+
+namespace Inspector {
+
+PlatformSocketType RemoteInspector::s_connectionIdentifier = INVALID_SOCKET_VALUE;
+
+RemoteInspector& RemoteInspector::singleton()
+{
+ static NeverDestroyed<RemoteInspector> shared;
+ return shared;
+}
+
+RemoteInspector::RemoteInspector()
+{
+ start();
+}
+
+void RemoteInspector::didClose(ClientID clientID)
+{
+ if (clientID != m_clientID.value())
+ return;
+
+ RunLoop::current().dispatch([=] {
+ LockHolder lock(m_mutex);
+ stopInternal(StopSource::API);
+ });
+}
+
+HashMap<String, RemoteInspector::CallHandler>& RemoteInspector::dispatchMap()
+{
+ static NeverDestroyed<HashMap<String, CallHandler>> methods = HashMap<String, CallHandler>({
+ {"GetTargetList"_s, static_cast<CallHandler>(&RemoteInspector::receivedGetTargetListMessage)},
+ {"Setup"_s, static_cast<CallHandler>(&RemoteInspector::receivedSetupMessage)},
+ {"SendMessageToTarget"_s, static_cast<CallHandler>(&RemoteInspector::receivedDataMessage)},
+ {"FrontendDidClose"_s, static_cast<CallHandler>(&RemoteInspector::receivedCloseMessage)},
+ });
+
+ return methods;
+}
+
+void RemoteInspector::sendWebInspectorEvent(const String& event)
+{
+ if (!m_clientID)
+ return;
+
+ const CString message = event.utf8();
+ m_socketConnection->send(m_clientID.value(), reinterpret_cast<const uint8_t*>(message.data()), message.length());
+}
+
+void RemoteInspector::start()
+{
+ LockHolder lock(m_mutex);
+
+ if (m_enabled || s_connectionIdentifier == INVALID_SOCKET_VALUE)
+ return;
+
+ m_enabled = true;
+
+ m_socketConnection = RemoteInspectorSocketEndpoint::create(this, "RemoteInspector");
+
+ m_clientID = m_socketConnection->createClient(s_connectionIdentifier);
+
+ if (!m_targetMap.isEmpty())
+ pushListingsSoon();
+}
+
+void RemoteInspector::stopInternal(StopSource)
+{
+ if (!m_enabled)
+ return;
+
+ m_enabled = false;
+ m_pushScheduled = false;
+
+ for (auto targetConnection : m_targetConnectionMap.values())
+ targetConnection->close();
+ m_targetConnectionMap.clear();
+
+ updateHasActiveDebugSession();
+
+ m_automaticInspectionPaused = false;
+ m_socketConnection = nullptr;
+ m_clientID = WTF::nullopt;
+ s_connectionIdentifier = INVALID_SOCKET_VALUE;
+}
+
+TargetListing RemoteInspector::listingForInspectionTarget(const RemoteInspectionTarget& target) const
+{
+ if (!target.remoteDebuggingAllowed())
+ return nullptr;
+
+ // FIXME: Support remote debugging of a ServiceWorker.
+ if (target.type() == RemoteInspectionTarget::Type::ServiceWorker)
+ return nullptr;
+
+ TargetListing targetListing = JSON::Object::create();
+
+ targetListing->setString("name"_s, target.name());
+ targetListing->setString("url"_s, target.name());
+ targetListing->setInteger("targetID"_s, target.targetIdentifier());
+ targetListing->setBoolean("hasLocalDebugger"_s, target.hasLocalDebugger());
+ if (target.type() == RemoteInspectionTarget::Type::Web)
+ targetListing->setString("type"_s, "Web"_s);
+ else if (target.type() == RemoteInspectionTarget::Type::_javascript_)
+ targetListing->setString("type"_s, "_javascript_"_s);
+ else if (target.type() == RemoteInspectionTarget::Type::ServiceWorker)
+ targetListing->setString("type"_s, "ServiceWorker"_s);
+
+ return targetListing;
+}
+
+TargetListing RemoteInspector::listingForAutomationTarget(const RemoteAutomationTarget&) const
+{
+ return nullptr;
+}
+
+void RemoteInspector::pushListingsNow()
+{
+ if (!m_socketConnection)
+ return;
+
+ m_pushScheduled = false;
+
+ auto targetListJSON = JSON::Array::create();
+ for (auto listing : m_targetListingMap.values())
+ targetListJSON->pushObject(listing);
+
+ auto jsonEvent = JSON::Object::create();
+ jsonEvent->setString("event"_s, "SetTargetList"_s);
+ jsonEvent->setString("message"_s, targetListJSON->toJSONString());
+ sendWebInspectorEvent(jsonEvent->toJSONString());
+}
+
+void RemoteInspector::pushListingsSoon()
+{
+ if (!m_socketConnection)
+ return;
+
+ if (m_pushScheduled)
+ return;
+
+ m_pushScheduled = true;
+
+ RunLoop::current().dispatch([=] {
+ LockHolder lock(m_mutex);
+ if (m_pushScheduled)
+ pushListingsNow();
+ });
+}
+
+void RemoteInspector::updateAutomaticInspectionCandidate(RemoteInspectionTarget*)
+{
+}
+
+void RemoteInspector::sendAutomaticInspectionCandidateMessage()
+{
+}
+
+void RemoteInspector::sendMessageToRemote(unsigned targetIdentifier, const String& message)
+{
+ LockHolder lock(m_mutex);
+ if (!m_socketConnection)
+ return;
+
+ auto sendMessageEvent = JSON::Object::create();
+ sendMessageEvent->setInteger("targetID"_s, targetIdentifier);
+ sendMessageEvent->setString("event"_s, "SendMessageToFrontend"_s);
+ sendMessageEvent->setString("message"_s, message);
+ sendWebInspectorEvent(sendMessageEvent->toJSONString());
+}
+
+void RemoteInspector::receivedGetTargetListMessage(const Event&)
+{
+ ASSERT(isMainThread());
+
+ LockHolder lock(m_mutex);
+ pushListingsNow();
+}
+
+void RemoteInspector::receivedSetupMessage(const Event& event)
+{
+ ASSERT(isMainThread());
+
+ if (event.targetID)
+ setup(event.targetID.value());
+}
+
+void RemoteInspector::receivedDataMessage(const Event& event)
+{
+ ASSERT(isMainThread());
+
+ if (!event.targetID || !event.message)
+ return;
+
+ RefPtr<RemoteConnectionToTarget> connectionToTarget;
+ {
+ LockHolder lock(m_mutex);
+ connectionToTarget = m_targetConnectionMap.get(event.targetID.value());
+ if (!connectionToTarget)
+ return;
+ }
+
+ connectionToTarget->sendMessageToTarget(event.message.value());
+}
+
+void RemoteInspector::receivedCloseMessage(const Event& event)
+{
+ ASSERT(isMainThread());
+
+ if (!event.targetID)
+ return;
+
+ RefPtr<RemoteConnectionToTarget> connectionToTarget;
+ {
+ LockHolder lock(m_mutex);
+ RemoteControllableTarget* target = m_targetMap.get(event.targetID.value());
+ if (!target)
+ return;
+
+ connectionToTarget = m_targetConnectionMap.take(event.targetID.value());
+ updateHasActiveDebugSession();
+ }
+
+ if (connectionToTarget)
+ connectionToTarget->close();
+}
+
+void RemoteInspector::setup(unsigned targetIdentifier)
+{
+ RemoteControllableTarget* target;
+ {
+ LockHolder lock(m_mutex);
+ target = m_targetMap.get(targetIdentifier);
+ if (!target)
+ return;
+ }
+
+ auto connectionToTarget = adoptRef(*new RemoteConnectionToTarget(*target));
+ ASSERT(is<RemoteInspectionTarget>(target) || is<RemoteAutomationTarget>(target));
+ if (!connectionToTarget->setup()) {
+ connectionToTarget->close();
+ return;
+ }
+
+ LockHolder lock(m_mutex);
+ m_targetConnectionMap.set(targetIdentifier, WTFMove(connectionToTarget));
+
+ updateHasActiveDebugSession();
+}
+
+void RemoteInspector::sendMessageToTarget(unsigned targetIdentifier, const char* message)
+{
+ if (auto connectionToTarget = m_targetConnectionMap.get(targetIdentifier))
+ connectionToTarget->sendMessageToTarget(String::fromUTF8(message));
+}
+
+void RemoteInspector::setConnectionIdentifier(PlatformSocketType connectionIdentifier)
+{
+ RemoteInspector::s_connectionIdentifier = connectionIdentifier;
+}
+
+} // namespace Inspector
+
+#endif // ENABLE(REMOTE_INSPECTOR)
Copied: trunk/Source/_javascript_Core/inspector/remote/socket/RemoteInspectorSocket.h (from rev 244500, trunk/Source/_javascript_Core/inspector/remote/playstation/RemoteInspectorSocket.h) (0 => 244501)
--- trunk/Source/_javascript_Core/inspector/remote/socket/RemoteInspectorSocket.h (rev 0)
+++ trunk/Source/_javascript_Core/inspector/remote/socket/RemoteInspectorSocket.h 2019-04-22 16:38:11 UTC (rev 244501)
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) 2019 Sony Interactive Entertainment Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#if ENABLE(REMOTE_INSPECTOR)
+
+#include <array>
+#include <wtf/Optional.h>
+#include <wtf/Vector.h>
+
+#if PLATFORM(PLAYSTATION)
+#include <poll.h>
+#endif
+
+#if OS(WINDOWS)
+#include <winsock2.h>
+#endif
+
+namespace Inspector {
+
+#if OS(WINDOWS)
+
+using ClientID = unsigned;
+using PlatformSocketType = SOCKET;
+using PollingDescriptor = WSAPOLLFD;
+constexpr PlatformSocketType INVALID_SOCKET_VALUE = INVALID_SOCKET;
+
+#else
+
+using ClientID = unsigned;
+using PlatformSocketType = int;
+using PollingDescriptor = struct pollfd;
+constexpr PlatformSocketType INVALID_SOCKET_VALUE = -1;
+
+#endif
+
+class MessageParser;
+
+namespace Socket {
+
+enum class Domain {
+ Local,
+ Network,
+};
+
+Optional<PlatformSocketType> connect(const char* serverAddress, uint16_t serverPort);
+Optional<PlatformSocketType> listen(uint16_t port);
+Optional<PlatformSocketType> accept(PlatformSocketType);
+Optional<std::array<PlatformSocketType, 2>> createPair();
+
+void setup(PlatformSocketType);
+bool isValid(PlatformSocketType);
+bool isListening(PlatformSocketType);
+
+Optional<size_t> read(PlatformSocketType, void* buffer, int bufferSize);
+Optional<size_t> write(PlatformSocketType, const void* data, int size);
+
+void close(PlatformSocketType&);
+
+PollingDescriptor preparePolling(PlatformSocketType);
+bool poll(Vector<PollingDescriptor>&, int timeout);
+bool isReadable(const PollingDescriptor&);
+bool isWritable(const PollingDescriptor&);
+void markWaitingWritable(PollingDescriptor&);
+void clearWaitingWritable(PollingDescriptor&);
+
+struct Connection {
+ std::unique_ptr<MessageParser> parser;
+ Vector<uint8_t> sendBuffer;
+ PlatformSocketType socket { INVALID_SOCKET_VALUE };
+ PollingDescriptor poll;
+};
+
+constexpr size_t BufferSize = 65536;
+
+} // namespace Socket
+
+} // namespace Inspector
+
+#endif // ENABLE(REMOTE_INSPECTOR)
Added: trunk/Source/_javascript_Core/inspector/remote/socket/RemoteInspectorSocketEndpoint.cpp (0 => 244501)
--- trunk/Source/_javascript_Core/inspector/remote/socket/RemoteInspectorSocketEndpoint.cpp (rev 0)
+++ trunk/Source/_javascript_Core/inspector/remote/socket/RemoteInspectorSocketEndpoint.cpp 2019-04-22 16:38:11 UTC (rev 244501)
@@ -0,0 +1,261 @@
+/*
+ * Copyright (C) 2019 Sony Interactive Entertainment Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "RemoteInspectorSocketEndpoint.h"
+
+#if ENABLE(REMOTE_INSPECTOR)
+
+#include "RemoteInspectorConnectionClient.h"
+#include "RemoteInspectorMessageParser.h"
+#include <wtf/CryptographicallyRandomNumber.h>
+#include <wtf/MainThread.h>
+#include <wtf/text/WTFString.h>
+
+namespace Inspector {
+
+RemoteInspectorSocketEndpoint::RemoteInspectorSocketEndpoint(RemoteInspectorConnectionClient* inspectorClient, const char* name)
+ : m_inspectorClient(makeWeakPtr(inspectorClient))
+{
+ if (auto sockets = Socket::createPair()) {
+ m_wakeupSendSocket = sockets->at(0);
+ m_wakeupReceiveSocket = sockets->at(1);
+ }
+
+ m_workerThread = Thread::create(name, [this] {
+ workerThread();
+ });
+}
+
+RemoteInspectorSocketEndpoint::~RemoteInspectorSocketEndpoint()
+{
+ ASSERT(m_workerThread.get() != &Thread::current());
+
+ m_shouldAbortWorkerThread = true;
+ wakeupWorkerThread();
+ m_workerThread->waitForCompletion();
+
+ Socket::close(m_wakeupSendSocket);
+ Socket::close(m_wakeupReceiveSocket);
+ for (const auto& connection : m_connections.values())
+ Socket::close(connection->socket);
+}
+
+void RemoteInspectorSocketEndpoint::wakeupWorkerThread()
+{
+ if (Socket::isValid(m_wakeupSendSocket))
+ Socket::write(m_wakeupSendSocket, "1", 1);
+}
+
+Optional<ClientID> RemoteInspectorSocketEndpoint::connectInet(const char* serverAddress, uint16_t serverPort)
+{
+ if (auto socket = Socket::connect(serverAddress, serverPort))
+ return createClient(*socket);
+ return WTF::nullopt;
+}
+
+bool RemoteInspectorSocketEndpoint::listenInet(uint16_t port)
+{
+ if (auto socket = Socket::listen(port)) {
+ if (createClient(*socket))
+ return true;
+ }
+
+ return false;
+}
+
+bool RemoteInspectorSocketEndpoint::isListening(ClientID id)
+{
+ LockHolder lock(m_connectionsLock);
+ if (const auto& connection = m_connections.get(id))
+ return Socket::isListening(connection->socket);
+ return false;
+}
+
+void RemoteInspectorSocketEndpoint::workerThread()
+{
+ PollingDescriptor wakeup = Socket::preparePolling(m_wakeupReceiveSocket);
+
+ while (!m_shouldAbortWorkerThread) {
+ Vector<PollingDescriptor> pollfds;
+ Vector<ClientID> ids;
+ {
+ LockHolder lock(m_connectionsLock);
+ for (const auto& connection : m_connections) {
+ pollfds.append(connection.value->poll);
+ ids.append(connection.key);
+ }
+ }
+ pollfds.append(wakeup);
+
+ if (!Socket::poll(pollfds, -1))
+ continue;
+
+ if (Socket::isReadable(pollfds.last())) {
+ char wakeMessage;
+ Socket::read(m_wakeupReceiveSocket, &wakeMessage, sizeof(wakeMessage));
+ continue;
+ }
+
+ for (size_t i = 0; i < ids.size(); i++) {
+ auto id = ids[i];
+
+ if (Socket::isReadable(pollfds[i]) && isListening(id))
+ acceptInetSocketIfEnabled(id);
+ else if (Socket::isReadable(pollfds[i]))
+ recvIfEnabled(id);
+ else if (Socket::isWritable(pollfds[i]))
+ sendIfEnabled(id);
+ }
+ }
+}
+
+Optional<ClientID> RemoteInspectorSocketEndpoint::createClient(PlatformSocketType socket)
+{
+ if (!Socket::isValid(socket))
+ return WTF::nullopt;
+
+ LockHolder lock(m_connectionsLock);
+
+ ClientID id;
+ do {
+ id = cryptographicallyRandomNumber();
+ } while (!id || m_connections.contains(id));
+
+ Socket::setup(socket);
+
+ auto connection = std::make_unique<Socket::Connection>();
+
+ connection->poll = Socket::preparePolling(socket);
+ connection->socket = socket;
+ connection->parser = std::make_unique<MessageParser>(id, Socket::BufferSize);
+ connection->parser->setDidParseMessageListener([this](ClientID id, Vector<uint8_t>&& data) {
+ if (m_inspectorClient)
+ m_inspectorClient->didReceiveWebInspectorEvent(id, WTFMove(data));
+ });
+ m_connections.add(id, WTFMove(connection));
+ wakeupWorkerThread();
+
+ return id;
+}
+
+void RemoteInspectorSocketEndpoint::recvIfEnabled(ClientID clientID)
+{
+ LockHolder lock(m_connectionsLock);
+ if (const auto& connection = m_connections.get(clientID)) {
+ Vector<uint8_t> recvBuffer(Socket::BufferSize);
+ if (auto readSize = Socket::read(connection->socket, recvBuffer.data(), recvBuffer.size())) {
+ if (*readSize > 0)
+ connection->parser->pushReceivedData(recvBuffer.data(), *readSize);
+ return;
+ }
+
+ Socket::close(connection->socket);
+ m_connections.remove(clientID);
+
+ lock.unlockEarly();
+ if (m_inspectorClient)
+ m_inspectorClient->didClose(clientID);
+ }
+}
+
+void RemoteInspectorSocketEndpoint::sendIfEnabled(ClientID clientID)
+{
+ LockHolder lock(m_connectionsLock);
+ if (const auto& connection = m_connections.get(clientID)) {
+ Socket::clearWaitingWritable(connection->poll);
+
+ auto& buffer = connection->sendBuffer;
+ if (buffer.isEmpty())
+ return;
+
+ if (auto writeSize = Socket::write(connection->socket, buffer.data(), std::min(buffer.size(), Socket::BufferSize))) {
+ auto size = *writeSize;
+ if (size == buffer.size()) {
+ buffer.clear();
+ return;
+ }
+
+ if (size > 0)
+ buffer.remove(0, size);
+ }
+
+ Socket::markWaitingWritable(connection->poll);
+ }
+}
+
+void RemoteInspectorSocketEndpoint::send(ClientID clientID, const uint8_t* data, size_t size)
+{
+ LockHolder lock(m_connectionsLock);
+ if (const auto& connection = m_connections.get(clientID)) {
+ auto message = MessageParser::createMessage(data, size);
+ if (message.isEmpty())
+ return;
+
+ size_t offset = 0;
+ if (connection->sendBuffer.isEmpty()) {
+ // Try to call send() directly if buffer is empty.
+ if (auto writeSize = Socket::write(connection->socket, message.data(), std::min(message.size(), Socket::BufferSize)))
+ offset = *writeSize;
+ // @TODO need to handle closed socket case?
+ }
+
+ // Check all data is sent.
+ if (offset == message.size())
+ return;
+
+ // Copy remaining data to send later.
+ connection->sendBuffer.appendRange(message.begin() + offset, message.end());
+ Socket::markWaitingWritable(connection->poll);
+
+ wakeupWorkerThread();
+ }
+}
+
+void RemoteInspectorSocketEndpoint::acceptInetSocketIfEnabled(ClientID id)
+{
+ if (!isListening(id))
+ return;
+
+ LockHolder lock(m_connectionsLock);
+ if (const auto& connection = m_connections.get(id)) {
+ if (auto socket = Socket::accept(connection->socket)) {
+ // Need to unlock before calling createClient as it also attempts to lock.
+ lock.unlockEarly();
+ if (auto newID = createClient(*socket)) {
+ if (m_inspectorClient) {
+ m_inspectorClient->didAccept(newID.value(), Socket::Domain::Network);
+ return;
+ }
+ }
+
+ Socket::close(*socket);
+ }
+ }
+}
+
+} // namespace Inspector
+
+#endif // ENABLE(REMOTE_INSPECTOR)
Copied: trunk/Source/_javascript_Core/inspector/remote/socket/RemoteInspectorSocketEndpoint.h (from rev 244500, trunk/Source/_javascript_Core/inspector/remote/playstation/RemoteInspectorSocket.h) (0 => 244501)
--- trunk/Source/_javascript_Core/inspector/remote/socket/RemoteInspectorSocketEndpoint.h (rev 0)
+++ trunk/Source/_javascript_Core/inspector/remote/socket/RemoteInspectorSocketEndpoint.h 2019-04-22 16:38:11 UTC (rev 244501)
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2019 Sony Interactive Entertainment Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#if ENABLE(REMOTE_INSPECTOR)
+
+#include "RemoteInspectorSocket.h"
+
+#include <wtf/Condition.h>
+#include <wtf/Function.h>
+#include <wtf/HashMap.h>
+#include <wtf/Lock.h>
+#include <wtf/Threading.h>
+#include <wtf/Vector.h>
+#include <wtf/WeakPtr.h>
+
+namespace Inspector {
+
+class MessageParser;
+class RemoteInspectorConnectionClient;
+
+class JS_EXPORT_PRIVATE RemoteInspectorSocketEndpoint {
+public:
+ static std::unique_ptr<RemoteInspectorSocketEndpoint> create(RemoteInspectorConnectionClient* inspectorClient, const char* name)
+ {
+ return std::make_unique<RemoteInspectorSocketEndpoint>(inspectorClient, name);
+ }
+
+ RemoteInspectorSocketEndpoint(RemoteInspectorConnectionClient*, const char*);
+ ~RemoteInspectorSocketEndpoint();
+
+ Optional<ClientID> connectInet(const char* serverAddr, uint16_t serverPort);
+ bool listenInet(uint16_t port);
+
+ void send(ClientID, const uint8_t* data, size_t);
+
+ Optional<ClientID> createClient(PlatformSocketType fd);
+
+protected:
+ void recvIfEnabled(ClientID);
+ void sendIfEnabled(ClientID);
+ void workerThread();
+ void wakeupWorkerThread();
+ void acceptInetSocketIfEnabled(ClientID);
+ bool isListening(ClientID);
+
+ Lock m_connectionsLock;
+ HashMap<ClientID, std::unique_ptr<Socket::Connection>> m_connections;
+
+ PlatformSocketType m_wakeupSendSocket { INVALID_SOCKET_VALUE };
+ PlatformSocketType m_wakeupReceiveSocket { INVALID_SOCKET_VALUE };
+
+ RefPtr<Thread> m_workerThread;
+ std::atomic<bool> m_shouldAbortWorkerThread { false };
+
+ WeakPtr<RemoteInspectorConnectionClient> m_inspectorClient;
+};
+
+} // namespace Inspector
+
+#endif // ENABLE(REMOTE_INSPECTOR)
Added: trunk/Source/_javascript_Core/inspector/remote/socket/posix/RemoteInspectorSocketPOSIX.cpp (0 => 244501)
--- trunk/Source/_javascript_Core/inspector/remote/socket/posix/RemoteInspectorSocketPOSIX.cpp (rev 0)
+++ trunk/Source/_javascript_Core/inspector/remote/socket/posix/RemoteInspectorSocketPOSIX.cpp 2019-04-22 16:38:11 UTC (rev 244501)
@@ -0,0 +1,229 @@
+/*
+ * Copyright (C) 2019 Sony Interactive Entertainment Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "RemoteInspectorSocket.h"
+
+#if ENABLE(REMOTE_INSPECTOR)
+
+#include <arpa/inet.h>
+#include <fcntl.h>
+#include <netinet/in.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <unistd.h>
+
+namespace Inspector {
+
+namespace Socket {
+
+Optional<PlatformSocketType> connect(const char* serverAddress, uint16_t serverPort)
+{
+ struct sockaddr_in address = { };
+
+ address.sin_family = AF_INET;
+ inet_aton(serverAddress, &address.sin_addr);
+ address.sin_port = htons(serverPort);
+
+ int fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
+ if (fd < 0) {
+ LOG_ERROR("Failed to create socket for %s:%d, errno = %d", serverAddress, serverPort, errno);
+ return WTF::nullopt;
+ }
+
+ int error = ::connect(fd, (struct sockaddr*)&address, sizeof(address));
+ if (error < 0) {
+ LOG_ERROR("Failed to connect to %s:%u, errno = %d", serverAddress, serverPort, errno);
+ ::close(fd);
+ return WTF::nullopt;
+ }
+
+ return fd;
+}
+
+Optional<PlatformSocketType> listen(uint16_t port)
+{
+ struct sockaddr_in address = { };
+
+ int fdListen = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
+ if (fdListen < 0) {
+ LOG_ERROR("socket() failed, errno = %d", errno);
+ return WTF::nullopt;
+ }
+
+ const int enabled = 1;
+ int error = setsockopt(fdListen, SOL_SOCKET, SO_REUSEADDR, &enabled, sizeof(enabled));
+ if (error < 0) {
+ LOG_ERROR("setsockopt() SO_REUSEADDR, errno = %d", errno);
+ return WTF::nullopt;
+ }
+ error = setsockopt(fdListen, SOL_SOCKET, SO_REUSEPORT, &enabled, sizeof(enabled));
+ if (error < 0) {
+ LOG_ERROR("setsockopt() SO_REUSEPORT, errno = %d", errno);
+ return WTF::nullopt;
+ }
+
+ // FIXME: Support AF_INET6 connections.
+ address.sin_family = AF_INET;
+ address.sin_addr.s_addr = htonl(INADDR_ANY);
+ address.sin_port = htons(port);
+ error = ::bind(fdListen, (struct sockaddr*)&address, sizeof(address));
+ if (error < 0) {
+ LOG_ERROR("bind() failed, errno = %d", errno);
+ ::close(fdListen);
+ return WTF::nullopt;
+ }
+
+ error = ::listen(fdListen, 1);
+ if (error < 0) {
+ LOG_ERROR("listen() failed, errno = %d", errno);
+ ::close(fdListen);
+ return WTF::nullopt;
+ }
+
+ return fdListen;
+}
+
+Optional<PlatformSocketType> accept(PlatformSocketType socket)
+{
+ struct sockaddr_in address = { };
+
+ socklen_t len = sizeof(struct sockaddr_in);
+ int fd = ::accept(socket, (struct sockaddr*) &address, &len);
+ if (fd >= 0)
+ return fd;
+
+ LOG_ERROR("accept(inet) error (errno = %d)", errno);
+ return WTF::nullopt;
+}
+
+Optional<std::array<PlatformSocketType, 2>> createPair()
+{
+ std::array<PlatformSocketType, 2> sockets;
+
+ if (socketpair(AF_UNIX, SOCK_STREAM, 0, &sockets[0]))
+ return WTF::nullopt;
+
+ return sockets;
+}
+
+void setup(PlatformSocketType socket)
+{
+ fcntl(socket, F_SETFD, FD_CLOEXEC);
+ int flags = fcntl(socket, F_GETFL, 0);
+ fcntl(socket, F_SETFL, flags | O_NONBLOCK);
+
+ setsockopt(socket, SOL_SOCKET, SO_RCVBUF, &BufferSize, sizeof(BufferSize));
+ setsockopt(socket, SOL_SOCKET, SO_SNDBUF, &BufferSize, sizeof(BufferSize));
+}
+
+bool isValid(PlatformSocketType socket)
+{
+ return socket != INVALID_SOCKET_VALUE;
+}
+
+bool isListening(PlatformSocketType socket)
+{
+ int out;
+ socklen_t outSize = sizeof(out);
+ if (getsockopt(socket, SOL_SOCKET, SO_ACCEPTCONN, &out, &outSize) != -1)
+ return out;
+
+ LOG_ERROR("getsockopt errno = %d", errno);
+ return false;
+}
+
+Optional<size_t> read(PlatformSocketType socket, void* buffer, int bufferSize)
+{
+ ASSERT(isValid(socket));
+
+ ssize_t readSize = ::read(socket, buffer, bufferSize);
+ if (readSize >= 0)
+ return static_cast<size_t>(readSize);
+
+ LOG_ERROR("read error (errno = %d)", errno);
+ return WTF::nullopt;
+}
+
+Optional<size_t> write(PlatformSocketType socket, const void* data, int size)
+{
+ ASSERT(isValid(socket));
+
+ ssize_t writeSize = ::write(socket, data, size);
+ if (writeSize >= 0)
+ return static_cast<size_t>(writeSize);
+
+ LOG_ERROR("write error (errno = %d)", errno);
+ return WTF::nullopt;
+}
+
+void close(PlatformSocketType& socket)
+{
+ if (!isValid(socket))
+ return;
+
+ ::close(socket);
+ socket = INVALID_SOCKET_VALUE;
+}
+
+PollingDescriptor preparePolling(PlatformSocketType socket)
+{
+ PollingDescriptor poll;
+ poll.fd = socket;
+ poll.events = POLLIN;
+ return poll;
+}
+
+bool poll(Vector<PollingDescriptor>& pollDescriptors, int timeout)
+{
+ int ret = ::poll(pollDescriptors.data(), pollDescriptors.size(), timeout);
+ return ret > 0;
+}
+
+bool isReadable(const PollingDescriptor& poll)
+{
+ return poll.revents & POLLIN;
+}
+
+bool isWritable(const PollingDescriptor& poll)
+{
+ return poll.revents & POLLOUT;
+}
+
+void markWaitingWritable(PollingDescriptor& poll)
+{
+ poll.events |= POLLOUT;
+}
+
+void clearWaitingWritable(PollingDescriptor& poll)
+{
+ poll.events &= ~POLLOUT;
+}
+
+} // namespace Socket
+
+} // namespace Inspector
+
+#endif // ENABLE(REMOTE_INSPECTOR)