|
|
@@ -28,12 +28,12 @@ public enum SocketError: ErrorType {
|
|
|
|
|
|
public class Socket: Hashable, Equatable {
|
|
|
|
|
|
- public class func tcpSocketForListen(port: in_port_t, maxPendingConnection: Int32 = SOMAXCONN) throws -> Socket {
|
|
|
+ public class func tcpSocketForListen(port: in_port_t, forceIPv4: Bool = false, maxPendingConnection: Int32 = SOMAXCONN) throws -> Socket {
|
|
|
|
|
|
#if os(Linux)
|
|
|
- let socketFileDescriptor = socket(AF_INET, Int32(SOCK_STREAM.rawValue), 0)
|
|
|
+ let socketFileDescriptor = socket(forceIPv4 ? AF_INET : AF_INET6, Int32(SOCK_STREAM.rawValue), 0)
|
|
|
#else
|
|
|
- let socketFileDescriptor = socket(AF_INET6, SOCK_STREAM, 0)
|
|
|
+ let socketFileDescriptor = socket(forceIPv4 ? AF_INET : AF_INET6, SOCK_STREAM, 0)
|
|
|
#endif
|
|
|
|
|
|
if socketFileDescriptor == -1 {
|
|
|
@@ -49,30 +49,46 @@ public class Socket: Hashable, Equatable {
|
|
|
Socket.setNoSigPipe(socketFileDescriptor)
|
|
|
|
|
|
#if os(Linux)
|
|
|
- var addr = sockaddr_in()
|
|
|
- addr.sin_family = sa_family_t(AF_INET)
|
|
|
- addr.sin_port = Socket.htonsPort(port)
|
|
|
- addr.sin_addr = in_addr(s_addr: in_addr_t(0))
|
|
|
- addr.sin_zero = (0, 0, 0, 0, 0, 0, 0, 0)
|
|
|
+ var bindResult: Int32 = -1
|
|
|
+ if forceIPv4 {
|
|
|
+ var addr = sockaddr_in(sin_family: sa_family_t(AF_INET),
|
|
|
+ sin_port: Socket.htonsPort(port),
|
|
|
+ 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: Socket.htonsPort(port),
|
|
|
+ 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 addr = sockaddr_in6(
|
|
|
- sin6_len: UInt8(strideof(sockaddr_in6)),
|
|
|
- sin6_family: UInt8(AF_INET6),
|
|
|
- sin6_port: Socket.htonsPort(port),
|
|
|
- sin6_flowinfo: 0,
|
|
|
- sin6_addr: in6addr_any,
|
|
|
- sin6_scope_id: 0
|
|
|
- )
|
|
|
+ var bindResult: Int32 = -1
|
|
|
+ if forceIPv4 {
|
|
|
+ var addr = sockaddr_in(sin_len: UInt8(strideof(sockaddr_in)),
|
|
|
+ sin_family: UInt8(AF_INET),
|
|
|
+ sin_port: Socket.htonsPort(port),
|
|
|
+ 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: Socket.htonsPort(port),
|
|
|
+ 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
|
|
|
-
|
|
|
- var bind_addr = sockaddr_in6()
|
|
|
- memcpy(&bind_addr, &addr, Int(sizeof(sockaddr_in6)))
|
|
|
-
|
|
|
- let bind_result = withUnsafePointer(&bind_addr) { addr in
|
|
|
- return bind(socketFileDescriptor, UnsafePointer<sockaddr>(addr), socklen_t(sizeof(sockaddr_in6)))
|
|
|
- }
|
|
|
|
|
|
- if bind_result == -1 {
|
|
|
+ if bindResult == -1 {
|
|
|
let details = Socket.descriptionOfLastError()
|
|
|
Socket.release(socketFileDescriptor)
|
|
|
throw SocketError.BindFailed(details)
|