Commit 5e8eb250 authored by James Hughes's avatar James Hughes
Browse files

Merge remote-tracking branch 'origin/master'

parents 4efe17c4 7ef0fe89
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -4,7 +4,7 @@ PODS:
  - CryptoSwift (0.0.12)
  - ProtocolBuffers-Swift (2.0)
  - Result (0.6-beta.1)
  - Socket (0.1.0)
  - Socket (0.2.0)

DEPENDENCIES:
  - BrightFutures (from `https://github.com/Thomvis/BrightFutures`)
@@ -32,6 +32,6 @@ SPEC CHECKSUMS:
  CryptoSwift: 16f1b5a768057636275b76d1c43231c2abba9e80
  ProtocolBuffers-Swift: cf3b2c2ee00cd89374612d58d6043f409a798b3f
  Result: 6c990ec4a72470672f9fc5b6fef009da0f6f40d1
  Socket: 0c7dfa1ec25b7b517a3e5e088b76ce2d4ec4d16f
  Socket: 8aed603b0b94e4c16b2d9ba3d5c18fd9dce98a90

COCOAPODS: 0.38.2
+2 −2
Original line number Diff line number Diff line
@@ -4,7 +4,7 @@ PODS:
  - CryptoSwift (0.0.12)
  - ProtocolBuffers-Swift (2.0)
  - Result (0.6-beta.1)
  - Socket (0.1.0)
  - Socket (0.2.0)

DEPENDENCIES:
  - BrightFutures (from `https://github.com/Thomvis/BrightFutures`)
@@ -32,6 +32,6 @@ SPEC CHECKSUMS:
  CryptoSwift: 16f1b5a768057636275b76d1c43231c2abba9e80
  ProtocolBuffers-Swift: cf3b2c2ee00cd89374612d58d6043f409a798b3f
  Result: 6c990ec4a72470672f9fc5b6fef009da0f6f40d1
  Socket: 0c7dfa1ec25b7b517a3e5e088b76ce2d4ec4d16f
  Socket: 8aed603b0b94e4c16b2d9ba3d5c18fd9dce98a90

COCOAPODS: 0.38.2
+552 −548

File changed.

Preview size limit exceeded, changes collapsed.

+3 −0
Original line number Diff line number Diff line
# A pure sockets library for Swift 
[![CocoaPods](https://img.shields.io/cocoapods/v/Socket.svg)](https://cocoapods.org/pods/Socket)
[![CocoaPods](https://img.shields.io/cocoapods/l/Socket.svg)](https://github.com/jphughes/socket-swift/blob/master/LICENSE/mit.md)
[![CocoaPods](https://img.shields.io/cocoapods/p/Socket.svg)]()

This is a work-in-progress 
+79 −5
Original line number Diff line number Diff line
@@ -10,11 +10,85 @@ import Foundation

protocol DatagramProtocol {
    
    init(port: Int) throws
    var port:Int { get }
    func send (host:in_addr_t, port:in_port_t, message:Bytes) throws
    // opens datagram socket to a given port. To get an ephemeral port, 
    // leave the port off or specify port 0
    init(port: in_port_t) throws
    
    // opens a datagram socket to a specific multicast address and port.
    init(multicast:String, port p:in_port_t) throws
    
    // get the port (useful for ephemeral port)
    var port:in_port_t { get }
    
    // sends a message
    func send (host:String, port:in_port_t, message:Bytes) throws
    func recv (length: Int) throws -> (host:in_addr_t, port:in_port_t, message:Bytes)
    func join (host:String)
    
    // receives a message. host and port are the source of the message
    func recv (length: Int, timeout:Double) throws -> (host:String, port:in_port_t, message:Bytes)
}


public class Datagram: Socket, DatagramProtocol {
    
    enum Error:ErrorType {
        case timeout
    }
    
    public required init(port p:in_port_t = 0) throws {
        try super.init(sock: socket(AF_INET,SOCK_DGRAM,0))

        var yes:Int32 = 1
        guard setsockopt(s,SOL_SOCKET,SO_REUSEADDR,&yes,socklen_t(strideof(Int32))) == 0 else {
            throw PosixError(comment: "Datagram setsockopt(SO_REUSEADDR...)")
        }
        
        var bindPort = sockaddr(host: "0.0.0.0", port: p)
        guard bind(s, &bindPort, socklen_t(strideof(sockaddr))) == 0 else {
            throw PosixError(comment: "Datagram bind(...)")
        }

        try setPort()
    }
    
    convenience required public init(multicast:String, port p:in_port_t) throws {
        try self.init(port:p)
        
        let group = in_addr(s_addr: inet_addr(multicast))
        let interface = in_addr(s_addr: inet_addr("0.0.0.0"))
        var mcq = ip_mreq(imr_multiaddr: group, imr_interface: interface)
        guard setsockopt(s, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mcq,(socklen_t(strideof(ip_mreq)))) == 0 else {
            throw PosixError(comment: "Datagram setsockopt(IP_ADD_MEMBERSHIP...)")
        }
    }
    
    func send (host:String, port:in_port_t, var message:Bytes) throws {
        var sa = sockaddr(host: host, port: port)
        switch sendto(s, &message, message.count, 0, &sa, socklen_t(strideof(sockaddr))) {
        case let x where x < 0:
            throw PosixError(comment: "write(...) failed.")
        case message.count:
            return // happy
        case let x:     // x > 0 then
            fatalError("partial write len \(x) should have been \(message.count)")
        }
    }
    
    func recv (length: Int, timeout:Double = 0) throws -> (host:String, port:in_port_t, message:Bytes) {
        try setRdTimeout(timeout)
        var message = Bytes(count: 65535, repeatedValue: 0)
        var sa = sockaddr()
        var salen = socklen_t(strideof(sockaddr))
        switch recvfrom(s, &message, message.count, 0, &sa, &salen) {
        case let x where x < 0 && errno == 35:
            throw Error.timeout
        case let x where x < 0:
            throw PosixError(comment: "Datagram read(...)")
        case let x:
            message.removeRange( x ..< message.count)
        }
        let sin = sockaddr_in(fromSockaddr: sa)
        
        let host = String(CString: inet_ntoa(sin.sin_addr), encoding: NSUTF8StringEncoding)
        return (host!, sin.sin_port.byteSwapped, message)
    }
}
 No newline at end of file
Loading