THRIFT-5125: Swift server does not work using present code
Client: Swift
Patch: Jano Svitok

This closes #2038
diff --git a/lib/swift/Sources/TSocketServer.swift b/lib/swift/Sources/TSocketServer.swift
index 5d0dd49..d70020e 100644
--- a/lib/swift/Sources/TSocketServer.swift
+++ b/lib/swift/Sources/TSocketServer.swift
@@ -31,21 +31,17 @@
 public let TSocketServerProcessorKey = "TSocketServerProcessor"
 public let TSocketServerTransportKey = "TSocketServerTransport"
 
-class TSocketServer<InProtocol: TProtocol, OutProtocol: TProtocol, Processor: TProcessor, Service> {
+open class TSocketServer<InProtocol: TProtocol, OutProtocol: TProtocol, Processor: TProcessor> {
   var socketFileHandle: FileHandle
   var processingQueue =  DispatchQueue(label: "TSocketServer.processing",
                                        qos: .background,
                                        attributes: .concurrent)
-  var serviceHandler: Service
   let processor: Processor
 
   public init(port: Int,
-              service: Service,
               inProtocol: InProtocol.Type,
               outProtocol: OutProtocol.Type,
               processor: Processor) throws {
-    // set service handler
-    self.serviceHandler = service
     self.processor = processor
 
     // create a socket
@@ -61,16 +57,16 @@
       fd = CFSocketGetNative(sock)
       var yes = 1
       setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &yes, UInt32(MemoryLayout<Int>.size))
-
+      let inPort = in_port_t(UInt16(truncatingIfNeeded: port).bigEndian)
       #if os(Linux)
         var addr = sockaddr_in(sin_family: sa_family_t(AF_INET),
-                               sin_port: in_port_t(port.bigEndian),
+                               sin_port: inPort,
                                sin_addr: in_addr(s_addr: in_addr_t(0)),
                                sin_zero: (0, 0, 0, 0, 0, 0, 0, 0))
       #else
         var addr = sockaddr_in(sin_len: UInt8(MemoryLayout<sockaddr_in>.size),
                                sin_family: sa_family_t(AF_INET),
-                               sin_port: in_port_t(port.bigEndian),
+                               sin_port: inPort,
                                sin_addr: in_addr(s_addr: in_addr_t(0)),
                                sin_zero: (0, 0, 0, 0, 0, 0, 0, 0))
       #endif
@@ -82,7 +78,7 @@
       let address = Data(bytes: ptr, count: MemoryLayout<sockaddr_in>.size)
 
       let cfaddr = address.withUnsafeBytes {
-        CFDataCreateWithBytesNoCopy(kCFAllocatorDefault, $0.bindMemory(to: UInt8.self).baseAddress!, address.count, nil)
+        CFDataCreateWithBytesNoCopy(kCFAllocatorDefault, $0.bindMemory(to: UInt8.self).baseAddress!, address.count, kCFAllocatorNull)
       }
       if CFSocketSetAddress(sock, cfaddr) != CFSocketError.success { //kCFSocketSuccess {
         CFSocketInvalidate(sock)
@@ -106,7 +102,8 @@
                                                object: nil, queue: nil) {
                                                 [weak self] notification in
                                                 guard let strongSelf = self else { return }
-                                                strongSelf.connectionAccepted(strongSelf.socketFileHandle)
+                                                guard let clientSocket = notification.userInfo?[NSFileHandleNotificationFileHandleItem] as? FileHandle else { return }
+                                                strongSelf.connectionAccepted(clientSocket)
     }
 
     // tell socket to listen
@@ -119,22 +116,29 @@
     NotificationCenter.default.removeObserver(self)
   }
 
-  func connectionAccepted(_ socket: FileHandle) {
+  func connectionAccepted(_ clientSocket: FileHandle) {
     // Now that we have a client connected, handle the request on queue
     processingQueue.async {
-      self.handleClientConnection(socket)
+      self.handleClientConnection(clientSocket)
     }
+
+    // continue accepting connections
+    socketFileHandle.acceptConnectionInBackgroundAndNotify()
+  }
+
+  open func createTransport(fileHandle: FileHandle) -> TTransport {
+    return TFileHandleTransport(fileHandle: fileHandle)
   }
 
   func handleClientConnection(_ clientSocket: FileHandle) {
-
-    let transport = TFileHandleTransport(fileHandle: clientSocket)
-
+    let transport = createTransport(fileHandle: clientSocket)
     let inProtocol = InProtocol(on: transport)
     let outProtocol = OutProtocol(on: transport)
 
     do {
-      try processor.process(on: inProtocol, outProtocol: outProtocol)
+      while true {
+        try processor.process(on: inProtocol, outProtocol: outProtocol)
+      }
     } catch let error {
       print("Error processign request: \(error)")
     }
@@ -147,3 +151,9 @@
     }
   }
 }
+
+public class TFramedSocketServer<InProtocol: TProtocol, OutProtocol: TProtocol, Processor: TProcessor>: TSocketServer<InProtocol, OutProtocol, Processor> {
+  open override func createTransport(fileHandle: FileHandle) -> TTransport {
+    return TFramedTransport(transport: super.createTransport(fileHandle: fileHandle))
+  }
+}
diff --git a/lib/swift/Tests/ThriftTests/TSocketServerTests.swift b/lib/swift/Tests/ThriftTests/TSocketServerTests.swift
new file mode 100644
index 0000000..a00ebbc
--- /dev/null
+++ b/lib/swift/Tests/ThriftTests/TSocketServerTests.swift
@@ -0,0 +1,55 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+*   http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*/
+
+import XCTest
+import Foundation
+@testable import Thrift
+
+private protocol CalculatorService { }
+
+private class Calculator: CalculatorService { }
+
+private class CalculatorProcessor: TProcessor {
+  private let service: CalculatorService
+
+  init(service: CalculatorService) {
+    self.service = service
+  }
+
+  var processCalled = false
+  func process(on inProtocol: TProtocol, outProtocol: TProtocol) throws {
+    processCalled = true
+  }
+}
+
+class TSocketServerTests: XCTestCase {
+  func testInit() throws {
+    let service: CalculatorService = Calculator()
+    let processor: CalculatorProcessor = CalculatorProcessor(service: service)
+    let _: TSocketServer<TBinaryProtocol, TBinaryProtocol, CalculatorProcessor> = 
+      try TSocketServer(port: 9090, inProtocol: TBinaryProtocol.self, outProtocol: TBinaryProtocol.self, processor: processor)
+  }
+
+  static var allTests : [(String, (TSocketServerTests) -> () throws -> Void)] {
+    return [
+      ("testInit", testInit),
+    ]
+  }
+
+}