UDPServer.cpp 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105
  1. /*
  2. * Copyright (c) 2020, Andreas Kling <kling@serenityos.org>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #include <AK/IPv4Address.h>
  7. #include <AK/Types.h>
  8. #include <LibCore/Notifier.h>
  9. #include <LibCore/UDPServer.h>
  10. #include <LibCore/UDPSocket.h>
  11. #include <errno.h>
  12. #include <stdio.h>
  13. #include <unistd.h>
  14. #ifndef SOCK_NONBLOCK
  15. # include <fcntl.h>
  16. # include <sys/ioctl.h>
  17. #endif
  18. namespace Core {
  19. UDPServer::UDPServer(Object* parent)
  20. : Object(parent)
  21. {
  22. #ifdef SOCK_NONBLOCK
  23. m_fd = socket(AF_INET, SOCK_DGRAM | SOCK_NONBLOCK | SOCK_CLOEXEC, 0);
  24. #else
  25. m_fd = socket(AF_INET, SOCK_DGRAM, 0);
  26. int option = 1;
  27. ioctl(m_fd, FIONBIO, &option);
  28. fcntl(m_fd, F_SETFD, FD_CLOEXEC);
  29. #endif
  30. VERIFY(m_fd >= 0);
  31. }
  32. UDPServer::~UDPServer()
  33. {
  34. ::close(m_fd);
  35. }
  36. bool UDPServer::bind(const IPv4Address& address, u16 port)
  37. {
  38. if (m_bound)
  39. return false;
  40. auto saddr = SocketAddress(address, port);
  41. auto in = saddr.to_sockaddr_in();
  42. if (::bind(m_fd, (const sockaddr*)&in, sizeof(in)) != 0) {
  43. perror("UDPServer::bind");
  44. return false;
  45. }
  46. m_bound = true;
  47. m_notifier = Notifier::construct(m_fd, Notifier::Event::Read, this);
  48. m_notifier->on_ready_to_read = [this] {
  49. if (on_ready_to_receive)
  50. on_ready_to_receive();
  51. };
  52. return true;
  53. }
  54. ByteBuffer UDPServer::receive(size_t size, sockaddr_in& in)
  55. {
  56. auto buf = ByteBuffer::create_uninitialized(size);
  57. socklen_t in_len = sizeof(in);
  58. ssize_t rlen = ::recvfrom(m_fd, buf.data(), size, 0, (sockaddr*)&in, &in_len);
  59. if (rlen < 0) {
  60. dbgln("recvfrom: {}", strerror(errno));
  61. return {};
  62. }
  63. buf.resize(rlen);
  64. return buf;
  65. }
  66. Optional<IPv4Address> UDPServer::local_address() const
  67. {
  68. if (m_fd == -1)
  69. return {};
  70. sockaddr_in address;
  71. socklen_t len = sizeof(address);
  72. if (getsockname(m_fd, (sockaddr*)&address, &len) != 0)
  73. return {};
  74. return IPv4Address(address.sin_addr.s_addr);
  75. }
  76. Optional<u16> UDPServer::local_port() const
  77. {
  78. if (m_fd == -1)
  79. return {};
  80. sockaddr_in address;
  81. socklen_t len = sizeof(address);
  82. if (getsockname(m_fd, (sockaddr*)&address, &len) != 0)
  83. return {};
  84. return ntohs(address.sin_port);
  85. }
  86. }