Etan1

getaddrinfo

Oct 4th, 2016
265
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Swift 4.35 KB | None | 0 0
  1. import Foundation
  2.  
  3. public final class addrinfo {
  4.     fileprivate(set) public var ai_flags: Int32
  5.     fileprivate(set) public var ai_family: Int32
  6.     fileprivate(set) public var ai_socktype: Int32
  7.     fileprivate(set) public var ai_protocol: Int32
  8.     fileprivate(set) public var ai_addrlen: socklen_t
  9.     fileprivate(set) public var ai_canonname: String?
  10.     fileprivate(set) public var ai_addr: sockaddr_storage?
  11.     fileprivate(set) public var ai_next: addrinfo?
  12.  
  13.     fileprivate init(
  14.         ai_flags: Int32,
  15.         ai_family: Int32,
  16.         ai_socktype: Int32,
  17.         ai_protocol: Int32,
  18.         ai_addrlen: socklen_t,
  19.         ai_canonname: String?,
  20.         ai_addr: sockaddr_storage?,
  21.         ai_next: addrinfo?)
  22.     {
  23.         self.ai_flags = ai_flags
  24.         self.ai_family = ai_family
  25.         self.ai_socktype = ai_socktype
  26.         self.ai_protocol = ai_protocol
  27.         self.ai_addrlen = ai_addrlen
  28.         self.ai_canonname = ai_canonname
  29.         self.ai_addr = ai_addr
  30.         self.ai_next = ai_next
  31.     }
  32.  
  33.     public convenience init(ai_flags: Int32, ai_family: Int32, ai_socktype: Int32, ai_protocol: Int32) {
  34.         self.init(
  35.             ai_flags: ai_flags,
  36.             ai_family: ai_family,
  37.             ai_socktype: ai_socktype,
  38.             ai_protocol: ai_protocol,
  39.             ai_addrlen: 0,
  40.             ai_canonname: nil,
  41.             ai_addr: nil,
  42.             ai_next: nil)
  43.     }
  44. }
  45.  
  46. public func getaddrinfo(_ node: String?, _ service: String?, _ hints: addrinfo?) throws -> addrinfo? {
  47.     if let hints = hints {
  48.         precondition(hints.ai_addrlen == 0)
  49.         precondition(hints.ai_canonname == nil)
  50.         precondition(hints.ai_addr == nil)
  51.         precondition(hints.ai_next == nil)
  52.     }
  53.  
  54.     let err: Int32
  55.     var res: UnsafeMutablePointer<Foundation.addrinfo>?
  56.     if let hints = hints {
  57.         var hints = Foundation.addrinfo(
  58.             ai_flags: hints.ai_flags,
  59.             ai_family: hints.ai_family,
  60.             ai_socktype: hints.ai_socktype,
  61.             ai_protocol: hints.ai_protocol,
  62.             ai_addrlen: 0,
  63.             ai_canonname: nil,
  64.             ai_addr: nil,
  65.             ai_next: nil)
  66.         if let node = node {
  67.             if let service = service {
  68.                 err = Foundation.getaddrinfo(node, service, &hints, &res)
  69.             } else {
  70.                 err = Foundation.getaddrinfo(node, nil, &hints, &res)
  71.             }
  72.         } else {
  73.             if let service = service {
  74.                 err = Foundation.getaddrinfo(nil, service, &hints, &res)
  75.             } else {
  76.                 err = Foundation.getaddrinfo(nil, nil, &hints, &res)
  77.             }
  78.         }
  79.     } else {
  80.         if let node = node {
  81.             if let service = service {
  82.                 err = Foundation.getaddrinfo(node, service, nil, &res)
  83.             } else {
  84.                 err = Foundation.getaddrinfo(node, nil, nil, &res)
  85.             }
  86.         } else {
  87.             if let service = service {
  88.                 err = Foundation.getaddrinfo(nil, service, nil, &res)
  89.             } else {
  90.                 err = Foundation.getaddrinfo(nil, nil, nil, &res)
  91.             }
  92.         }
  93.     }
  94.     if err == EAI_SYSTEM {
  95.         throw SystemError.getaddrinfo(err, errno)
  96.     }
  97.     if err != 0 {
  98.         throw SystemError.getaddrinfo(err, nil)
  99.     }
  100.     defer {
  101.         freeaddrinfo(res)
  102.     }
  103.  
  104.     var result: addrinfo? = nil
  105.     var ai_last: addrinfo? = nil
  106.     if let res = res {
  107.         for res in sequence(first: res.pointee, next: { $0.ai_next?.pointee }) {
  108.             var ai_addr: sockaddr_storage?
  109.             if res.ai_addr != nil {
  110.                 ai_addr = sockaddr_storage()
  111.                 assert(Int(res.ai_addrlen) <= MemoryLayout.size(ofValue: ai_addr))
  112.                 memcpy(&ai_addr, res.ai_addr!, Int(res.ai_addrlen))
  113.             }
  114.             let ai = addrinfo(
  115.                 ai_flags: res.ai_flags,
  116.                 ai_family: res.ai_family,
  117.                 ai_socktype: res.ai_socktype,
  118.                 ai_protocol: res.ai_protocol,
  119.                 ai_addrlen: res.ai_addrlen,
  120.                 ai_canonname: res.ai_canonname == nil ? nil : String(cString: res.ai_canonname!),
  121.                 ai_addr: ai_addr,
  122.                 ai_next: nil)
  123.  
  124.             result = result ?? ai
  125.             ai_last?.ai_next = ai
  126.             ai_last = ai
  127.         }
  128.     }
  129.     return result
  130. }
Advertisement
Add Comment
Please, Sign In to add comment