Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

IPC sockets #3

Open
wants to merge 13 commits into
base: master
Choose a base branch
from
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