Socket.swift 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106
  1. //
  2. // Socket.swift
  3. // Swifter
  4. // Copyright (c) 2014 Damian Kołakowski. All rights reserved.
  5. //
  6. import Foundation
  7. /* Low level routines for POSIX sockets */
  8. struct Socket {
  9. static func lastErr(reason: String) -> NSError {
  10. let errorCode = errno
  11. if let errorText = String.fromCString(UnsafePointer(strerror(errorCode))) {
  12. return NSError(domain: "SOCKET", code: Int(errorCode), userInfo: [NSLocalizedFailureReasonErrorKey : reason, NSLocalizedDescriptionKey : errorText])
  13. }
  14. return NSError(domain: "SOCKET", code: Int(errorCode), userInfo: nil)
  15. }
  16. static func tcpForListen(port: in_port_t = 8080, error:NSErrorPointer = nil) -> CInt? {
  17. let s = socket(AF_INET, SOCK_STREAM, 0)
  18. if ( s == -1 ) {
  19. if error != nil { error.memory = lastErr("socket(...) failed.") }
  20. return nil
  21. }
  22. var value: Int32 = 1;
  23. if ( setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &value, socklen_t(sizeof(Int32))) == -1 ) {
  24. release(s)
  25. if error != nil { error.memory = lastErr("setsockopt(...) failed.") }
  26. return nil
  27. }
  28. nosigpipe(s)
  29. var addr = sockaddr_in(sin_len: __uint8_t(sizeof(sockaddr_in)), sin_family: sa_family_t(AF_INET),
  30. sin_port: port_htons(port), sin_addr: in_addr(s_addr: inet_addr("0.0.0.0")), sin_zero: (0, 0, 0, 0, 0, 0, 0, 0))
  31. var sock_addr = sockaddr(sa_len: 0, sa_family: 0, sa_data: (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0))
  32. memcpy(&sock_addr, &addr, UInt(sizeof(sockaddr_in)))
  33. if ( bind(s, &sock_addr, socklen_t(sizeof(sockaddr_in))) == -1 ) {
  34. release(s)
  35. if error != nil { error.memory = lastErr("bind(...) failed.") }
  36. return nil
  37. }
  38. if ( listen(s, 20 /* max pending connection */ ) == -1 ) {
  39. release(s)
  40. if error != nil { error.memory = lastErr("listen(...) failed.") }
  41. return nil
  42. }
  43. return s
  44. }
  45. static func writeStringUTF8(socket: CInt, string: String, error: NSErrorPointer = nil) -> Bool {
  46. if let nsdata = string.dataUsingEncoding(NSUTF8StringEncoding) {
  47. writeData(socket, data: nsdata, error: error)
  48. }
  49. return true
  50. }
  51. static func writeStringASCII(socket: CInt, string: String, error: NSErrorPointer = nil) -> Bool {
  52. if let nsdata = string.dataUsingEncoding(NSASCIIStringEncoding) {
  53. writeData(socket, data: nsdata, error: error)
  54. }
  55. return true
  56. }
  57. static func writeData(socket: CInt, data: NSData, error:NSErrorPointer = nil) -> Bool {
  58. var sent = 0
  59. let unsafePointer = UnsafePointer<UInt8>(data.bytes)
  60. while ( sent < data.length ) {
  61. let s = write(socket, unsafePointer + sent, UInt(data.length - sent))
  62. if ( s <= 0 ) {
  63. if error != nil { error.memory = lastErr("write(...) failed.") }
  64. return false
  65. }
  66. sent += s
  67. }
  68. return true
  69. }
  70. static func acceptClientSocket(socket: CInt, error:NSErrorPointer = nil) -> CInt? {
  71. 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)), len: socklen_t = 0
  72. let clientSocket = accept(socket, &addr, &len)
  73. if ( clientSocket != -1 ) {
  74. Socket.nosigpipe(clientSocket)
  75. return clientSocket
  76. }
  77. if error != nil { error.memory = lastErr("accept(...) failed.") }
  78. return nil
  79. }
  80. static func nosigpipe(socket: CInt) {
  81. // prevents crashes when blocking calls are pending and the app is paused ( via Home button )
  82. var no_sig_pipe: Int32 = 1;
  83. setsockopt(socket, SOL_SOCKET, SO_NOSIGPIPE, &no_sig_pipe, socklen_t(sizeof(Int32)));
  84. }
  85. static func port_htons(port: in_port_t) -> in_port_t {
  86. let isLittleEndian = Int(OSHostByteOrder()) == OSLittleEndian
  87. return isLittleEndian ? _OSSwapInt16(port) : port
  88. }
  89. static func release(socket: CInt) {
  90. shutdown(socket, SHUT_RDWR)
  91. close(socket)
  92. }
  93. }