Socket.swift 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213
  1. //
  2. // Socket.swift
  3. // Swifter
  4. // Copyright (c) 2015 Damian Kołakowski. All rights reserved.
  5. //
  6. #if os(Linux)
  7. import Glibc
  8. #else
  9. import Foundation
  10. #endif
  11. /* Low level routines for POSIX sockets */
  12. enum SocketError: ErrorType {
  13. case SocketCreationFailed(String)
  14. case SocketSettingReUseAddrFailed(String)
  15. case BindFailed(String)
  16. case ListenFailed(String)
  17. case WriteFailed(String)
  18. case GetPeerNameFailed(String)
  19. case ConvertingPeerNameFailed
  20. case GetNameInfoFailed(String)
  21. case AcceptFailed(String)
  22. case RecvFailed(String)
  23. }
  24. public class Socket: Hashable, Equatable {
  25. public class func tcpSocketForListen(port: in_port_t = 8080, maxPendingConnection: Int32 = SOMAXCONN) throws -> Socket {
  26. #if os(Linux)
  27. let socketFileDescriptor = socket(AF_INET, Int32(SOCK_STREAM.rawValue), 0)
  28. #else
  29. let socketFileDescriptor = socket(AF_INET, SOCK_STREAM, 0)
  30. #endif
  31. if socketFileDescriptor == -1 {
  32. throw SocketError.SocketCreationFailed(Socket.descriptionOfLastError())
  33. }
  34. var value: Int32 = 1
  35. if setsockopt(socketFileDescriptor, SOL_SOCKET, SO_REUSEADDR, &value, socklen_t(sizeof(Int32))) == -1 {
  36. let details = Socket.descriptionOfLastError()
  37. Socket.release(socketFileDescriptor)
  38. throw SocketError.SocketSettingReUseAddrFailed(details)
  39. }
  40. Socket.setNoSigPipe(socketFileDescriptor)
  41. #if os(Linux)
  42. var addr = sockaddr_in()
  43. addr.sin_family = sa_family_t(AF_INET)
  44. addr.sin_port = Socket.htonsPort(port)
  45. addr.sin_addr = in_addr(s_addr: in_addr_t(0))
  46. addr.sin_zero = (0, 0, 0, 0, 0, 0, 0, 0)
  47. #else
  48. var addr = sockaddr_in()
  49. addr.sin_len = __uint8_t(sizeof(sockaddr_in))
  50. addr.sin_family = sa_family_t(AF_INET)
  51. addr.sin_port = Socket.htonsPort(port)
  52. addr.sin_addr = in_addr(s_addr: inet_addr("0.0.0.0"))
  53. addr.sin_zero = (0, 0, 0, 0, 0, 0, 0, 0)
  54. #endif
  55. var bind_addr = sockaddr()
  56. memcpy(&bind_addr, &addr, Int(sizeof(sockaddr_in)))
  57. if bind(socketFileDescriptor, &bind_addr, socklen_t(sizeof(sockaddr_in))) == -1 {
  58. let details = Socket.descriptionOfLastError()
  59. Socket.release(socketFileDescriptor)
  60. throw SocketError.BindFailed(details)
  61. }
  62. if listen(socketFileDescriptor, maxPendingConnection ) == -1 {
  63. let details = Socket.descriptionOfLastError()
  64. Socket.release(socketFileDescriptor)
  65. throw SocketError.ListenFailed(details)
  66. }
  67. return Socket(socketFileDescriptor: socketFileDescriptor)
  68. }
  69. private let socketFileDescriptor: Int32
  70. init(socketFileDescriptor: Int32) {
  71. self.socketFileDescriptor = socketFileDescriptor
  72. }
  73. public var hashValue: Int { return Int(self.socketFileDescriptor) }
  74. public func release() {
  75. Socket.release(self.socketFileDescriptor)
  76. }
  77. public func shutdwn() {
  78. Socket.shutdwn(self.socketFileDescriptor)
  79. }
  80. public func acceptClientSocket() throws -> Socket {
  81. #if os(Linux)
  82. var addr = sockaddr()
  83. #else
  84. var addr = sockaddr(sa_len: 0, sa_family: 0, sa_data: (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0))
  85. #endif
  86. var len: socklen_t = 0
  87. let clientSocket = accept(self.socketFileDescriptor, &addr, &len)
  88. if clientSocket == -1 {
  89. throw SocketError.AcceptFailed(Socket.descriptionOfLastError())
  90. }
  91. Socket.setNoSigPipe(clientSocket)
  92. return Socket(socketFileDescriptor: clientSocket)
  93. }
  94. public func writeUTF8(string: String) throws {
  95. try writeUInt8([UInt8](string.utf8))
  96. }
  97. public func writeUInt8(data: [UInt8]) throws {
  98. try data.withUnsafeBufferPointer {
  99. var sent = 0
  100. while sent < data.count {
  101. #if os(Linux)
  102. let s = send(self.socketFileDescriptor, $0.baseAddress + sent, Int(data.count - sent), Int32(MSG_NOSIGNAL))
  103. #else
  104. let s = write(self.socketFileDescriptor, $0.baseAddress + sent, Int(data.count - sent))
  105. #endif
  106. if s <= 0 {
  107. throw SocketError.WriteFailed(Socket.descriptionOfLastError())
  108. }
  109. sent += s
  110. }
  111. }
  112. }
  113. public func read() throws -> UInt8 {
  114. var buffer = [UInt8](count: 1, repeatedValue: 0)
  115. let next = recv(self.socketFileDescriptor as Int32, &buffer, Int(buffer.count), 0)
  116. if next <= 0 {
  117. throw SocketError.RecvFailed(Socket.descriptionOfLastError())
  118. }
  119. return buffer[0]
  120. }
  121. public func readLine() throws -> String {
  122. var characters: String = ""
  123. var n: UInt8 = 0
  124. repeat {
  125. n = try self.read()
  126. if n > Constants.CR { characters.append(Character(UnicodeScalar(n))) }
  127. } while n != Constants.NL
  128. return characters
  129. }
  130. public func peername() throws -> String {
  131. var addr = sockaddr(), len: socklen_t = socklen_t(sizeof(sockaddr))
  132. if getpeername(self.socketFileDescriptor, &addr, &len) != 0 {
  133. throw SocketError.GetPeerNameFailed(Socket.descriptionOfLastError())
  134. }
  135. var hostBuffer = [CChar](count: Int(NI_MAXHOST), repeatedValue: 0)
  136. if getnameinfo(&addr, len, &hostBuffer, socklen_t(hostBuffer.count), nil, 0, NI_NUMERICHOST) != 0 {
  137. throw SocketError.GetNameInfoFailed(Socket.descriptionOfLastError())
  138. }
  139. guard let name = String.fromCString(hostBuffer) else {
  140. throw SocketError.ConvertingPeerNameFailed
  141. }
  142. return name
  143. }
  144. private class func descriptionOfLastError() -> String {
  145. return String.fromCString(UnsafePointer(strerror(errno))) ?? "Error: \(errno)"
  146. }
  147. private class func setNoSigPipe(socket: Int32) {
  148. #if os(Linux)
  149. // There is no SO_NOSIGPIPE in Linux (nor some other systems). You can instead use the MSG_NOSIGNAL flag when calling send(),
  150. // or use signal(SIGPIPE, SIG_IGN) to make your entire application ignore SIGPIPE.
  151. #else
  152. // Prevents crashes when blocking calls are pending and the app is paused ( via Home button ).
  153. var no_sig_pipe: Int32 = 1
  154. setsockopt(socket, SOL_SOCKET, SO_NOSIGPIPE, &no_sig_pipe, socklen_t(sizeof(Int32)))
  155. #endif
  156. }
  157. private class func shutdwn(socket: Int32) {
  158. #if os(Linux)
  159. shutdown(socket, Int32(SHUT_RDWR))
  160. #else
  161. Darwin.shutdown(socket, SHUT_RDWR)
  162. #endif
  163. }
  164. private class func release(socket: Int32) {
  165. #if os(Linux)
  166. shutdown(socket, Int32(SHUT_RDWR))
  167. #else
  168. Darwin.shutdown(socket, SHUT_RDWR)
  169. #endif
  170. close(socket)
  171. }
  172. private class func htonsPort(port: in_port_t) -> in_port_t {
  173. #if os(Linux)
  174. return htons(port)
  175. #else
  176. let isLittleEndian = Int(OSHostByteOrder()) == OSLittleEndian
  177. return isLittleEndian ? _OSSwapInt16(port) : port
  178. #endif
  179. }
  180. }
  181. public func ==(socket1: Socket, socket2: Socket) -> Bool {
  182. return socket1.socketFileDescriptor == socket2.socketFileDescriptor
  183. }