Socket+Server.swift 3.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798
  1. //
  2. // Socket+Server.swift
  3. // Swifter
  4. //
  5. // Created by Damian Kolakowski on 13/07/16.
  6. //
  7. import Foundation
  8. extension Socket {
  9. public class func tcpSocketForListen(_ port: in_port_t, _ forceIPv4: Bool = false, _ maxPendingConnection: Int32 = SOMAXCONN) throws -> Socket {
  10. #if os(Linux)
  11. let socketFileDescriptor = socket(forceIPv4 ? AF_INET : AF_INET6, Int32(SOCK_STREAM.rawValue), 0)
  12. #else
  13. let socketFileDescriptor = socket(forceIPv4 ? AF_INET : AF_INET6, SOCK_STREAM, 0)
  14. #endif
  15. if socketFileDescriptor == -1 {
  16. throw SocketError.socketCreationFailed(Errno.description())
  17. }
  18. var value: Int32 = 1
  19. if setsockopt(socketFileDescriptor, SOL_SOCKET, SO_REUSEADDR, &value, socklen_t(MemoryLayout<Int32>.size)) == -1 {
  20. let details = Errno.description()
  21. Socket.close(socketFileDescriptor)
  22. throw SocketError.socketSettingReUseAddrFailed(details)
  23. }
  24. Socket.setNoSigPipe(socketFileDescriptor)
  25. var bindResult: Int32 = -1
  26. if forceIPv4 {
  27. #if os(Linux)
  28. var addr = sockaddr_in(
  29. sin_family: sa_family_t(AF_INET),
  30. sin_port: port.bigEndian,
  31. sin_addr: in_addr(s_addr: in_addr_t(0)),
  32. sin_zero:(0, 0, 0, 0, 0, 0, 0, 0))
  33. #else
  34. var addr = sockaddr_in(
  35. sin_len: UInt8(MemoryLayout<sockaddr_in>.stride),
  36. sin_family: UInt8(AF_INET),
  37. sin_port: port.bigEndian,
  38. sin_addr: in_addr(s_addr: in_addr_t(0)),
  39. sin_zero:(0, 0, 0, 0, 0, 0, 0, 0))
  40. #endif
  41. bindResult = withUnsafePointer(to: &addr) {
  42. bind(socketFileDescriptor, UnsafePointer<sockaddr>(OpaquePointer($0)), socklen_t(MemoryLayout<sockaddr_in>.size))
  43. }
  44. } else {
  45. #if os(Linux)
  46. var addr = sockaddr_in6(
  47. sin6_family: sa_family_t(AF_INET6),
  48. sin6_port: port.bigEndian,
  49. sin6_flowinfo: 0,
  50. sin6_addr: in6addr_any,
  51. sin6_scope_id: 0)
  52. #else
  53. var addr = sockaddr_in6(
  54. sin6_len: UInt8(MemoryLayout<sockaddr_in6>.stride),
  55. sin6_family: UInt8(AF_INET6),
  56. sin6_port: port.bigEndian,
  57. sin6_flowinfo: 0,
  58. sin6_addr: in6addr_any,
  59. sin6_scope_id: 0)
  60. #endif
  61. bindResult = withUnsafePointer(to: &addr) {
  62. bind(socketFileDescriptor, UnsafePointer<sockaddr>(OpaquePointer($0)), socklen_t(MemoryLayout<sockaddr_in6>.size))
  63. }
  64. }
  65. if bindResult == -1 {
  66. let details = Errno.description()
  67. Socket.close(socketFileDescriptor)
  68. throw SocketError.bindFailed(details)
  69. }
  70. if listen(socketFileDescriptor, maxPendingConnection) == -1 {
  71. let details = Errno.description()
  72. Socket.close(socketFileDescriptor)
  73. throw SocketError.listenFailed(details)
  74. }
  75. return Socket(socketFileDescriptor: socketFileDescriptor)
  76. }
  77. public func acceptClientSocket() throws -> Socket {
  78. var addr = sockaddr()
  79. var len: socklen_t = 0
  80. let clientSocket = accept(self.socketFileDescriptor, &addr, &len)
  81. if clientSocket == -1 {
  82. throw SocketError.acceptFailed(Errno.description())
  83. }
  84. Socket.setNoSigPipe(clientSocket)
  85. return Socket(socketFileDescriptor: clientSocket)
  86. }
  87. }