Skip to content
3 changes: 1 addition & 2 deletions Sources/Connection.swift
Original file line number Diff line number Diff line change
@@ -1,2 +1 @@
public protocol Connection : ReadableFileDescriptor, WritableFileDescriptor {
}
public protocol Connection : ReadableFileDescriptor, WritableFileDescriptor {}
68 changes: 34 additions & 34 deletions Sources/FDSet.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,20 +6,20 @@ import Darwin


func fdZero(_ set: inout fd_set) {
#if os(Linux)
set.__fds_bits = (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
#else
set.fds_bits = (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
#endif
#if os(Linux)
set.__fds_bits = (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
#else
set.fds_bits = (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
#endif
}


func fdSet(_ descriptor: FileNumber, _ set: inout fd_set) {
#if os(Linux)
let intOffset = Int(descriptor / 16)
let bitOffset = Int(descriptor % 16)
let mask = 1 << bitOffset
switch intOffset {
#if os(Linux)
let intOffset = Int(descriptor / 16)
let bitOffset = Int(descriptor % 16)
let mask = 1 << bitOffset
switch intOffset {
case 0: set.__fds_bits.0 = set.__fds_bits.0 | mask
case 1: set.__fds_bits.1 = set.__fds_bits.1 | mask
case 2: set.__fds_bits.2 = set.__fds_bits.2 | mask
Expand All @@ -37,13 +37,13 @@ func fdSet(_ descriptor: FileNumber, _ set: inout fd_set) {
case 14: set.__fds_bits.14 = set.__fds_bits.14 | mask
case 15: set.__fds_bits.15 = set.__fds_bits.15 | mask
default: break
}
#else
let intOffset = Int32(descriptor / 16)
let bitOffset = Int32(descriptor % 16)
let mask: Int32 = 1 << bitOffset

switch intOffset {
}
#else
let intOffset = Int32(descriptor / 16)
let bitOffset = Int32(descriptor % 16)
let mask: Int32 = 1 << bitOffset
switch intOffset {
case 0: set.fds_bits.0 = set.fds_bits.0 | mask
case 1: set.fds_bits.1 = set.fds_bits.1 | mask
case 2: set.fds_bits.2 = set.fds_bits.2 | mask
Expand All @@ -61,18 +61,18 @@ func fdSet(_ descriptor: FileNumber, _ set: inout fd_set) {
case 14: set.fds_bits.14 = set.fds_bits.14 | mask
case 15: set.fds_bits.15 = set.fds_bits.15 | mask
default: break
}
#endif
}
#endif
}


func fdIsSet(_ descriptor: FileNumber, _ set: inout fd_set) -> Bool {
#if os(Linux)
let intOffset = Int(descriptor / 32)
let bitOffset = Int(descriptor % 32)
let mask = Int(1 << bitOffset)

switch intOffset {
#if os(Linux)
let intOffset = Int(descriptor / 32)
let bitOffset = Int(descriptor % 32)
let mask = Int(1 << bitOffset)
switch intOffset {
case 0: return set.__fds_bits.0 & mask != 0
case 1: return set.__fds_bits.1 & mask != 0
case 2: return set.__fds_bits.2 & mask != 0
Expand All @@ -90,13 +90,13 @@ func fdIsSet(_ descriptor: FileNumber, _ set: inout fd_set) -> Bool {
case 14: return set.__fds_bits.14 & mask != 0
case 15: return set.__fds_bits.15 & mask != 0
default: return false
}
#else
let intOffset = Int32(descriptor / 32)
let bitOffset = Int32(descriptor % 32)
let mask = Int32(1 << bitOffset)

switch intOffset {
}
#else
let intOffset = Int32(descriptor / 32)
let bitOffset = Int32(descriptor % 32)
let mask = Int32(1 << bitOffset)
switch intOffset {
case 0: return set.fds_bits.0 & mask != 0
case 1: return set.fds_bits.1 & mask != 0
case 2: return set.fds_bits.2 & mask != 0
Expand Down Expand Up @@ -130,6 +130,6 @@ func fdIsSet(_ descriptor: FileNumber, _ set: inout fd_set) -> Bool {
case 30: return set.fds_bits.30 & mask != 0
case 31: return set.fds_bits.31 & mask != 0
default: return false
}
#endif
}
#endif
}
50 changes: 34 additions & 16 deletions Sources/FileDescriptor.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,32 +7,50 @@ private let system_close = Darwin.close
#endif


public typealias Byte = Int8
public typealias Byte = UInt8
public typealias FileNumber = Int32


public protocol FileDescriptor {
var fileNumber: FileNumber { get }
var fileNumber: FileNumber { get }
}


struct FileDescriptorError : Error {
enum ErrorKind: String {
case readError, writeError, selectError, pipeError, closeError, unknown
}

let kind: ErrorKind
let message: String?

var localizedDescription: String {
"FileDescriptorError of kind \(kind.rawValue)\(message != nil ? "\nmessage: \(message!)" : "")"
}

init(kind: ErrorKind, message: String? = nil) {
self.kind = kind
self.message = message
}

init(kind: ErrorKind, errno: Int32) {
let message = String(utf8String: strerror(errno))
self.init(kind: kind, message: message)
}
}


extension FileDescriptor {
/// Close deletes the file descriptor from the per-process object reference table
public func close() throws {
if system_close(fileNumber) == -1 {
throw FileDescriptorError()
/// Close deletes the file descriptor from the per-process object reference table
public func close() throws {
if system_close(fileNumber) == -1 {
throw FileDescriptorError(kind: .closeError, errno: errno)
}
}
}

public var isClosed: Bool {
if fcntl(fileNumber, F_GETFL) == -1 {
return errno == EBADF

public var isClosed: Bool {
if fcntl(fileNumber, F_GETFL) == -1 {
return errno == EBADF
}

return false
}

return false
}
}
4 changes: 3 additions & 1 deletion Sources/Listener.swift
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
public protocol Listener : FileDescriptor {
func accept() throws -> Connection
associatedtype AnyConnection

func accept() throws -> AnyConnection
}
46 changes: 23 additions & 23 deletions Sources/Pipe.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,35 +8,35 @@ private let system_pipe = Darwin.pipe


class PipeReadFileDescriptor : ReadableFileDescriptor {
let fileNumber: FileNumber

init(fileNumber: FileNumber) {
self.fileNumber = fileNumber
}

deinit {
let _ = try? close()
}
let fileNumber: FileNumber
init(fileNumber: FileNumber) {
self.fileNumber = fileNumber
}
deinit {
let _ = try? close()
}
}


class PipeWriteFileDescriptor : WritableFileDescriptor {
let fileNumber: FileNumber

init(fileNumber: FileNumber) {
self.fileNumber = fileNumber
}

deinit {
let _ = try? close()
}
let fileNumber: FileNumber
init(fileNumber: FileNumber) {
self.fileNumber = fileNumber
}
deinit {
let _ = try? close()
}
}


public func pipe() throws -> (reader: ReadableFileDescriptor, writer: WritableFileDescriptor) {
var fileNumbers: [FileNumber] = [0, 0]
if system_pipe(&fileNumbers) == -1 {
throw FileDescriptorError()
}
return (PipeReadFileDescriptor(fileNumber: fileNumbers[0]), PipeWriteFileDescriptor(fileNumber: fileNumbers[1]))
var fileNumbers: [FileNumber] = [0, 0]
if system_pipe(&fileNumbers) == -1 {
throw FileDescriptorError(kind: .pipeError, errno: errno)
}
return (PipeReadFileDescriptor(fileNumber: fileNumbers[0]), PipeWriteFileDescriptor(fileNumber: fileNumbers[1]))
}
57 changes: 39 additions & 18 deletions Sources/ReadableFileDescriptor.swift
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import Foundation
#if os(Linux)
import Glibc
private let system_read = Glibc.read
Expand All @@ -6,25 +7,45 @@ import Darwin
private let system_read = Darwin.read
#endif


public protocol ReadableFileDescriptor : FileDescriptor {
}

public protocol ReadableFileDescriptor : FileDescriptor {}

extension ReadableFileDescriptor {
/// Read attempts to read the given size from the file descriptor
public func read(_ bufferSize: Int) throws -> [Byte] {
let buffer = UnsafeMutableRawPointer(malloc(bufferSize))
defer { free(buffer) }
let size = system_read(fileNumber, buffer!, bufferSize)

if size > 0 {
let readSize = min(size, bufferSize)
var bytes = [Byte](repeating: 0, count: readSize)
memcpy(&bytes, buffer!, readSize)
return bytes
/// Read attempts to read the given size from the file descriptor
public func read(_ bufferSize: Int) throws -> [Byte] {
let buffer = UnsafeMutableRawPointer(malloc(bufferSize))
defer { free(buffer) }
let size = system_read(fileNumber, buffer!, bufferSize)

guard size != -1 else {
throw FileDescriptorError(kind: .readError, errno: errno)
}

let readSize = min(size, bufferSize)
var bytes = [Byte](repeating: 0, count: readSize)
memcpy(&bytes, buffer!, readSize)
return bytes
}

/// Read attempts to read the given size from the file descriptor
public func read(_ bufferSize: Int) throws -> Data {
let bytes: [Byte] = try read(bufferSize)

return Data(bytes: bytes, count: bytes.count)
}

public func readAll() throws -> Data {
var result = Data()
var data = CChar()
var data_read: size_t

while (((data_read = recv(fileNumber, &data, 1, 0)), data_read > 0).1 && !Character(UnicodeScalar(UInt8(bitPattern: data))).isNewline) {
result.append(contentsOf: [data].map(UInt8.init))
}

guard data_read != -1 else {
throw FileDescriptorError(kind: .unknown, errno: errno)
}

return result
}

throw FileDescriptorError()
}
}
10 changes: 5 additions & 5 deletions Sources/TCPConnection.swift
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
public class TCPConnection : FileDescriptor, Connection {
public let fileNumber: FileNumber

public init(fileNumber: FileNumber) {
self.fileNumber = fileNumber
}
public let fileNumber: FileNumber
public init(fileNumber: FileNumber) {
self.fileNumber = fileNumber
}
}
Loading