|
|
@@ -28,81 +28,7 @@ public enum SocketError: ErrorType {
|
|
|
}
|
|
|
|
|
|
public class Socket: Hashable, Equatable {
|
|
|
-
|
|
|
- public class func tcpSocketForListen(port: in_port_t, forceIPv4: Bool = false, maxPendingConnection: Int32 = SOMAXCONN) throws -> Socket {
|
|
|
-
|
|
|
- #if os(Linux)
|
|
|
- let socketFileDescriptor = socket(forceIPv4 ? AF_INET : AF_INET6, Int32(SOCK_STREAM.rawValue), 0)
|
|
|
- #else
|
|
|
- let socketFileDescriptor = socket(forceIPv4 ? AF_INET : AF_INET6, SOCK_STREAM, 0)
|
|
|
- #endif
|
|
|
-
|
|
|
- if socketFileDescriptor == -1 {
|
|
|
- throw SocketError.SocketCreationFailed(Errno.description())
|
|
|
- }
|
|
|
|
|
|
- var value: Int32 = 1
|
|
|
- if setsockopt(socketFileDescriptor, SOL_SOCKET, SO_REUSEADDR, &value, socklen_t(sizeof(Int32))) == -1 {
|
|
|
- let details = Errno.description()
|
|
|
- Socket.release(socketFileDescriptor)
|
|
|
- throw SocketError.SocketSettingReUseAddrFailed(details)
|
|
|
- }
|
|
|
- Socket.setNoSigPipe(socketFileDescriptor)
|
|
|
-
|
|
|
- #if os(Linux)
|
|
|
- var bindResult: Int32 = -1
|
|
|
- if forceIPv4 {
|
|
|
- var addr = sockaddr_in(sin_family: sa_family_t(AF_INET),
|
|
|
- sin_port: port.bigEndian,
|
|
|
- sin_addr: in_addr(s_addr: in_addr_t(0)),
|
|
|
- sin_zero:(0, 0, 0, 0, 0, 0, 0, 0))
|
|
|
-
|
|
|
- bindResult = withUnsafePointer(&addr) { bind(socketFileDescriptor, UnsafePointer<sockaddr>($0), socklen_t(sizeof(sockaddr_in))) }
|
|
|
- } else {
|
|
|
- var addr = sockaddr_in6(sin6_family: sa_family_t(AF_INET6),
|
|
|
- sin6_port: port.bigEndian,
|
|
|
- sin6_flowinfo: 0,
|
|
|
- sin6_addr: in6addr_any,
|
|
|
- sin6_scope_id: 0)
|
|
|
-
|
|
|
- bindResult = withUnsafePointer(&addr) { bind(socketFileDescriptor, UnsafePointer<sockaddr>($0), socklen_t(sizeof(sockaddr_in6))) }
|
|
|
- }
|
|
|
- #else
|
|
|
- var bindResult: Int32 = -1
|
|
|
- if forceIPv4 {
|
|
|
- var addr = sockaddr_in(sin_len: UInt8(strideof(sockaddr_in)),
|
|
|
- sin_family: UInt8(AF_INET),
|
|
|
- sin_port: port.bigEndian,
|
|
|
- sin_addr: in_addr(s_addr: in_addr_t(0)),
|
|
|
- sin_zero:(0, 0, 0, 0, 0, 0, 0, 0))
|
|
|
-
|
|
|
- bindResult = withUnsafePointer(&addr) { bind(socketFileDescriptor, UnsafePointer<sockaddr>($0), socklen_t(sizeof(sockaddr_in))) }
|
|
|
- } else {
|
|
|
- var addr = sockaddr_in6(sin6_len: UInt8(strideof(sockaddr_in6)),
|
|
|
- sin6_family: UInt8(AF_INET6),
|
|
|
- sin6_port: port.bigEndian,
|
|
|
- sin6_flowinfo: 0,
|
|
|
- sin6_addr: in6addr_any,
|
|
|
- sin6_scope_id: 0)
|
|
|
-
|
|
|
- bindResult = withUnsafePointer(&addr) { bind(socketFileDescriptor, UnsafePointer<sockaddr>($0), socklen_t(sizeof(sockaddr_in6))) }
|
|
|
- }
|
|
|
- #endif
|
|
|
-
|
|
|
- if bindResult == -1 {
|
|
|
- let details = Errno.description()
|
|
|
- Socket.release(socketFileDescriptor)
|
|
|
- throw SocketError.BindFailed(details)
|
|
|
- }
|
|
|
-
|
|
|
- if listen(socketFileDescriptor, maxPendingConnection ) == -1 {
|
|
|
- let details = Errno.description()
|
|
|
- Socket.release(socketFileDescriptor)
|
|
|
- throw SocketError.ListenFailed(details)
|
|
|
- }
|
|
|
- return Socket(socketFileDescriptor: socketFileDescriptor)
|
|
|
- }
|
|
|
-
|
|
|
let socketFileDescriptor: Int32
|
|
|
|
|
|
public init(socketFileDescriptor: Int32) {
|
|
|
@@ -149,6 +75,17 @@ public class Socket: Hashable, Equatable {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ public func isIPv4() throws -> Bool {
|
|
|
+ var addr = sockaddr_in()
|
|
|
+ return try withUnsafePointer(&addr) { pointer in
|
|
|
+ var len = socklen_t(sizeof(sockaddr_in))
|
|
|
+ if getsockname(socketFileDescriptor, UnsafeMutablePointer(pointer), &len) != 0 {
|
|
|
+ throw SocketError.GetSockNameFailed(Errno.description())
|
|
|
+ }
|
|
|
+ return Int32(addr.sin_family) == AF_INET
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
public func writeUTF8(string: String) throws {
|
|
|
try writeUInt8(ArraySlice(string.utf8))
|
|
|
}
|
|
|
@@ -211,7 +148,7 @@ public class Socket: Hashable, Equatable {
|
|
|
return name
|
|
|
}
|
|
|
|
|
|
- private class func setNoSigPipe(socket: Int32) {
|
|
|
+ public class func setNoSigPipe(socket: Int32) {
|
|
|
#if os(Linux)
|
|
|
// There is no SO_NOSIGPIPE in Linux (nor some other systems). You can instead use the MSG_NOSIGNAL flag when calling send(),
|
|
|
// or use signal(SIGPIPE, SIG_IGN) to make your entire application ignore SIGPIPE.
|
|
|
@@ -222,7 +159,7 @@ public class Socket: Hashable, Equatable {
|
|
|
#endif
|
|
|
}
|
|
|
|
|
|
- private class func shutdwn(socket: Int32) {
|
|
|
+ public class func shutdwn(socket: Int32) {
|
|
|
#if os(Linux)
|
|
|
shutdown(socket, Int32(SHUT_RDWR))
|
|
|
#else
|
|
|
@@ -230,7 +167,7 @@ public class Socket: Hashable, Equatable {
|
|
|
#endif
|
|
|
}
|
|
|
|
|
|
- private class func release(socket: Int32) {
|
|
|
+ public class func release(socket: Int32) {
|
|
|
#if os(Linux)
|
|
|
shutdown(socket, Int32(SHUT_RDWR))
|
|
|
#else
|