Browse Source

Heavy revision of prototype generated API, all in the Echo Mac app.

Tim Burks 9 years ago
parent
commit
70805aa9fd

+ 5 - 5
Examples/Echo/Swift/Echo.xcodeproj/project.pbxproj

@@ -14,7 +14,7 @@
 		D35C9FAE1D74B079000443CD /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = D35C9FAD1D74B079000443CD /* Assets.xcassets */; };
 		D35C9FB11D74B079000443CD /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = D35C9FAF1D74B079000443CD /* MainMenu.xib */; };
 		D35C9FC81D74B0C1000443CD /* EchoViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D35C9FC71D74B0C1000443CD /* EchoViewController.swift */; };
-		D38F9C401E1F0D2C003DECA4 /* EchoServer.swift in Sources */ = {isa = PBXBuildFile; fileRef = D38F9C3F1E1F0D2C003DECA4 /* EchoServer.swift */; };
+		D38F9C401E1F0D2C003DECA4 /* EchoHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = D38F9C3F1E1F0D2C003DECA4 /* EchoHandler.swift */; };
 		D3971E211D89132E001A0B3F /* ssl.key in Resources */ = {isa = PBXBuildFile; fileRef = D3971E201D89132E001A0B3F /* ssl.key */; };
 		D3BFE28C1D87A45D00A648D8 /* ssl.crt in Resources */ = {isa = PBXBuildFile; fileRef = D3BFE28B1D87A45D00A648D8 /* ssl.crt */; };
 		D3D2EA4C1D75FB7F002EF89C /* gRPC.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D3D2EA3E1D75FB56002EF89C /* gRPC.framework */; };
@@ -74,7 +74,7 @@
 
 /* Begin PBXFileReference section */
 		D30DACEF1DB6FC2D00886B20 /* echo.client.pb.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = echo.client.pb.swift; sourceTree = "<group>"; };
-		D324A6011D81CF8F00421B59 /* echo.server.pb.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = echo.server.pb.swift; sourceTree = "<group>"; };
+		D324A6011D81CF8F00421B59 /* echo.server.pb.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; lineEnding = 0; path = echo.server.pb.swift; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.swift; };
 		D359A6261DBAD11C00FE6282 /* echo.pb.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = echo.pb.swift; path = Protobuf/echo.pb.swift; sourceTree = "<group>"; };
 		D35C9FA81D74B079000443CD /* Echo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Echo.app; sourceTree = BUILT_PRODUCTS_DIR; };
 		D35C9FAB1D74B079000443CD /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
@@ -83,7 +83,7 @@
 		D35C9FB21D74B079000443CD /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
 		D35C9FC71D74B0C1000443CD /* EchoViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EchoViewController.swift; sourceTree = "<group>"; };
 		D36C3EF81E145A2200BF4EB3 /* SwiftProtobufRuntime.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = SwiftProtobufRuntime.xcodeproj; path = "../../../third_party/swift-protobuf/SwiftProtobufRuntime.xcodeproj"; sourceTree = "<group>"; };
-		D38F9C3F1E1F0D2C003DECA4 /* EchoServer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EchoServer.swift; sourceTree = "<group>"; };
+		D38F9C3F1E1F0D2C003DECA4 /* EchoHandler.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; lineEnding = 0; path = EchoHandler.swift; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.swift; };
 		D3971E201D89132E001A0B3F /* ssl.key */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = ssl.key; sourceTree = "<group>"; };
 		D3BFE28B1D87A45D00A648D8 /* ssl.crt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = ssl.crt; sourceTree = "<group>"; };
 		D3D2EA391D75FB56002EF89C /* gRPC.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = gRPC.xcodeproj; path = ../../../gRPC.xcodeproj; sourceTree = "<group>"; };
@@ -135,7 +135,7 @@
 				D35C9FAD1D74B079000443CD /* Assets.xcassets */,
 				D30DACEF1DB6FC2D00886B20 /* echo.client.pb.swift */,
 				D324A6011D81CF8F00421B59 /* echo.server.pb.swift */,
-				D38F9C3F1E1F0D2C003DECA4 /* EchoServer.swift */,
+				D38F9C3F1E1F0D2C003DECA4 /* EchoHandler.swift */,
 				D35C9FC71D74B0C1000443CD /* EchoViewController.swift */,
 				D35C9FB21D74B079000443CD /* Info.plist */,
 				D35C9FAF1D74B079000443CD /* MainMenu.xib */,
@@ -291,7 +291,7 @@
 				D30DACF01DB6FC2D00886B20 /* echo.client.pb.swift in Sources */,
 				D324A6021D81CF8F00421B59 /* echo.server.pb.swift in Sources */,
 				D35C9FC81D74B0C1000443CD /* EchoViewController.swift in Sources */,
-				D38F9C401E1F0D2C003DECA4 /* EchoServer.swift in Sources */,
+				D38F9C401E1F0D2C003DECA4 /* EchoHandler.swift in Sources */,
 				D359A6271DBAD11C00FE6282 /* echo.pb.swift in Sources */,
 				D35C9FAC1D74B079000443CD /* AppDelegate.swift in Sources */,
 			);

+ 17 - 6
Examples/Echo/Swift/Echo/AppDelegate.swift

@@ -37,14 +37,25 @@ class AppDelegate: NSObject, NSApplicationDelegate {
 
   @IBOutlet weak var window: NSWindow!
 
-  var insecureEchoServer: EchoServer!
-  var secureEchoServer: EchoServer!
+  var echoHandler : EchoHandler!
+  var insecureServer: Echo_EchoServer!
+  var secureServer: Echo_EchoServer!
 
   func applicationDidFinishLaunching(_ aNotification: Notification) {
-    insecureEchoServer = EchoServer(address:"localhost:8081", secure:false)
-    insecureEchoServer.start()
 
-    secureEchoServer = EchoServer(address:"localhost:8443", secure:true)
-    secureEchoServer.start()
+    // instantiate our custom-written application handler
+    echoHandler = EchoHandler()
+
+    // create and start a server for handling insecure requests
+    insecureServer = Echo_EchoServer(address:"localhost:8081",
+                                     handler:echoHandler,
+                                     secure:false)
+    insecureServer.start()
+
+    // create and start a server for handling secure requests
+    secureServer = Echo_EchoServer(address:"localhost:8443",
+                                   handler:echoHandler,
+                                   secure:true)
+    secureServer.start()
   }
 }

+ 1 - 1
Examples/Echo/Swift/Echo/Base.lproj/MainMenu.xib

@@ -144,7 +144,7 @@
                     <textField verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="jnU-RF-9F0">
                         <rect key="frame" x="20" y="59" width="305" height="22"/>
                         <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
-                        <textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" editable="YES" sendsActionOnEndEditing="YES" state="on" borderStyle="bezel" title="localhost:8080" placeholderString="Server Address" drawsBackground="YES" id="mDa-qc-62R">
+                        <textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" editable="YES" sendsActionOnEndEditing="YES" state="on" borderStyle="bezel" title="localhost:8081" placeholderString="Server Address" drawsBackground="YES" id="mDa-qc-62R">
                             <font key="font" metaFont="system"/>
                             <color key="textColor" name="textColor" catalog="System" colorSpace="catalog"/>
                             <color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>

+ 31 - 34
Examples/Echo/Swift/Echo/EchoServer.swift → Examples/Echo/Swift/Echo/EchoHandler.swift

@@ -33,58 +33,55 @@
 
 import Foundation
 
-// The following code is for developer/users to edit.
-// Everything above these lines is intended to be preexisting or generated.
-
-class MyEchoServer : CustomEchoServer {
+class EchoHandler : Echo_EchoHandler {
 
+  // Get returns requests as they were received.
   func Get(request : Echo_EchoRequest) throws -> Echo_EchoResponse {
     return Echo_EchoResponse(text:"Swift echo get: " + request.text)
   }
 
-  func Expand(request : Echo_EchoRequest, session : EchoExpandSession) throws -> Void {
+  // Expand splits a request into words and returns each word in a separate message.
+  func Expand(request : Echo_EchoRequest, session : Echo_EchoExpandSession) throws -> Void {
     let parts = request.text.components(separatedBy: " ")
     var i = 0
     for part in parts {
-      try! session.Send(Echo_EchoResponse(text:"Swift echo expand (\(i)): \(part)"))
+      try session.Send(Echo_EchoResponse(text:"Swift echo expand (\(i)): \(part)"))
       i += 1
       sleep(1)
     }
   }
 
-  func Collect(session : EchoCollectSession) throws -> Void {
-    DispatchQueue.global().async {
-      var parts : [String] = []
-      while true {
-        do {
-          let request = try session.Recv()
-          parts.append(request.text)
-        } catch ServerError.endOfStream {
-          break
-        } catch (let error) {
-          print("\(error)")
-        }
+  // Collect collects a sequence of messages and returns them concatenated when the caller closes.
+  func Collect(session : Echo_EchoCollectSession) throws -> Void {
+    var parts : [String] = []
+    while true {
+      do {
+        let request = try session.Receive()
+        parts.append(request.text)
+      } catch Echo_EchoServerError.endOfStream {
+        break
+      } catch (let error) {
+        print("\(error)")
       }
-      let response = Echo_EchoResponse(text:"Swift echo collect: " + parts.joined(separator: " "))
-      try! session.SendAndClose(response)
     }
+    let response = Echo_EchoResponse(text:"Swift echo collect: " + parts.joined(separator: " "))
+    try session.SendAndClose(response)
   }
 
-  func Update(session : EchoUpdateSession) throws -> Void {
-    DispatchQueue.global().async {
-      var count = 0
-      while true {
-        do {
-          let request = try session.Recv()
-          count += 1
-          try session.Send(Echo_EchoResponse(text:"Swift echo update (\(count)): \(request.text)"))
-        } catch ServerError.endOfStream {
-          break
-        } catch (let error) {
-          print("\(error)")
-        }
+  // Update streams back messages as they are received in an input stream.
+  func Update(session : Echo_EchoUpdateSession) throws -> Void {
+    var count = 0
+    while true {
+      do {
+        let request = try session.Receive()
+        count += 1
+        try session.Send(Echo_EchoResponse(text:"Swift echo update (\(count)): \(request.text)"))
+      } catch Echo_EchoServerError.endOfStream {
+        break
+      } catch (let error) {
+        print("\(error)")
       }
-      session.Close()
     }
+    session.Close()
   }
 }

+ 10 - 9
Examples/Echo/Swift/Echo/EchoViewController.swift

@@ -42,11 +42,11 @@ class EchoViewController : NSViewController, NSTextFieldDelegate {
   @IBOutlet weak var callSelectButton: NSSegmentedControl!
   @IBOutlet weak var closeButton: NSButton!
 
-  private var service : EchoService?
+  private var service : Echo_EchoService?
 
-  private var expandCall: EchoExpandCall?
-  private var collectCall: EchoCollectCall?
-  private var updateCall: EchoUpdateCall?
+  private var expandCall: Echo_EchoExpandCall?
+  private var collectCall: Echo_EchoCollectCall?
+  private var updateCall: Echo_EchoUpdateCall?
 
   private var nowStreaming = false
 
@@ -119,12 +119,12 @@ class EchoViewController : NSViewController, NSTextFieldDelegate {
       return
     }
     if (TLSButton.intValue == 0) {
-      service = EchoService(address:address)
+      service = Echo_EchoService(address:address)
     } else {
       let certificateURL = Bundle.main.url(forResource: "ssl",
                                            withExtension: "crt")!
       let certificates = try! String(contentsOf: certificateURL)
-      service = EchoService(address:address, certificates:certificates, host:host)
+      service = Echo_EchoService(address:address, certificates:certificates, host:host)
     }
     if let service = service {
       service.channel.host = "example.com" // sample override
@@ -142,6 +142,7 @@ class EchoViewController : NSViewController, NSTextFieldDelegate {
       if let service = service {
         var requestMessage = Echo_EchoRequest()
         requestMessage.text = self.messageField.stringValue
+        self.displayMessageSent(requestMessage.text)
 
         // service.get() is a blocking call
         DispatchQueue.global().async {
@@ -204,7 +205,7 @@ class EchoViewController : NSViewController, NSTextFieldDelegate {
     DispatchQueue.global().async {
       var running = true
       while running {
-        let result = expandCall.Recv()
+        let result = expandCall.Receive()
         switch result {
         case .Response(let responseMessage):
           self.displayMessageReceived(responseMessage.text)
@@ -244,7 +245,7 @@ class EchoViewController : NSViewController, NSTextFieldDelegate {
     DispatchQueue.global().async {
       var running = true
       while running {
-        let result = updateCall.Recv()
+        let result = updateCall.Receive()
         switch result {
         case .Response(let responseMessage):
           self.displayMessageReceived(responseMessage.text)
@@ -268,7 +269,7 @@ class EchoViewController : NSViewController, NSTextFieldDelegate {
       self.closeButton.isEnabled = false
     }
     if let collectCall = collectCall {
-      let result = collectCall.CloseAndRecv()
+      let result = collectCall.CloseAndReceive()
       switch result {
       case .Response(let responseMessage):
         self.displayMessageReceived(responseMessage.text)

+ 17 - 17
Examples/Echo/Swift/Echo/echo.client.pb.swift

@@ -36,6 +36,7 @@
 import Foundation
 import gRPC
 
+// this is probably going to go.
 public enum EchoResult {
   case Response(r: Echo_EchoResponse)
   // these last two should be merged
@@ -46,7 +47,7 @@ public enum EchoResult {
 //
 // Unary GET
 //
-public class EchoGetCall {
+public class Echo_EchoGetCall {
   var call : Call
 
   fileprivate init(_ channel: Channel) {
@@ -77,7 +78,7 @@ public class EchoGetCall {
 //
 // Server-streaming EXPAND
 //
-public class EchoExpandCall {
+public class Echo_EchoExpandCall {
   var call : Call
 
   fileprivate init(_ channel: Channel) {
@@ -100,7 +101,7 @@ public class EchoExpandCall {
 
   // Call this to wait for a result.
   // BLOCKING
-  public func Recv() -> EchoResult {
+  public func Receive() -> EchoResult {
     let done = NSCondition()
     var result : EchoResult!
     try! call.receiveMessage() {(data) in
@@ -127,7 +128,7 @@ public class EchoExpandCall {
 //
 // Client-streaming COLLECT
 //
-public class EchoCollectCall {
+public class Echo_EchoCollectCall {
   var call : Call
 
   fileprivate init(_ channel: Channel) {
@@ -147,7 +148,7 @@ public class EchoCollectCall {
 
   // Call this to close the connection and wait for a response.
   // BLOCKING
-  public func CloseAndRecv() -> EchoResult {
+  public func CloseAndReceive() -> EchoResult {
     let done = NSCondition()
     var result : EchoResult!
 
@@ -204,7 +205,7 @@ public class EchoCollectCall {
 //
 // Bidirectional-streaming UPDATE
 //
-public class EchoUpdateCall {
+public class Echo_EchoUpdateCall {
   var call : Call
 
   fileprivate init(_ channel: Channel) {
@@ -229,7 +230,7 @@ public class EchoUpdateCall {
     }
   }
 
-  public func Recv() -> EchoResult {
+  public func Receive() -> EchoResult {
     let done = NSCondition()
     var result : EchoResult!
     try! self.receiveMessage() {responseMessage in
@@ -266,9 +267,8 @@ public class EchoUpdateCall {
   }
 }
 
-// The generated service adaptor
-// Call these methods to make API calls
-public class EchoService {
+// Call methods of this class to make API calls.
+public class Echo_EchoService {
   public var channel: Channel
 
   public init(address: String) {
@@ -281,7 +281,7 @@ public class EchoService {
 
   // Synchronous. Unary.
   public func get(_ requestMessage: Echo_EchoRequest) -> EchoResult {
-    let call = EchoGetCall(channel)
+    let call = Echo_EchoGetCall(channel)
     let done = NSCondition()
     var finalResult : EchoResult!
     call.perform(request:requestMessage) {(result) in
@@ -299,8 +299,8 @@ public class EchoService {
   // Asynchronous. Server-streaming.
   // Send the initial message.
   // Use methods on the returned object to get streamed responses.
-  public func expand(_ requestMessage: Echo_EchoRequest) -> EchoExpandCall {
-    let call = EchoExpandCall(channel)
+  public func expand(_ requestMessage: Echo_EchoRequest) -> Echo_EchoExpandCall {
+    let call = Echo_EchoExpandCall(channel)
     call.perform(request:requestMessage) {response in }
     return call
   }
@@ -308,8 +308,8 @@ public class EchoService {
   // Asynchronous. Client-streaming.
   // Use methods on the returned object to stream messages and
   // to close the connection and wait for a final response.
-  public func collect() -> EchoCollectCall {
-    let call = EchoCollectCall(channel)
+  public func collect() -> Echo_EchoCollectCall {
+    let call = Echo_EchoCollectCall(channel)
     try! call.start(metadata:Metadata(), completion:{})
     return call
   }
@@ -317,8 +317,8 @@ public class EchoService {
   // Asynchronous. Bidirectional-streaming.
   // Use methods on the returned object to stream messages,
   // to wait for replies, and to close the connection.
-  public func update() -> EchoUpdateCall {
-    let call = EchoUpdateCall(channel)
+  public func update() -> Echo_EchoUpdateCall {
+    let call = Echo_EchoUpdateCall(channel)
     try! call.start(metadata:Metadata(), completion:{})
     return call
   }

+ 105 - 124
Examples/Echo/Swift/Echo/echo.server.pb.swift

@@ -35,40 +35,38 @@
 
 import Foundation
 import gRPC
-import Darwin // for sleep()
 
-enum ServerError : Error {
+public enum Echo_EchoServerError : Error {
   case endOfStream
 }
 
-protocol CustomEchoServer {
+public protocol Echo_EchoHandler {
   func Get(request : Echo_EchoRequest) throws -> Echo_EchoResponse
-  func Collect(session : EchoCollectSession) throws -> Void
-  func Expand(request : Echo_EchoRequest, session : EchoExpandSession) throws -> Void
-  func Update(session : EchoUpdateSession) throws -> Void
+  func Collect(session : Echo_EchoCollectSession) throws -> Void
+  func Expand(request : Echo_EchoRequest, session : Echo_EchoExpandSession) throws -> Void
+  func Update(session : Echo_EchoUpdateSession) throws -> Void
 }
 
 // unary
-class EchoGetSession : Session {
-  var handler : Handler
-  var server : CustomEchoServer
+public class Echo_EchoGetSession {
+  var connection : gRPC.Handler
+  var handler : Echo_EchoHandler
 
-  init(handler:Handler, server: CustomEchoServer) {
+  fileprivate init(connection:gRPC.Handler, handler: Echo_EchoHandler) {
+    self.connection = connection
     self.handler = handler
-    self.server = server
   }
 
-  func run() {
+  fileprivate func run(queue:DispatchQueue) {
     do {
-      try handler.receiveMessage(initialMetadata:Metadata()) {(requestData) in
+      try connection.receiveMessage(initialMetadata:Metadata()) {(requestData) in
         if let requestData = requestData {
           let requestMessage = try! Echo_EchoRequest(protobuf:requestData)
-          let replyMessage = try! self.server.Get(request:requestMessage)
-          // calling stub
-          try self.handler.sendResponse(message:replyMessage.serializeProtobuf(),
-                                        statusCode: 0,
-                                        statusMessage: "OK",
-                                        trailingMetadata:Metadata())
+          let replyMessage = try! self.handler.Get(request:requestMessage)
+          try self.connection.sendResponse(message:replyMessage.serializeProtobuf(),
+                                           statusCode: 0,
+                                           statusMessage: "OK",
+                                           trailingMetadata:Metadata())
 
         }
       }
@@ -79,29 +77,33 @@ class EchoGetSession : Session {
 }
 
 // server streaming
-class EchoExpandSession : Session {
-  var handler : Handler
-  var server : CustomEchoServer
+public class Echo_EchoExpandSession {
+  var connection : gRPC.Handler
+  var handler : Echo_EchoHandler
 
-  init(handler:Handler, server: CustomEchoServer) {
+  fileprivate init(connection:gRPC.Handler, handler: Echo_EchoHandler) {
+    self.connection = connection
     self.handler = handler
-    self.server = server
   }
 
-  func Send(_ response: Echo_EchoResponse) throws {
-    try! handler.sendResponse(message:response.serializeProtobuf()) {}
+  public func Send(_ response: Echo_EchoResponse) throws {
+    try! connection.sendResponse(message:response.serializeProtobuf()) {}
   }
 
-  func run() {
+  fileprivate func run(queue:DispatchQueue) {
     do {
-      try self.handler.receiveMessage(initialMetadata:Metadata()) {(requestData) in
+      try self.connection.receiveMessage(initialMetadata:Metadata()) {(requestData) in
         if let requestData = requestData {
           let requestMessage = try! Echo_EchoRequest(protobuf:requestData)
-          try self.server.Expand(request:requestMessage, session: self)
-          try! self.handler.sendStatus(statusCode:0,
-                                       statusMessage:"OK",
-                                       trailingMetadata:Metadata(),
-                                       completion:{})
+          // to keep handlers from blocking the server thread,
+          // we dispatch them to another queue.
+          queue.async {
+            try! self.handler.Expand(request:requestMessage, session: self)
+            try! self.connection.sendStatus(statusCode:0,
+                                            statusMessage:"OK",
+                                            trailingMetadata:Metadata(),
+                                            completion:{})
+          }
         }
       }
     } catch (let callError) {
@@ -111,20 +113,20 @@ class EchoExpandSession : Session {
 }
 
 // client streaming
-class EchoCollectSession : Session {
-  var handler : Handler
-  var server : CustomEchoServer
+public class Echo_EchoCollectSession {
+  var connection : gRPC.Handler
+  var handler : Echo_EchoHandler
 
-  init(handler:Handler, server: CustomEchoServer) {
+  fileprivate init(connection:gRPC.Handler, handler: Echo_EchoHandler) {
+    self.connection = connection
     self.handler = handler
-    self.server = server
   }
 
-  func Recv() throws -> Echo_EchoRequest {
+  public func Receive() throws -> Echo_EchoRequest {
     print("collect awaiting message")
     let done = NSCondition()
     var requestMessage : Echo_EchoRequest?
-    try self.handler.receiveMessage() {(requestData) in
+    try self.connection.receiveMessage() {(requestData) in
       print("collect received message")
       if let requestData = requestData {
         requestMessage = try! Echo_EchoRequest(protobuf:requestData)
@@ -137,30 +139,25 @@ class EchoCollectSession : Session {
     done.wait()
     done.unlock()
     if requestMessage == nil {
-      throw ServerError.endOfStream
+      throw Echo_EchoServerError.endOfStream
     }
     return requestMessage!
   }
 
-  func SendAndClose(_ response: Echo_EchoResponse) throws {
-    try! self.handler.sendResponse(message:response.serializeProtobuf(),
-                                   statusCode: 0,
-                                   statusMessage: "OK",
-                                   trailingMetadata: Metadata())
+  public func SendAndClose(_ response: Echo_EchoResponse) throws {
+    try! self.connection.sendResponse(message:response.serializeProtobuf(),
+                                      statusCode: 0,
+                                      statusMessage: "OK",
+                                      trailingMetadata: Metadata())
   }
 
-  func sendMessage(message:Echo_EchoResponse) -> Void {
-    try! self.handler.sendResponse(message:message.serializeProtobuf(),
-                                   statusCode: 0,
-                                   statusMessage: "OK",
-                                   trailingMetadata: Metadata())
-  }
-
-  func run() {
+  fileprivate func run(queue:DispatchQueue) {
     do {
       print("EchoCollectSession run")
-      try self.handler.sendMetadata(initialMetadata:Metadata()) {
-        try self.server.Collect(session:self)
+      try self.connection.sendMetadata(initialMetadata:Metadata()) {
+        queue.async {
+          try! self.handler.Collect(session:self)
+        }
       }
     } catch (let callError) {
       print("grpc error: \(callError)")
@@ -169,20 +166,20 @@ class EchoCollectSession : Session {
 }
 
 // fully streaming
-class EchoUpdateSession : Session {
-  var handler : Handler
-  var server : CustomEchoServer
+public class Echo_EchoUpdateSession {
+  var connection : gRPC.Handler
+  var handler : Echo_EchoHandler
 
-  init(handler:Handler, server: CustomEchoServer) {
+  fileprivate init(connection:gRPC.Handler, handler: Echo_EchoHandler) {
+    self.connection = connection
     self.handler = handler
-    self.server = server
   }
 
-  func Recv() throws -> Echo_EchoRequest {
+  public func Receive() throws -> Echo_EchoRequest {
     print("update awaiting message")
     let done = NSCondition()
     var requestMessage : Echo_EchoRequest?
-    try self.handler.receiveMessage() {(requestData) in
+    try self.connection.receiveMessage() {(requestData) in
       print("update received message")
       if let requestData = requestData {
         requestMessage = try! Echo_EchoRequest(protobuf:requestData)
@@ -195,39 +192,35 @@ class EchoUpdateSession : Session {
     done.wait()
     done.unlock()
     if requestMessage == nil {
-      throw ServerError.endOfStream
+      throw Echo_EchoServerError.endOfStream
     }
     return requestMessage!
   }
 
-  func Send(_ response: Echo_EchoResponse) throws {
-    try handler.sendResponse(message:response.serializeProtobuf()) {}
+  public func Send(_ response: Echo_EchoResponse) throws {
+    try connection.sendResponse(message:response.serializeProtobuf()) {}
   }
 
-  func sendMessage(message:Echo_EchoResponse) -> Void {
-    try! handler.sendResponse(message:message.serializeProtobuf()) {}
-  }
-
-  func Close() {
+  public func Close() {
     let done = NSCondition()
-
-    try! self.handler.sendStatus(statusCode: 0,
-                                 statusMessage: "OK",
-                                 trailingMetadata: Metadata()) {
-                                  done.lock()
-                                  done.signal()
-                                  done.unlock()
+    try! self.connection.sendStatus(statusCode: 0,
+                                    statusMessage: "OK",
+                                    trailingMetadata: Metadata()) {
+                                      done.lock()
+                                      done.signal()
+                                      done.unlock()
     }
-
     done.lock()
     done.wait()
     done.unlock()
   }
 
-  func run() {
+  fileprivate func run(queue:DispatchQueue) {
     do {
-      try self.handler.sendMetadata(initialMetadata:Metadata()) {
-        try self.server.Update(session:self)
+      try self.connection.sendMetadata(initialMetadata:Metadata()) {
+        queue.async {
+          try! self.handler.Update(session:self)
+        }
       }
     } catch (let callError) {
       print("grpc error: \(callError)")
@@ -235,15 +228,20 @@ class EchoUpdateSession : Session {
   }
 }
 
-class EchoServer {
+//
+// main server for generated service
+//
+public class Echo_EchoServer {
   private var address: String
-  private var server: Server
-
-  public var myServer: MyEchoServer!
+  private var server: gRPC.Server
+  public var handler: Echo_EchoHandler!
 
-  init(address:String, secure:Bool) {
+  public init(address:String,
+              handler:Echo_EchoHandler,
+              secure:Bool) {
     gRPC.initialize()
     self.address = address
+    self.handler = handler
     if secure {
       let certificateURL = Bundle.main.url(forResource: "ssl", withExtension: "crt")!
 
@@ -254,45 +252,28 @@ class EchoServer {
     } else {
       self.server = gRPC.Server(address:address)
     }
-    self.myServer = MyEchoServer()
   }
 
-  func start() {
-    print("Server Starting")
-    print("GRPC version " + gRPC.version())
-
-    server.run {(handler) in
-
-      print("Server received request to " + handler.host
-        + " calling " + handler.method
-        + " from " + handler.caller)
-
-      // to keep handlers from blocking the server thread,
-      // we dispatch them to another queue.
-      DispatchQueue.global().async {
-        if (handler.method == "/echo.Echo/Get") {
-          handler.session = EchoGetSession(handler:handler,
-                                           server:self.myServer)
-          handler.session.run()
-        }
-
-        else if (handler.method == "/echo.Echo/Expand") {
-          handler.session = EchoExpandSession(handler:handler,
-                                              server:self.myServer)
-          handler.session.run()
-        }
-
-        else if (handler.method == "/echo.Echo/Collect") {
-          handler.session = EchoCollectSession(handler:handler,
-                                               server:self.myServer)
-          handler.session.run()
-        }
-
-        else if (handler.method == "/echo.Echo/Update") {
-          handler.session = EchoUpdateSession(handler:handler,
-                                              server:self.myServer)
-          handler.session.run()
-        }
+  public func start(queue:DispatchQueue = DispatchQueue.global()) {
+    guard let handler = self.handler else {
+      assert(false) // the server requires a handler
+    }
+    server.run {(connection) in
+      print("Server received request to " + connection.host
+        + " calling " + connection.method
+        + " from " + connection.caller)
+
+      switch connection.method {
+      case "/echo.Echo/Get":
+        Echo_EchoGetSession(connection:connection, handler:handler).run(queue:queue)
+      case "/echo.Echo/Expand":
+        Echo_EchoExpandSession(connection:connection, handler:handler).run(queue:queue)
+      case "/echo.Echo/Collect":
+        Echo_EchoCollectSession(connection:connection, handler:handler).run(queue:queue)
+      case "/echo.Echo/Update":
+        Echo_EchoUpdateSession(connection:connection, handler:handler).run(queue:queue)
+      default:
+        break // handle unknown requests
       }
     }
   }

+ 0 - 7
Sources/gRPC/Handler.swift

@@ -35,10 +35,6 @@
 #endif
 import Foundation // for String.Encoding
 
-public protocol Session {
-  func run() -> Void
-}
-
 /// A gRPC request handler
 public class Handler {
   /// Pointer to underlying C representation
@@ -50,9 +46,6 @@ public class Handler {
   /// Metadata received with the request
   public var requestMetadata: Metadata
 
-  /// runnable object that we want retained until the handler is destroyed
-  public var session : Session!
-
   /// A Call object that can be used to respond to the request
   internal lazy var call: Call = {
     return Call(underlyingCall: cgrpc_handler_get_call(self.underlyingHandler),