Created
June 29, 2016 18:57
-
-
Save loganwright/23430e65e17ca8f7ed8a0e380ecb188e to your computer and use it in GitHub Desktop.
Foundation Server - [WIP]
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// http://stackoverflow.com/a/33729691/2611971 | |
public class FoundationServer { | |
public static func listen(port: Int) { | |
let sock_fd = socket(AF_INET, SOCK_STREAM, 0); | |
if sock_fd == -1 { | |
perror("Failure: creating socket") | |
exit(EXIT_FAILURE) | |
} | |
var sock_opt_on = Int32(1) | |
setsockopt(sock_fd, SOL_SOCKET, SO_REUSEADDR, &sock_opt_on, socklen_t(sizeofValue(sock_opt_on))) | |
var server_addr = sockaddr_in() | |
let server_addr_size = socklen_t(sizeofValue(server_addr)) | |
server_addr.sin_len = UInt8(server_addr_size) | |
server_addr.sin_family = sa_family_t(AF_INET) // chooses IPv4 | |
server_addr.sin_port = UInt16(port).bigEndian // chooses the port | |
let bind_server = withUnsafePointer(&server_addr) { | |
bind(sock_fd, UnsafePointer($0), server_addr_size) | |
} | |
if bind_server == -1 { | |
perror("Failure: binding port") | |
exit(EXIT_FAILURE) | |
} | |
if Foundation.listen(sock_fd, 5) == -1 { | |
exit(EXIT_FAILURE) | |
} | |
var client_addr = sockaddr_storage() | |
var client_addr_len = socklen_t(sizeofValue(client_addr)) | |
let client_fd = withUnsafeMutablePointer(&client_addr) { | |
accept(sock_fd, UnsafeMutablePointer($0), &client_addr_len) | |
} | |
if client_fd == -1 { | |
perror("Failure: accepting connection") | |
exit(EXIT_FAILURE); | |
} | |
let inputStream = NSInputStream() | |
let fileDescriptor = NSNumber(value: client_fd) | |
inputStream.setProperty(fileDescriptor, forKey: (kCFStreamPropertySocketNativeHandle as NSString) as String) | |
inputStream.open() | |
var buff_rcvd = Bytes(repeating: 0, count: 1024) | |
let bytesRead = read(client_fd, &buff_rcvd, 1024) | |
inputStream.read(&buff_rcvd, maxLength: 1024) | |
let str = buff_rcvd.prefix(bytesRead).string | |
print("Read: \(str)") | |
// var buff_rcvd = Bytes(repeating: 0, count: 1024) | |
// let bytesRead = read(client_fd, &buff_rcvd, 1024) | |
// let str = buff_rcvd.prefix(bytesRead).string | |
// print("Read: \(str)") | |
// CFSocketCreate | |
// print(NSString(format:"Received: *%c*",buff_rcvd)) | |
// writing one chat at a time | |
// var buff_send: CChar = 65 // character "A" defined as CChar | |
// write(client_fd, &buff_send, 1) | |
// print(NSString(format:"Sent: *%c*",buff_send)) | |
print("") | |
} | |
} | |
public final class FoundationServerStream: ServerStream { | |
public let host: String | |
public let port: Int | |
public let securityLayer: SecurityLayer | |
public init(host: String, port: Int, securityLayer: SecurityLayer) throws { | |
self.host = host | |
self.port = port | |
self.securityLayer = securityLayer | |
} | |
public func accept() throws -> Stream { | |
fatalError() | |
} | |
} | |
public final class RawStream: Stream { | |
public let id: Int32 | |
public var closed: Bool = false | |
public init(_ id: Int32) { | |
self.id = id | |
} | |
public func setTimeout(_ timeout: Double) throws { | |
// unsupported currently | |
} | |
public func close() throws { | |
closed = true | |
// TODO: | |
} | |
public func send(_ bytes: Bytes) throws { | |
guard !bytes.isEmpty else { return } | |
var buffer = bytes | |
let written = write(id, &buffer, buffer.count) | |
guard written == bytes.count else { | |
throw FoundationStream.Error.unableToCompleteWriteOperation | |
} | |
} | |
public func flush() throws { | |
// unsupported | |
} | |
public func receive(max: Int) throws -> Bytes { | |
var buffer = Bytes(repeating: 0, count: max) | |
let bytesRead = read(id, &buffer, max) | |
return buffer.prefix(bytesRead).array | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment