5
5
// Created by Rene Hexel on 10/12/16.
6
6
// Copyright © 2016 René Hexel. All rights reserved.
7
7
//
8
- //#if os(Linux)
9
-
10
8
import CoreFoundation
11
9
import Foundation
12
10
@@ -15,50 +13,98 @@ import Foundation
15
13
private func CFStreamPropertyKey( rawValue: CFString ) -> CFString {
16
14
return rawValue
17
15
}
16
+
17
+ /// Set bind the given socket to the given address and listen for connections
18
+ ///
19
+ /// - Parameters:
20
+ /// - s: `CFSocket` to bind
21
+ /// - address: IP address to bind to (Data containing a `struct sockaddr*`)
22
+ /// - Returns: `0` if successful, an error code otherwise
23
+ @discardableResult
24
+ func CFSocketSetAddress( _ s: CFSocket , _ address: CFData ! ) -> CFSocketError {
25
+ let len = socklen_t ( CFDataGetLength ( address) )
26
+ guard address != nil ,
27
+ len >= socklen_t ( MemoryLayout< sockaddr_in> . size) ,
28
+ CFSocketIsValid ( s) else {
29
+ return CFSocketError ( kCFSocketError)
30
+ }
31
+ let sock = CFSocketGetNative ( s)
32
+ return CFDataGetBytePtr ( address) . withMemoryRebound ( to: sockaddr. self, capacity: 1 ) { ( addr: UnsafePointer < sockaddr > ! ) -> CFSocketError in
33
+ guard addr != nil else { return CFSocketError ( kCFSocketError) }
34
+ guard bind ( sock, addr, len) == 0 ,
35
+ listen ( sock, 256 ) == 0 else { return CFSocketError ( errno) }
36
+ return CFSocketError ( kCFSocketSuccess)
37
+ }
38
+ }
18
39
#else
19
40
private let utf8 = CFStringBuiltInEncodings . UTF8. rawValue
20
41
#endif
21
42
43
+ extension CFSocketNativeHandle {
44
+ func get( _ buffer: UnsafeMutableRawPointer , maxLength len: Int ) -> Int {
45
+ return Int ( read ( Int32 ( self ) , buffer, ssize_t ( len) ) )
46
+ }
47
+
48
+ func put( _ buffer: UnsafeRawPointer , maxLength len: Int ) -> Int {
49
+ return Int ( write ( Int32 ( self ) , buffer, ssize_t ( len) ) )
50
+ }
51
+
52
+ func closeReadingEnd( ) {
53
+ shutdown ( Int32 ( self ) , Int32 ( SHUT_RD) )
54
+ }
55
+
56
+ func closeWritingEnd( ) {
57
+ shutdown ( Int32 ( self ) , Int32 ( SHUT_WR) )
58
+ }
59
+
60
+ func has( events: Int16 = Int16 ( POLLIN) ) -> Bool {
61
+ var fd = pollfd ( fd: Int32 ( self ) , events: events, revents: 0 )
62
+ return poll ( & fd, 1 , 0 ) > 0
63
+ }
64
+ }
65
+
22
66
public class DNSSDNetServiceInputStream : InputStream {
23
- var cfStream : CFReadStream
67
+ var sock : CFSocketNativeHandle
68
+ var status = Status . open
24
69
25
- /// Initialise from a `CFReadStream `
70
+ /// Initialise from a `CFSocketNativeHandle `
26
71
///
27
- /// - Parameter stream: CoreFoundation read stream to initialise from
28
- public init ( _ stream : CFReadStream ) {
29
- cfStream = stream
72
+ /// - Parameter socket: Already connected socket to initialise from
73
+ public init ( _ socket : CFSocketNativeHandle ) {
74
+ sock = socket
30
75
super. init ( data: Data ( ) )
31
76
}
32
77
33
78
public override func read( _ buffer: UnsafeMutablePointer < UInt8 > , maxLength len: Int ) -> Int {
34
- return CFReadStreamRead ( cfStream , buffer, CFIndex ( len) )
79
+ return sock . get ( buffer, maxLength : len)
35
80
}
36
81
37
82
public override func getBuffer( _ buffer: UnsafeMutablePointer < UnsafeMutablePointer < UInt8 > ? > , length len: UnsafeMutablePointer < Int > ) -> Bool {
38
83
return false
39
84
}
40
85
41
86
public override var hasBytesAvailable : Bool {
42
- return CFReadStreamHasBytesAvailable ( cfStream )
87
+ return sock . has ( events : Int16 ( POLLIN ) )
43
88
}
44
89
45
90
public override func open( ) {
46
- CFReadStreamOpen ( cfStream)
47
91
}
48
92
49
93
public override func close( ) {
50
- CFReadStreamClose ( cfStream)
94
+ sock. closeReadingEnd ( )
95
+ status = Status . closed
51
96
}
52
97
53
98
public override var streamStatus : Status {
54
- let status = CFReadStreamGetStatus ( cfStream)
55
- return Stream . Status ( rawValue: unsafeBitCast ( status, to: UInt . self) ) !
99
+ return status
56
100
}
57
101
}
58
102
59
103
60
104
public class DNSSDNetServiceOutputStream : OutputStream {
61
- var cfStream : CFWriteStream !
105
+ var sock : CFSocketNativeHandle
106
+ var status = Status . open
107
+ var properties = Dictionary < PropertyKey , PropertyValue > ( )
62
108
63
109
#if os(Linux)
64
110
public typealias PropertyValue = AnyObject
@@ -70,50 +116,41 @@ public class DNSSDNetServiceOutputStream: OutputStream {
70
116
public typealias PropertyValue = Any
71
117
#endif
72
118
73
- public init ( _ stream : CFWriteStream ) {
74
- cfStream = stream
119
+ public init ( _ socket : CFSocketNativeHandle ) {
120
+ sock = socket
75
121
super. init ( toMemory: ( ) )
76
122
}
77
123
78
124
79
125
// writes the bytes from the specified buffer to the stream up to len bytes. Returns the number of bytes actually written.
80
126
public override func write( _ buffer: UnsafePointer < UInt8 > , maxLength len: Int ) -> Int {
81
- return CFWriteStreamWrite ( cfStream , buffer, len)
127
+ return sock . put ( buffer, maxLength : len)
82
128
}
83
129
84
130
// returns YES if the stream can be written to or if it is impossible to tell without actually doing the write.
85
131
public override var hasSpaceAvailable : Bool {
86
- return CFWriteStreamCanAcceptBytes ( cfStream )
132
+ return sock . has ( events : Int16 ( POLLOUT ) )
87
133
}
88
134
89
135
public override func open( ) {
90
- CFWriteStreamOpen ( cfStream)
91
136
}
92
137
93
138
public override func close( ) {
94
- CFWriteStreamClose ( cfStream)
139
+ sock. closeReadingEnd ( )
140
+ status = Status . closed
95
141
}
96
142
97
143
public override var streamStatus : Status {
98
- let status = CFWriteStreamGetStatus ( cfStream)
99
- return Stream . Status ( rawValue: unsafeBitCast ( status, to: UInt . self) ) !
144
+ return status
100
145
}
101
146
102
147
public override func property( forKey key: PropertyKey ) -> PropertyValue ? {
103
- return key. rawValue. withCString {
104
- guard let k = CFStringCreateWithCString ( kCFAllocatorDefault, $0, utf8) else {
105
- return nil
106
- }
107
- return CFWriteStreamCopyProperty ( cfStream, CFStreamPropertyKey ( rawValue: k) )
108
- }
148
+ return properties [ key]
109
149
}
110
150
111
151
public override func setProperty( _ property: PropertyValue ? , forKey key: PropertyKey ) -> Bool {
112
- return key. rawValue. withCString {
113
- guard let k = CFStringCreateWithCString ( kCFAllocatorDefault, $0, utf8) else {
114
- return false
115
- }
116
- return CFWriteStreamSetProperty ( cfStream, CFStreamPropertyKey ( rawValue: k) , property as AnyObject ? )
117
- }
152
+ let rv = super. setProperty ( property, forKey: key)
153
+ properties [ key] = property
154
+ return rv
118
155
}
119
156
}
0 commit comments