Skip to content

Commit dac03b9

Browse files
committed
init
1 parent 76f8e4c commit dac03b9

11 files changed

+1101
-0
lines changed

.gitignore

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
.DS_Store
2+
/.build
3+
/Packages
4+
/*.xcodeproj

Package.swift

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import PackageDescription
2+
3+
let package = Package(
4+
name: "WebSocket",
5+
dependencies: [
6+
.Package(url: "https://github.com/slimane-swift/HTTPCore.git", majorVersion: 0, minor: 1),
7+
.Package(url: "https://github.com/Zewo/POSIX.git", majorVersion: 0, minor: 14),
8+
]
9+
)

Sources/CloseCode.swift

+94
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
// The MIT License (MIT)
2+
//
3+
// Copyright (c) 2015 Zewo
4+
//
5+
// Permission is hereby granted, free of charge, to any person obtaining a copy
6+
// of this software and associated documentation files (the "Software"), to deal
7+
// in the Software without restriction, including without limitation the rights
8+
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
// copies of the Software, and to permit persons to whom the Software is
10+
// furnished to do so, subject to the following conditions:
11+
//
12+
// The above copyright notice and this permission notice shall be included in all
13+
// copies or substantial portions of the Software.
14+
//
15+
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
// SOFTWARE.
22+
23+
public enum CloseCode : Equatable {
24+
case normal
25+
case goingAway
26+
case protocolError
27+
case unsupported
28+
case noStatus
29+
case abnormal
30+
case unsupportedData
31+
case policyViolation
32+
case tooLarge
33+
case missingExtension
34+
case internalError
35+
case serviceRestart
36+
case tryAgainLater
37+
case tlsHandshake
38+
case raw(UInt16)
39+
40+
init(code: UInt16) {
41+
switch code {
42+
case 1000: self = .normal
43+
case 1001: self = .goingAway
44+
case 1002: self = .protocolError
45+
case 1003: self = .unsupported
46+
case 1005: self = .noStatus
47+
case 1006: self = .abnormal
48+
case 1007: self = .unsupportedData
49+
case 1008: self = .policyViolation
50+
case 1009: self = .tooLarge
51+
case 1010: self = .missingExtension
52+
case 1011: self = .internalError
53+
case 1012: self = .serviceRestart
54+
case 1013: self = .tryAgainLater
55+
case 1015: self = .tlsHandshake
56+
default: self = .raw(UInt16(code))
57+
}
58+
}
59+
60+
var code: UInt16 {
61+
switch self {
62+
case .normal: return 1000
63+
case .goingAway: return 1001
64+
case .protocolError: return 1002
65+
case .unsupported: return 1003
66+
case .noStatus: return 1005
67+
case .abnormal: return 1006
68+
case .unsupportedData: return 1007
69+
case .policyViolation: return 1008
70+
case .tooLarge: return 1009
71+
case .missingExtension: return 1010
72+
case .internalError: return 1011
73+
case .serviceRestart: return 1012
74+
case .tryAgainLater: return 1013
75+
case .tlsHandshake: return 1015
76+
case .raw(let code): return code
77+
}
78+
}
79+
80+
var isValid: Bool {
81+
let code = self.code
82+
83+
if code >= 1000 && code <= 5000 {
84+
return code != 1004 && code != 1005 && code != 1006 && code != 1014 && code != 1015
85+
&& code != 1016 && code != 1100 && code != 2000 && code != 2999
86+
}
87+
88+
return false
89+
}
90+
}
91+
92+
public func == (lhs: CloseCode, rhs: CloseCode) -> Bool {
93+
return lhs.code == rhs.code
94+
}

Sources/Data.swift

+78
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
// The MIT License (MIT)
2+
//
3+
// Copyright (c) 2015 Zewo
4+
//
5+
// Permission is hereby granted, free of charge, to any person obtaining a copy
6+
// of this software and associated documentation files (the "Software"), to deal
7+
// in the Software without restriction, including without limitation the rights
8+
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
// copies of the Software, and to permit persons to whom the Software is
10+
// furnished to do so, subject to the following conditions:
11+
//
12+
// The above copyright notice and this permission notice shall be included in all
13+
// copies or substantial portions of the Software.
14+
//
15+
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
// SOFTWARE.
22+
23+
import Foundation
24+
import POSIX
25+
26+
extension Data {
27+
init<T>(number: T) {
28+
let totalBytes = MemoryLayout<T>.size
29+
let valuePointer = UnsafeMutablePointer<T>.allocate(capacity: 1)
30+
valuePointer.pointee = number
31+
32+
let bytesPointer = unsafeBitCast(valuePointer, to: UnsafeMutablePointer<Byte>.self)
33+
var bytes = [UInt8](repeating: 0, count: totalBytes)
34+
for j in 0 ..< totalBytes {
35+
bytes[totalBytes - 1 - j] = (bytesPointer + j).pointee
36+
}
37+
valuePointer.deinitialize()
38+
valuePointer.deallocate(capacity: 1)
39+
self.init(bytes)
40+
}
41+
42+
func toInt(size: Int, offset: Int = 0) -> UIntMax {
43+
guard size > 0 && size <= 8 && count >= offset+size else { return 0 }
44+
let slice = self[startIndex.advanced(by: offset) ..< startIndex.advanced(by: offset+size)]
45+
var result: UIntMax = 0
46+
for (idx, byte) in slice.enumerated() {
47+
let shiftAmount = UIntMax(size.toIntMax() - idx - 1) * 8
48+
result += UIntMax(byte) << shiftAmount
49+
}
50+
return result
51+
}
52+
53+
init(randomBytes byteCount: Int) throws {
54+
var bytes = [UInt8](repeating: 0, count: byteCount)
55+
56+
#if os(Linux)
57+
let urandom = open("/dev/urandom", O_RDONLY)
58+
59+
if urandom == -1 {
60+
try ensureLastOperationSucceeded()
61+
}
62+
63+
if read(urandom, &bytes, bytes.count) == -1 {
64+
try ensureLastOperationSucceeded()
65+
}
66+
67+
if close(urandom) == -1 {
68+
try ensureLastOperationSucceeded()
69+
}
70+
#else
71+
if SecRandomCopyBytes(kSecRandomDefault, byteCount, &bytes) == -1 {
72+
try ensureLastOperationSucceeded()
73+
}
74+
#endif
75+
76+
self.init(bytes)
77+
}
78+
}

Sources/EventEmitter.swift

+41
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
// The MIT License (MIT)
2+
//
3+
// Copyright (c) 2015 Zewo
4+
//
5+
// Permission is hereby granted, free of charge, to any person obtaining a copy
6+
// of this software and associated documentation files (the "Software"), to deal
7+
// in the Software without restriction, including without limitation the rights
8+
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
// copies of the Software, and to permit persons to whom the Software is
10+
// furnished to do so, subject to the following conditions:
11+
//
12+
// The above copyright notice and this permission notice shall be included in all
13+
// copies or substantial portions of the Software.
14+
//
15+
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
// SOFTWARE.
22+
23+
public final class EventEmitter<T> {
24+
fileprivate var listeners: [EventListener<T>] = []
25+
26+
public init() {}
27+
28+
public func addListener(_ times: Int = -1, listen: @escaping EventListener<T>.Listen) -> EventListener<T> {
29+
let listener = EventListener<T>(calls: times, listen: listen)
30+
listeners.append(listener)
31+
return listener
32+
}
33+
34+
public func emit(_ event: T) throws {
35+
listeners = listeners.filter({ $0.active })
36+
37+
for listener in listeners {
38+
let _ = try listener.call(event)
39+
}
40+
}
41+
}

Sources/EventListener.swift

+49
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
// The MIT License (MIT)
2+
//
3+
// Copyright (c) 2015 Zewo
4+
//
5+
// Permission is hereby granted, free of charge, to any person obtaining a copy
6+
// of this software and associated documentation files (the "Software"), to deal
7+
// in the Software without restriction, including without limitation the rights
8+
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
// copies of the Software, and to permit persons to whom the Software is
10+
// furnished to do so, subject to the following conditions:
11+
//
12+
// The above copyright notice and this permission notice shall be included in all
13+
// copies or substantial portions of the Software.
14+
//
15+
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
// SOFTWARE.
22+
23+
public final class EventListener<T> {
24+
public typealias Listen = (T) throws -> Void
25+
26+
fileprivate let listen: Listen
27+
fileprivate var calls: Int
28+
var active = true
29+
30+
init(calls: Int, listen: @escaping Listen) {
31+
self.calls = calls
32+
self.listen = listen
33+
}
34+
35+
func call(_ event: T) throws -> Bool {
36+
calls -= 1
37+
38+
if calls == 0 {
39+
active = false
40+
}
41+
42+
try listen(event)
43+
return active
44+
}
45+
46+
public func stop() {
47+
active = false
48+
}
49+
}

0 commit comments

Comments
 (0)