WebSocketImplQt.cpp 3.0 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  1. /*
  2. * Copyright (c) 2021, Dex♪ <dexes.ttp@gmail.com>
  3. * Copyright (c) 2022, Ali Mohammad Pur <mpfard@serenityos.org>
  4. * Copyright (c) 2022, the SerenityOS developers.
  5. * Copyright (c) 2022, Andreas Kling <kling@serenityos.org>
  6. *
  7. * SPDX-License-Identifier: BSD-2-Clause
  8. */
  9. #include "WebSocketImplQt.h"
  10. #include "StringUtils.h"
  11. #include <LibCore/EventLoop.h>
  12. #include <QSslSocket>
  13. #include <QTcpSocket>
  14. namespace Ladybird {
  15. WebSocketImplQt::~WebSocketImplQt() = default;
  16. WebSocketImplQt::WebSocketImplQt() = default;
  17. bool WebSocketImplQt::can_read_line()
  18. {
  19. return m_socket->canReadLine();
  20. }
  21. bool WebSocketImplQt::send(ReadonlyBytes bytes)
  22. {
  23. auto bytes_written = m_socket->write(reinterpret_cast<char const*>(bytes.data()), bytes.size());
  24. if (bytes_written == -1)
  25. return false;
  26. VERIFY(static_cast<size_t>(bytes_written) == bytes.size());
  27. return true;
  28. }
  29. bool WebSocketImplQt::eof()
  30. {
  31. return m_socket->state() == QTcpSocket::SocketState::UnconnectedState
  32. && !m_socket->bytesAvailable();
  33. }
  34. void WebSocketImplQt::discard_connection()
  35. {
  36. m_socket = nullptr;
  37. }
  38. void WebSocketImplQt::connect(WebSocket::ConnectionInfo const& connection_info)
  39. {
  40. VERIFY(!m_socket);
  41. VERIFY(on_connected);
  42. VERIFY(on_connection_error);
  43. VERIFY(on_ready_to_read);
  44. if (connection_info.is_secure()) {
  45. auto ssl_socket = make<QSslSocket>();
  46. ssl_socket->connectToHostEncrypted(
  47. qstring_from_ak_string(MUST(connection_info.url().serialized_host())),
  48. connection_info.url().port_or_default());
  49. QObject::connect(ssl_socket.ptr(), &QSslSocket::alertReceived, [this](QSsl::AlertLevel level, QSsl::AlertType, QString const&) {
  50. if (level == QSsl::AlertLevel::Fatal)
  51. on_connection_error();
  52. });
  53. m_socket = move(ssl_socket);
  54. } else {
  55. m_socket = make<QTcpSocket>();
  56. m_socket->connectToHost(
  57. qstring_from_ak_string(MUST(connection_info.url().serialized_host())),
  58. connection_info.url().port_or_default());
  59. }
  60. QObject::connect(m_socket.ptr(), &QTcpSocket::readyRead, [this] {
  61. on_ready_to_read();
  62. });
  63. QObject::connect(m_socket.ptr(), &QTcpSocket::connected, [this] {
  64. on_connected();
  65. });
  66. }
  67. ErrorOr<ByteBuffer> WebSocketImplQt::read(int max_size)
  68. {
  69. auto buffer = TRY(ByteBuffer::create_uninitialized(max_size));
  70. auto bytes_read = m_socket->read(reinterpret_cast<char*>(buffer.data()), buffer.size());
  71. if (bytes_read == -1)
  72. return Error::from_string_literal("WebSocketImplQt::read(): Error reading from socket");
  73. return buffer.slice(0, bytes_read);
  74. }
  75. ErrorOr<DeprecatedString> WebSocketImplQt::read_line(size_t size)
  76. {
  77. auto buffer = TRY(ByteBuffer::create_uninitialized(size));
  78. auto bytes_read = m_socket->readLine(reinterpret_cast<char*>(buffer.data()), buffer.size());
  79. if (bytes_read == -1)
  80. return Error::from_string_literal("WebSocketImplQt::read_line(): Error reading from socket");
  81. return DeprecatedString::copy(buffer.span().slice(0, bytes_read));
  82. }
  83. }