Socket.swift 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229
  1. //
  2. // Socket.swift
  3. // Swifter
  4. //
  5. // Copyright (c) 2014-2016 Damian Kołakowski. All rights reserved.
  6. //
  7. import Foundation
  8. public enum SocketError: Error {
  9. case socketCreationFailed(String)
  10. case socketSettingReUseAddrFailed(String)
  11. case bindFailed(String)
  12. case listenFailed(String)
  13. case writeFailed(String)
  14. case getPeerNameFailed(String)
  15. case convertingPeerNameFailed
  16. case getNameInfoFailed(String)
  17. case acceptFailed(String)
  18. case recvFailed(String)
  19. case getSockNameFailed(String)
  20. }
  21. open class Socket: Hashable, Equatable {
  22. let socketFileDescriptor: Int32
  23. private var shutdown = false
  24. public init(socketFileDescriptor: Int32) {
  25. self.socketFileDescriptor = socketFileDescriptor
  26. }
  27. deinit {
  28. close()
  29. }
  30. public var hashValue: Int { return Int(self.socketFileDescriptor) }
  31. public func close() {
  32. if shutdown {
  33. return
  34. }
  35. shutdown = true
  36. Socket.close(self.socketFileDescriptor)
  37. }
  38. public func port() throws -> in_port_t {
  39. var addr = sockaddr_in()
  40. return try withUnsafePointer(to: &addr) { pointer in
  41. var len = socklen_t(MemoryLayout<sockaddr_in>.size)
  42. if getsockname(socketFileDescriptor, UnsafeMutablePointer(OpaquePointer(pointer)), &len) != 0 {
  43. throw SocketError.getSockNameFailed(Errno.description())
  44. }
  45. let sin_port = pointer.pointee.sin_port
  46. #if os(Linux)
  47. return ntohs(sin_port)
  48. #else
  49. return Int(OSHostByteOrder()) != OSLittleEndian ? sin_port.littleEndian : sin_port.bigEndian
  50. #endif
  51. }
  52. }
  53. public func isIPv4() throws -> Bool {
  54. var addr = sockaddr_in()
  55. return try withUnsafePointer(to: &addr) { pointer in
  56. var len = socklen_t(MemoryLayout<sockaddr_in>.size)
  57. if getsockname(socketFileDescriptor, UnsafeMutablePointer(OpaquePointer(pointer)), &len) != 0 {
  58. throw SocketError.getSockNameFailed(Errno.description())
  59. }
  60. return Int32(pointer.pointee.sin_family) == AF_INET
  61. }
  62. }
  63. public func writeUTF8(_ string: String) throws {
  64. try writeUInt8(ArraySlice(string.utf8))
  65. }
  66. public func writeUInt8(_ data: [UInt8]) throws {
  67. try writeUInt8(ArraySlice(data))
  68. }
  69. public func writeUInt8(_ data: ArraySlice<UInt8>) throws {
  70. try data.withUnsafeBufferPointer {
  71. try writeBuffer($0.baseAddress!, length: data.count)
  72. }
  73. }
  74. public func writeData(_ data: NSData) throws {
  75. try writeBuffer(data.bytes, length: data.length)
  76. }
  77. public func writeData(_ data: Data) throws {
  78. try data.withUnsafeBytes { (pointer: UnsafePointer<UInt8>) -> Void in
  79. try self.writeBuffer(pointer, length: data.count)
  80. }
  81. }
  82. private func writeBuffer(_ pointer: UnsafeRawPointer, length: Int) throws {
  83. var sent = 0
  84. while sent < length {
  85. #if os(Linux)
  86. let s = send(self.socketFileDescriptor, pointer + sent, Int(length - sent), Int32(MSG_NOSIGNAL))
  87. #else
  88. let s = write(self.socketFileDescriptor, pointer + sent, Int(length - sent))
  89. #endif
  90. if s <= 0 {
  91. throw SocketError.writeFailed(Errno.description())
  92. }
  93. sent += s
  94. }
  95. }
  96. /// Read a single byte off the socket. This method is optimized for reading
  97. /// a single byte. For reading multiple bytes, use read(length:), which will
  98. /// pre-allocate heap space and read directly into it.
  99. ///
  100. /// - Returns: A single byte
  101. /// - Throws: SocketError.recvFailed if unable to read from the socket
  102. open func read() throws -> UInt8 {
  103. var byte: UInt8 = 0
  104. #if os(Linux)
  105. let count = Glibc.read(self.socketFileDescriptor as Int32, &byte, 1)
  106. #else
  107. let count = Darwin.read(self.socketFileDescriptor as Int32, &byte, 1)
  108. #endif
  109. guard count > 0 else {
  110. throw SocketError.recvFailed(Errno.description())
  111. }
  112. return byte
  113. }
  114. /// Read up to `length` bytes from this socket
  115. ///
  116. /// - Parameter length: The maximum bytes to read
  117. /// - Returns: A buffer containing the bytes read
  118. /// - Throws: SocketError.recvFailed if unable to read bytes from the socket
  119. open func read(length: Int) throws -> [UInt8] {
  120. var buffer = UnsafeMutableBufferPointer<UInt8>.allocate(capacity: length)
  121. let bytesRead = try read(into: &buffer, length: length)
  122. let rv = [UInt8](buffer[0..<bytesRead])
  123. buffer.deallocate()
  124. return rv
  125. }
  126. static let kBufferLength = 1024
  127. /// Read up to `length` bytes from this socket into an existing buffer
  128. ///
  129. /// - Parameter into: The buffer to read into (must be at least length bytes in size)
  130. /// - Parameter length: The maximum bytes to read
  131. /// - Returns: The number of bytes read
  132. /// - Throws: SocketError.recvFailed if unable to read bytes from the socket
  133. func read(into buffer: inout UnsafeMutableBufferPointer<UInt8>, length: Int) throws -> Int {
  134. var offset = 0
  135. guard let baseAddress = buffer.baseAddress else { return 0 }
  136. while offset < length {
  137. // Compute next read length in bytes. The bytes read is never more than kBufferLength at once.
  138. let readLength = offset + Socket.kBufferLength < length ? Socket.kBufferLength : length - offset
  139. #if os(Linux)
  140. let bytesRead = Glibc.read(self.socketFileDescriptor as Int32, baseAddress + offset, readLength)
  141. #else
  142. let bytesRead = Darwin.read(self.socketFileDescriptor as Int32, baseAddress + offset, readLength)
  143. #endif
  144. guard bytesRead > 0 else {
  145. throw SocketError.recvFailed(Errno.description())
  146. }
  147. offset += bytesRead
  148. }
  149. return offset
  150. }
  151. private static let CR: UInt8 = 13
  152. private static let NL: UInt8 = 10
  153. public func readLine() throws -> String {
  154. var characters: String = ""
  155. var n: UInt8 = 0
  156. repeat {
  157. n = try self.read()
  158. if n > Socket.CR { characters.append(Character(UnicodeScalar(n))) }
  159. } while n != Socket.NL
  160. return characters
  161. }
  162. public func peername() throws -> String {
  163. var addr = sockaddr(), len: socklen_t = socklen_t(MemoryLayout<sockaddr>.size)
  164. if getpeername(self.socketFileDescriptor, &addr, &len) != 0 {
  165. throw SocketError.getPeerNameFailed(Errno.description())
  166. }
  167. var hostBuffer = [CChar](repeating: 0, count: Int(NI_MAXHOST))
  168. if getnameinfo(&addr, len, &hostBuffer, socklen_t(hostBuffer.count), nil, 0, NI_NUMERICHOST) != 0 {
  169. throw SocketError.getNameInfoFailed(Errno.description())
  170. }
  171. return String(cString: hostBuffer)
  172. }
  173. public class func setNoSigPipe(_ socket: Int32) {
  174. #if os(Linux)
  175. // There is no SO_NOSIGPIPE in Linux (nor some other systems). You can instead use the MSG_NOSIGNAL flag when calling send(),
  176. // or use signal(SIGPIPE, SIG_IGN) to make your entire application ignore SIGPIPE.
  177. #else
  178. // Prevents crashes when blocking calls are pending and the app is paused ( via Home button ).
  179. var no_sig_pipe: Int32 = 1
  180. setsockopt(socket, SOL_SOCKET, SO_NOSIGPIPE, &no_sig_pipe, socklen_t(MemoryLayout<Int32>.size))
  181. #endif
  182. }
  183. public class func close(_ socket: Int32) {
  184. #if os(Linux)
  185. let _ = Glibc.close(socket)
  186. #else
  187. let _ = Darwin.close(socket)
  188. #endif
  189. }
  190. }
  191. public func == (socket1: Socket, socket2: Socket) -> Bool {
  192. return socket1.socketFileDescriptor == socket2.socketFileDescriptor
  193. }