import Foundation
signal(SIGPIPE,SIG_IGN)
let s = Server();
s.start()
var bval:UnsafeMutablePointer<UnsafeMutableRawPointer?>? = nil
var ende:Bool? = nil
var semacnt:Int? = nil
var accarrFD:[Int32]? = nil
class Server {
init() {
if (CommandLine.argc > 1) {
tmpSvcPort = Int(CommandLine.arguments[1]) ?? 0
if (tmpSvcPort > 0){ servicePort = String(tmpSvcPort) }
}
semacnt! = 0
ende! = false
accarrFD! = Array(repeating:Int32(0),count:0)
bval = UnsafeMutablePointer.allocate(capacity:1)
bval!.pointee = UnsafeMutableRawPointer.allocate(byteCount:1,alignment:1)
print("assigning")
bval!.pointee!.storeBytes(of:0,as: UInt8.self)
print("assigned")
}
deinit {
bval!.pointee!.deallocate()
bval!.deallocate()
}
var tmpSvcPort: Int = 0
var servicePort = "1234"
class Worker:Thread{
override init(){
super.init()
semacnt! += 1
}
deinit {
semacnt! -= 1
}
override func main(){
let MTU = 65536
let buffer = UnsafeMutablePointer<CChar>.allocate(capacity:MTU)
let True = UnsafeMutablePointer<UInt8>.allocate(capacity:1)
let False = UnsafeMutablePointer<UInt8>.allocate(capacity:1)
True.pointee = 1
False.pointee = 0
defer {
True.deallocate()
False.deallocate()
buffer.deallocate()
}
while(true){
repeat {
usleep(100);
OSMemoryBarrier()
}
/***
* interrestingky CAS doesn't work because of
* some weird Apple memory scheme
*/
while (bval!.pointee!.load(as:UInt8.self) == 1)
OSMemoryBarrier()
bval!.pointee!.storeBytes(of:1,as: UInt8.self)
print("acquired")
var oneFD = Array(repeating:Int32(0),count:0)
if (!accarrFD!.isEmpty){
/// collect rest of fds
oneFD.append(accarrFD![accarrFD!.count-1])
accarrFD!.remove(at:accarrFD!.count-1)
}
OSMemoryBarrier()
bval!.pointee!.storeBytes(of:0,as: UInt8.self)
print("releazed\n")
let toproc = oneFD
for fd in toproc{
let sockKqueue = kqueue()
if sockKqueue == -1 {
print("Error creating kqueue")
}
defer {close(fd);close(sockKqueue)}
var sockKevent = kevent(
ident: UInt(fd),
filter: Int16(EVFILT_READ),
flags: UInt16(EV_ADD | EV_ENABLE),
fflags: 0,
data: 0,
udata: nil)
kevent(sockKqueue, &sockKevent, 1, nil, 0, nil)
var event = kevent()
let status = kevent(sockKqueue, nil, 0, &event, 1, nil)
if status == 0 {
print("Timeout")
continue
} else if status > 0 {
if (event.flags & UInt16(EV_EOF)) == EV_EOF {
print("The socket (\(fd)) has been closed.")
continue
}
print("File descriptor: \(fd) - has \(event.data) characters for reading")
}
else {
print("Error reading kevent")
continue
}
let readResult = read(fd, buffer, MTU)
if (readResult == 0) {
continue; // end of file
} else if (readResult == -1) {
print("Error reading form client(\(fd)) - \(errno)")
continue; // error
} else {
let strResult =
String(cString: buffer)
let cset = CharacterSet(charactersIn: " \r\n")
let numbers = strResult.components(separatedBy: cset)
var sum = 0
if numbers.count > 1 {
if numbers[0].lowercased() == "quit" {
ende! = true
continue
} else {
let num1 = Int(numbers[0]) ?? 0
let num2 = Int(numbers[1]) ?? 0
sum = num1 + num2
}
}
print("Received form client(\(fd)): \(strResult)")
let out = String(format:"suma %d\n",sum)
let _ = out.withCString {
/**let flags = fcntl(fd,F_GETFL)
let _ = fcntl(fd,F_SETFL,flags | O_NONBLOCK)
*/
var sockKevent = kevent(
ident: UInt(fd),
filter: Int16(EVFILT_WRITE),
flags: UInt16(EV_ADD | EV_ENABLE),
fflags: 0,
data: 0,
udata: nil)
kevent(sockKqueue, &sockKevent, 1, nil, 0, nil)
var event = kevent()
let status = kevent(sockKqueue, nil, 0, &event, 1, nil)
if status == 0 {
print("Timeout")
} else if status > 0 {
if (event.flags & UInt16(EV_EOF)) == EV_EOF {
print("The socket (\(fd)) has been closed.")
}
print("File descriptor: \(fd) - can write")
write(fd, $0, out.count)
}
else {
print("Error reading kevent")
}
}
}
}
usleep(100)
let True = UnsafeMutablePointer<UInt8>.allocate(capacity:1)
let False = UnsafeMutablePointer<UInt8>.allocate(capacity:1)
True.pointee = 1
False.pointee = 0
defer {
True.deallocate()
False.deallocate()
}
while (!ende!) {
var addr = sockaddr()
var addr_len :socklen_t = 0
while (!ende!) {
print("About to accept")
let accFD = accept(socketFD, &addr, &addr_len)
if (accFD > 0){
print("Accepted new client with file descriptor: \(accFD)")
repeat {
usleep(100);
OSMemoryBarrier()
}
while (bval!.pointee!.load(as:UInt8.self) == 1)
OSMemoryBarrier()
bval!.pointee!.storeBytes(of:1,as:UInt8.self)
accarrFD!.append(accFD)
OSMemoryBarrier()
bval!.pointee!.storeBytes(of:0,as:UInt8.self)
if (semacnt! < 5) {
let handle = Worker();
handle.start()
}
} else {
print("Error accepting connection")
usleep(100)
}
OSMemoryBarrier() /// barrier needed here
}
}
exit(EXIT_SUCCESS)