1
0

Socket+Server.swift 4.4 KB

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