Browse Source

Updates to Sessions demo app to match new API.

Tim Burks 9 years ago
parent
commit
c7630c2074

+ 6 - 11
Examples/Sessions/Sessions/Base.lproj/Document.xib

@@ -1,8 +1,8 @@
 <?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="11129.15" systemVersion="15G31" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
+<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="11198.2" systemVersion="15G31" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
     <dependencies>
         <deployment identifier="macosx"/>
-        <plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="11129.15"/>
+        <plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="11198.2"/>
     </dependencies>
     <objects>
         <customObject id="-2" userLabel="File's Owner" customClass="Document" customModule="Sessions" customModuleProvider="target">
@@ -48,11 +48,8 @@
                             </segments>
                         </segmentedCell>
                     </segmentedControl>
-                    <box verticalHuggingPriority="750" title="Box" boxType="separator" titlePosition="noTitle" translatesAutoresizingMaskIntoConstraints="NO" id="LWX-9I-afj">
+                    <box verticalHuggingPriority="750" boxType="separator" translatesAutoresizingMaskIntoConstraints="NO" id="LWX-9I-afj">
                         <rect key="frame" x="0.0" y="367" width="507" height="5"/>
-                        <color key="borderColor" white="0.0" alpha="0.41999999999999998" colorSpace="calibratedWhite"/>
-                        <color key="fillColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
-                        <font key="titleFont" metaFont="system"/>
                     </box>
                     <button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="E5S-Hy-mmH">
                         <rect key="frame" x="423" y="373" width="70" height="32"/>
@@ -69,7 +66,7 @@
                         <constraints>
                             <constraint firstAttribute="width" constant="48" id="v6k-Kj-Zr6"/>
                         </constraints>
-                        <textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" editable="YES" sendsActionOnEndEditing="YES" state="on" borderStyle="bezel" title="8080" placeholderString="port" drawsBackground="YES" id="EyU-s3-DxA">
+                        <textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" editable="YES" sendsActionOnEndEditing="YES" state="on" borderStyle="bezel" title="9090" placeholderString="port" drawsBackground="YES" id="EyU-s3-DxA">
                             <font key="font" metaFont="system"/>
                             <color key="textColor" name="textColor" catalog="System" colorSpace="catalog"/>
                             <color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
@@ -81,15 +78,13 @@
                             <rect key="frame" x="1" y="1" width="505" height="367"/>
                             <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
                             <subviews>
-                                <textView importsGraphics="NO" findStyle="panel" continuousSpellChecking="YES" allowsUndo="YES" usesRuler="YES" usesFontPanel="YES" verticallyResizable="YES" allowsNonContiguousLayout="YES" quoteSubstitution="YES" dashSubstitution="YES" spellingCorrection="YES" smartInsertDelete="YES" id="Yd5-bB-slU">
+                                <textView importsGraphics="NO" usesFontPanel="YES" findStyle="panel" continuousSpellChecking="YES" allowsUndo="YES" usesRuler="YES" allowsNonContiguousLayout="YES" quoteSubstitution="YES" dashSubstitution="YES" spellingCorrection="YES" smartInsertDelete="YES" id="Yd5-bB-slU">
                                     <rect key="frame" x="0.0" y="0.0" width="505" height="367"/>
                                     <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
                                     <color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
                                     <size key="minSize" width="505" height="367"/>
-                                    <size key="maxSize" width="505" height="10000000"/>
+                                    <size key="maxSize" width="507" height="10000000"/>
                                     <color key="insertionPointColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
-                                    <size key="minSize" width="505" height="367"/>
-                                    <size key="maxSize" width="505" height="10000000"/>
                                 </textView>
                             </subviews>
                             <color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>

+ 67 - 72
Examples/Sessions/Sessions/Document.swift

@@ -64,6 +64,10 @@ class Document: NSDocument {
   @IBOutlet var textView: NSTextView!
   // http://stackoverflow.com/questions/24062437/cannot-form-weak-reference-to-instance-of-class-nstextview
 
+  var client : Client!
+
+  var server : Server!
+
   var running: Bool // all accesses to this should be synchronized
 
   override init() {
@@ -82,15 +86,10 @@ class Document: NSDocument {
   }
 
   override func data(ofType typeName: String) throws -> Data {
-    // Insert code here to write your document to data of the specified type. If outError != nil, ensure that you create and set an appropriate error when returning nil.
-    // You can also choose to override fileWrapperOfType:error:, writeToURL:ofType:error:, or writeToURL:ofType:forSaveOperation:originalContentsURL:error: instead.
     throw NSError(domain: NSOSStatusErrorDomain, code: unimpErr, userInfo: nil)
   }
 
   override func read(from data: Data, ofType typeName: String) throws {
-    // Insert code here to read your document from the given data of the specified type. If outError != nil, ensure that you create and set an appropriate error when returning false.
-    // You can also choose to override readFromFileWrapper:ofType:error: or readFromURL:ofType:error: instead.
-    // If you override either of these, you should also override -isEntireFileLoaded to return false if the contents are lazily loaded.
     throw NSError(domain: NSOSStatusErrorDomain, code: unimpErr, userInfo: nil)
   }
 
@@ -152,64 +151,61 @@ class Document: NSDocument {
   }
 
   func stop() {
-    setIsRunning(false)
+    if (self.client != nil) {
+      setIsRunning(false) // stops client
+    }
+    if (self.server != nil) {
+      self.server.stop() // stops server
+    }
   }
 
   func startServer(address:String) {
-    DispatchQueue.global().async {
-      self.log("Server Starting")
-      self.log("GRPC version " + gRPC.version())
-      self.setIsRunning(true)
+    self.log("Server Starting")
+    self.log("GRPC version " + gRPC.version())
+    self.setIsRunning(true)
 
-      let server = gRPC.Server(address:address)
-      server.start()
+    self.server = gRPC.Server(address:address)
+    var requestCount = 0
 
-      var requestCount = 0
-      while(self.isRunning()) {
-        let (callError, completionType, requestHandler) = server.getNextRequest(timeout:1.0)
-        if (callError != GRPC_CALL_OK) {
-          self.log("\(requestCount): Call error \(callError)")
-          self.log("------------------------------")
-        } else if (completionType == GRPC_OP_COMPLETE) {
-          if let requestHandler = requestHandler {
-            requestCount += 1
-            self.log("\(requestCount): Received request " + requestHandler.host() + " " + requestHandler.method() + " from " + requestHandler.caller())
-            let initialMetadata = requestHandler.requestMetadata
-            for i in 0..<initialMetadata.count() {
-              self.log("\(requestCount): Received initial metadata -> " + initialMetadata.key(index:i) + ":" + initialMetadata.value(index:i))
-            }
+    self.server.run() {(requestHandler) in
+      requestCount += 1
+      self.log("\(requestCount): Received request " + requestHandler.host()
+        + " " + requestHandler.method()
+        + " from " + requestHandler.caller())
+      let initialMetadata = requestHandler.requestMetadata
+      for i in 0..<initialMetadata.count() {
+        self.log("\(requestCount): Received initial metadata -> " + initialMetadata.key(index:i) + ":" + initialMetadata.value(index:i))
+      }
 
-            let initialMetadataToSend = Metadata()
-            initialMetadataToSend.add(key:"a", value:"Apple")
-            initialMetadataToSend.add(key:"b", value:"Banana")
-            initialMetadataToSend.add(key:"c", value:"Cherry")
-            let (_, _, message) = requestHandler.receiveMessage(initialMetadata:initialMetadataToSend)
-            if let message = message {
-              self.log("\(requestCount): Received message: " + message.string())
-            }
-            if requestHandler.method() == "/quit" {
-              self.stop()
-            }
-            let replyMessage = "thank you very much!"
-            let trailingMetadataToSend = Metadata()
-            trailingMetadataToSend.add(key:"0", value:"zero")
-            trailingMetadataToSend.add(key:"1", value:"one")
-            trailingMetadataToSend.add(key:"2", value:"two")
-            let (_, _) = requestHandler.sendResponse(message:ByteBuffer(string:replyMessage),
-                                                     trailingMetadata:trailingMetadataToSend)
-            self.log("------------------------------")
-          }
-        } else if (completionType == GRPC_QUEUE_TIMEOUT) {
-          // everything is fine
-        } else if (completionType == GRPC_QUEUE_SHUTDOWN) {
-          self.stop()
-        }
+      let initialMetadataToSend = Metadata()
+      initialMetadataToSend.add(key:"a", value:"Apple")
+      initialMetadataToSend.add(key:"b", value:"Banana")
+      initialMetadataToSend.add(key:"c", value:"Cherry")
+      requestHandler.receiveMessage(initialMetadata:initialMetadataToSend) {(messageBuffer) in
+        let messageData = messageBuffer!.data()
+        let messageString = String(data: messageData as Data, encoding:String.Encoding.utf8)
+        self.log("\(requestCount): Received message: " + messageString!)
       }
+      if requestHandler.method() == "/quit" {
+        self.stop()
+      }
+      let replyMessage = "thank you very much!"
+      let trailingMetadataToSend = Metadata()
+      trailingMetadataToSend.add(key:"0", value:"zero")
+      trailingMetadataToSend.add(key:"1", value:"one")
+      trailingMetadataToSend.add(key:"2", value:"two")
+      requestHandler.sendResponse(message:ByteBuffer(string:replyMessage),
+                                  trailingMetadata:trailingMetadataToSend)
+      self.log("------------------------------")
+    }
+
+    self.server.onCompletion() {
       self.log("Server Stopped")
       self.updateInterfaceAfterStopping()
     }
   }
 
+
   func startClient(address:String) {
     DispatchQueue.global().async {
       self.log("Client Starting")
@@ -219,7 +215,7 @@ class Document: NSDocument {
       let host = "foo.test.google.fr"
       let message = gRPC.ByteBuffer(string:"hello gRPC server!")
 
-      let c = gRPC.Client(address:address)
+      self.client = gRPC.Client(address:address)
       let steps = 10
       for i in 1...steps {
         if !self.isRunning() {
@@ -231,33 +227,32 @@ class Document: NSDocument {
                                        MetadataPair(key:"y", value:"yu"),
                                        MetadataPair(key:"z", value:"zither")])
 
-        let response = c.performRequest(host:host,
-                                        method:method,
-                                        message:message,
-                                        metadata:metadata)
+        let call = self.client.createCall(host: host, method: method, timeout: 30)
+        call.performNonStreamingCall(messageData: message.data(),
+                                     metadata: metadata)
+        {(response) in
 
-        if let initialMetadata = response.initialMetadata {
-          for j in 0..<initialMetadata.count() {
-            self.log("\(i): Received initial metadata -> " + initialMetadata.key(index:j) + " : " + initialMetadata.value(index:j))
+          if let initialMetadata = response.initialMetadata {
+            for j in 0..<initialMetadata.count() {
+              self.log("\(i): Received initial metadata -> " + initialMetadata.key(index:j) + " : " + initialMetadata.value(index:j))
+            }
           }
-        }
 
-        self.log("\(i): Received status: \(response.status) " + response.statusDetails)
-        if let message = response.message {
-          self.log("\(i): Received message: " + message.string())
-        }
+          self.log("\(i): Received status: \(response.status) " + response.statusDetails)
+          if let messageData = response.messageData {
+            let messageString = String(data: messageData as Data, encoding:String.Encoding.utf8)
+            self.log("\(i): Received message: " + messageString!)
+          }
 
-        if let trailingMetadata = response.trailingMetadata {
-          for j in 0..<trailingMetadata.count() {
-            self.log("\(i): Received trailing metadata -> " + trailingMetadata.key(index:j) + " : " + trailingMetadata.value(index:j))
+          if let trailingMetadata = response.trailingMetadata {
+            for j in 0..<trailingMetadata.count() {
+              self.log("\(i): Received trailing metadata -> " + trailingMetadata.key(index:j) + " : " + trailingMetadata.value(index:j))
+            }
           }
-        }
-        self.log("------------------------------")
+          self.log("------------------------------")
 
-        if (response.status != 0) {
-          break
         }
-
+        
         sleep(1)
       }
       self.log("Client Stopped")

+ 1 - 0
Packages/CgRPC/Sources/cgrpc.h

@@ -137,6 +137,7 @@ cgrpc_completion_queue *cgrpc_client_completion_queue(cgrpc_client *client);
 
 // server support
 cgrpc_server *cgrpc_server_create(const char *address);
+void cgrpc_server_stop(cgrpc_server *server);
 void cgrpc_server_destroy(cgrpc_server *s);
 void cgrpc_server_start(cgrpc_server *s);
 cgrpc_completion_queue *cgrpc_server_get_completion_queue(cgrpc_server *s);

+ 6 - 0
Packages/CgRPC/Sources/server.c

@@ -48,6 +48,12 @@ cgrpc_server *cgrpc_server_create(const char *address) {
   return server;
 }
 
+void cgrpc_server_stop(cgrpc_server *server) {
+  grpc_server_shutdown_and_notify(server->server,
+                                  server->completion_queue,
+                                  cgrpc_create_tag(0));
+}
+
 void cgrpc_server_destroy(cgrpc_server *server) {
   grpc_server_shutdown_and_notify(server->server,
                                   server->completion_queue,

+ 42 - 11
Packages/gRPC/Sources/Server.swift

@@ -46,6 +46,9 @@ public class Server {
   /// Active handlers
   var handlers : NSMutableSet!
 
+  /// Optional callback when server stops serving
+  private var onCompletion: (() -> Void)!
+
   /// Initializes a Server
   ///
   /// - Parameter address: the address where the server will listen
@@ -61,25 +64,53 @@ public class Server {
   }
 
   /// Run the server
-  public func run(handler: @escaping (Handler) -> Void) {
+  public func run(handlerFunction: @escaping (Handler) -> Void) {
     cgrpc_server_start(s);
     DispatchQueue.global().async {
-      while(true) {
-        let (callError, completionType, requestHandler) =
-          self.getNextRequest(timeout:600.0)
-        if (callError != GRPC_CALL_OK) {
-          print("Call error \(callError)")
-        } else if (completionType == GRPC_OP_COMPLETE) {
-          handler(requestHandler!)
-        } else if (completionType == GRPC_QUEUE_TIMEOUT) {
-          // everything is fine
-        } else if (completionType == GRPC_QUEUE_SHUTDOWN) {
+      var running = true
+      while(running) {
+        let handler = Handler(h:cgrpc_handler_create_with_server(self.s))
+        let call_error = handler.requestCall(tag:101)
+        if (call_error != GRPC_CALL_OK) {
+          // not good, let's break
           break
         }
+        // blocks
+        let event = self.completionQueue.waitForCompletion(timeout:600)
+        if (event.type == GRPC_OP_COMPLETE) {
+          if cgrpc_event_tag(event) == 101 {
+            // run the handler and remove it when it finishes
+            if event.success != 0 {
+              self.handlers.add(handler)
+              handler.completionQueue.run() {
+                // on completion
+                self.handlers.remove(handler)
+              }
+              handlerFunction(handler)
+            }
+          } else if cgrpc_event_tag(event) == 0 {
+            running = false // exit the loop
+          }
+        } else if (event.type == GRPC_QUEUE_TIMEOUT) {
+          // everything is fine
+        } else if (event.type == GRPC_QUEUE_SHUTDOWN) {
+          running = false
+        }
+      }
+      if let onCompletion = self.onCompletion {
+        onCompletion()
       }
     }
   }
 
+  public func stop() {
+    cgrpc_server_stop(s)
+  }
+
+  public func onCompletion(completion:(() -> Void)) -> Void {
+    onCompletion = completion
+  }
+
   /// Gets the next request sent to the server
   ///
   /// - Returns: a tuple containing the results of waiting and a possible Handler for the request