PageRenderTime 29ms CodeModel.GetById 0ms RepoModel.GetById 0ms app.codeStats 0ms

/src/SFML/Network/TcpListener.cpp

http://github.com/LaurentGomila/SFML
C++ | 131 lines | 63 code | 23 blank | 45 comment | 16 complexity | ab3d3410c0a913a4a2bf64feb7975bff MD5 | raw file
  1. ////////////////////////////////////////////////////////////
  2. //
  3. // SFML - Simple and Fast Multimedia Library
  4. // Copyright (C) 2007-2019 Laurent Gomila (laurent@sfml-dev.org)
  5. //
  6. // This software is provided 'as-is', without any express or implied warranty.
  7. // In no event will the authors be held liable for any damages arising from the use of this software.
  8. //
  9. // Permission is granted to anyone to use this software for any purpose,
  10. // including commercial applications, and to alter it and redistribute it freely,
  11. // subject to the following restrictions:
  12. //
  13. // 1. The origin of this software must not be misrepresented;
  14. // you must not claim that you wrote the original software.
  15. // If you use this software in a product, an acknowledgment
  16. // in the product documentation would be appreciated but is not required.
  17. //
  18. // 2. Altered source versions must be plainly marked as such,
  19. // and must not be misrepresented as being the original software.
  20. //
  21. // 3. This notice may not be removed or altered from any source distribution.
  22. //
  23. ////////////////////////////////////////////////////////////
  24. ////////////////////////////////////////////////////////////
  25. // Headers
  26. ////////////////////////////////////////////////////////////
  27. #include <SFML/Network/TcpListener.hpp>
  28. #include <SFML/Network/TcpSocket.hpp>
  29. #include <SFML/Network/SocketImpl.hpp>
  30. #include <SFML/System/Err.hpp>
  31. namespace sf
  32. {
  33. ////////////////////////////////////////////////////////////
  34. TcpListener::TcpListener() :
  35. Socket(Tcp)
  36. {
  37. }
  38. ////////////////////////////////////////////////////////////
  39. unsigned short TcpListener::getLocalPort() const
  40. {
  41. if (getHandle() != priv::SocketImpl::invalidSocket())
  42. {
  43. // Retrieve informations about the local end of the socket
  44. sockaddr_in address;
  45. priv::SocketImpl::AddrLength size = sizeof(address);
  46. if (getsockname(getHandle(), reinterpret_cast<sockaddr*>(&address), &size) != -1)
  47. {
  48. return ntohs(address.sin_port);
  49. }
  50. }
  51. // We failed to retrieve the port
  52. return 0;
  53. }
  54. ////////////////////////////////////////////////////////////
  55. Socket::Status TcpListener::listen(unsigned short port, const IpAddress& address)
  56. {
  57. // Close the socket if it is already bound
  58. close();
  59. // Create the internal socket if it doesn't exist
  60. create();
  61. // Check if the address is valid
  62. if ((address == IpAddress::None) || (address == IpAddress::Broadcast))
  63. return Error;
  64. // Bind the socket to the specified port
  65. sockaddr_in addr = priv::SocketImpl::createAddress(address.toInteger(), port);
  66. if (bind(getHandle(), reinterpret_cast<sockaddr*>(&addr), sizeof(addr)) == -1)
  67. {
  68. // Not likely to happen, but...
  69. err() << "Failed to bind listener socket to port " << port << std::endl;
  70. return Error;
  71. }
  72. // Listen to the bound port
  73. if (::listen(getHandle(), SOMAXCONN) == -1)
  74. {
  75. // Oops, socket is deaf
  76. err() << "Failed to listen to port " << port << std::endl;
  77. return Error;
  78. }
  79. return Done;
  80. }
  81. ////////////////////////////////////////////////////////////
  82. void TcpListener::close()
  83. {
  84. // Simply close the socket
  85. Socket::close();
  86. }
  87. ////////////////////////////////////////////////////////////
  88. Socket::Status TcpListener::accept(TcpSocket& socket)
  89. {
  90. // Make sure that we're listening
  91. if (getHandle() == priv::SocketImpl::invalidSocket())
  92. {
  93. err() << "Failed to accept a new connection, the socket is not listening" << std::endl;
  94. return Error;
  95. }
  96. // Accept a new connection
  97. sockaddr_in address;
  98. priv::SocketImpl::AddrLength length = sizeof(address);
  99. SocketHandle remote = ::accept(getHandle(), reinterpret_cast<sockaddr*>(&address), &length);
  100. // Check for errors
  101. if (remote == priv::SocketImpl::invalidSocket())
  102. return priv::SocketImpl::getErrorStatus();
  103. // Initialize the new connected socket
  104. socket.close();
  105. socket.create(remote);
  106. return Done;
  107. }
  108. } // namespace sf