LocalSocket.h 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  1. /*
  2. * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #pragma once
  7. #include <AK/IntrusiveList.h>
  8. #include <Kernel/DoubleBuffer.h>
  9. #include <Kernel/Net/Socket.h>
  10. namespace Kernel {
  11. class FileDescription;
  12. struct SocketPair {
  13. NonnullRefPtr<FileDescription> description0;
  14. NonnullRefPtr<FileDescription> description1;
  15. };
  16. class LocalSocket final : public Socket {
  17. public:
  18. static KResultOr<NonnullRefPtr<LocalSocket>> try_create(int type);
  19. static KResultOr<SocketPair> try_create_connected_pair(int type);
  20. virtual ~LocalSocket() override;
  21. KResult sendfd(const FileDescription& socket_description, FileDescription& passing_description);
  22. KResultOr<NonnullRefPtr<FileDescription>> recvfd(const FileDescription& socket_description);
  23. static void for_each(Function<void(const LocalSocket&)>);
  24. StringView socket_path() const;
  25. String absolute_path(const FileDescription& description) const override;
  26. // ^Socket
  27. virtual KResult bind(Userspace<const sockaddr*>, socklen_t) override;
  28. virtual KResult connect(FileDescription&, Userspace<const sockaddr*>, socklen_t, ShouldBlock = ShouldBlock::Yes) override;
  29. virtual KResult listen(size_t) override;
  30. virtual void get_local_address(sockaddr*, socklen_t*) override;
  31. virtual void get_peer_address(sockaddr*, socklen_t*) override;
  32. virtual KResult attach(FileDescription&) override;
  33. virtual void detach(FileDescription&) override;
  34. virtual bool can_read(const FileDescription&, size_t) const override;
  35. virtual bool can_write(const FileDescription&, size_t) const override;
  36. virtual KResultOr<size_t> sendto(FileDescription&, const UserOrKernelBuffer&, size_t, int, Userspace<const sockaddr*>, socklen_t) override;
  37. virtual KResultOr<size_t> recvfrom(FileDescription&, UserOrKernelBuffer&, size_t, int flags, Userspace<sockaddr*>, Userspace<socklen_t*>, Time&) override;
  38. virtual KResult getsockopt(FileDescription&, int level, int option, Userspace<void*>, Userspace<socklen_t*>) override;
  39. virtual KResult ioctl(FileDescription&, unsigned request, Userspace<void*> arg) override;
  40. virtual KResult chown(FileDescription&, UserID, GroupID) override;
  41. virtual KResult chmod(FileDescription&, mode_t) override;
  42. private:
  43. explicit LocalSocket(int type, NonnullOwnPtr<DoubleBuffer> client_buffer, NonnullOwnPtr<DoubleBuffer> server_buffer);
  44. virtual StringView class_name() const override { return "LocalSocket"; }
  45. virtual bool is_local() const override { return true; }
  46. bool has_attached_peer(const FileDescription&) const;
  47. DoubleBuffer* receive_buffer_for(FileDescription&);
  48. DoubleBuffer* send_buffer_for(FileDescription&);
  49. NonnullRefPtrVector<FileDescription>& sendfd_queue_for(const FileDescription&);
  50. NonnullRefPtrVector<FileDescription>& recvfd_queue_for(const FileDescription&);
  51. void set_connect_side_role(Role connect_side_role, bool force_evaluate_block_conditions = false)
  52. {
  53. auto previous = m_connect_side_role;
  54. m_connect_side_role = connect_side_role;
  55. if (previous != m_connect_side_role || force_evaluate_block_conditions)
  56. evaluate_block_conditions();
  57. }
  58. KResult try_set_path(StringView);
  59. // An open socket file on the filesystem.
  60. RefPtr<FileDescription> m_file;
  61. UserID m_prebind_uid { 0 };
  62. GroupID m_prebind_gid { 0 };
  63. mode_t m_prebind_mode { 0 };
  64. // A single LocalSocket is shared between two file descriptions
  65. // on the connect side and the accept side; so we need to store
  66. // an additional role for the connect side and differentiate
  67. // between them.
  68. Role m_connect_side_role { Role::None };
  69. FileDescription* m_connect_side_fd { nullptr };
  70. virtual Role role(const FileDescription& description) const override
  71. {
  72. if (m_connect_side_fd == &description)
  73. return m_connect_side_role;
  74. return m_role;
  75. }
  76. bool m_bound { false };
  77. bool m_accept_side_fd_open { false };
  78. OwnPtr<KString> m_path;
  79. NonnullOwnPtr<DoubleBuffer> m_for_client;
  80. NonnullOwnPtr<DoubleBuffer> m_for_server;
  81. NonnullRefPtrVector<FileDescription> m_fds_for_client;
  82. NonnullRefPtrVector<FileDescription> m_fds_for_server;
  83. IntrusiveListNode<LocalSocket> m_list_node;
  84. public:
  85. using List = IntrusiveList<LocalSocket, RawPtr<LocalSocket>, &LocalSocket::m_list_node>;
  86. };
  87. }