Jelajahi Sumber

Echo app can now turn streaming on/off with a checkbox

Tim Burks 9 tahun lalu
induk
melakukan
1633d6259b

+ 14 - 15
Examples/Echo/Swift/Echo/AppDelegate.swift

@@ -41,13 +41,13 @@ class AppDelegate: NSObject, NSApplicationDelegate {
 
   func applicationDidFinishLaunching(_ aNotification: Notification) {
     gRPC.initialize()
-   // startServer(address:"localhost:8081")
+    //startServer(address:"localhost:8081")
   }
 
   func log(_ message: String) {
     print(message)
   }
-/*
+
   func startServer(address:String) {
     let fileDescriptorSet = FileDescriptorSet(filename:"echo.out")
     DispatchQueue.global().async {
@@ -68,18 +68,18 @@ class AppDelegate: NSObject, NSApplicationDelegate {
               + " calling " + requestHandler.method()
               + " from " + requestHandler.caller())
 
-            let (_, _, requestBuffer) = requestHandler.receiveMessage(initialMetadata:Metadata())
-            if let requestBuffer = requestBuffer,
-              let requestMessage = fileDescriptorSet.readMessage(name:"EchoRequest",
-                                                                 proto:requestBuffer.data()) {
-
-              requestMessage.forOneField(name:"text") {(field) in
-
-                let replyMessage = fileDescriptorSet.createMessage(name:"EchoResponse")!
-                replyMessage.addField(name:"text", value:field.string())
-
-                let (_, _) = requestHandler.sendResponse(message:ByteBuffer(data:replyMessage.serialize()),
-                                                         trailingMetadata:Metadata())
+            requestHandler.receiveMessage(initialMetadata:Metadata())
+            {(requestBuffer) in
+              if let requestBuffer = requestBuffer,
+                let requestMessage = fileDescriptorSet.readMessage(name:"EchoRequest",
+                                                                   proto:requestBuffer.data()) {
+                requestMessage.forOneField(name:"text") {(field) in
+                  let replyMessage = fileDescriptorSet.createMessage(name:"EchoResponse")!
+                  let text = "echo " + field.string()
+                  replyMessage.addField(name:"text", value:text)
+                  requestHandler.sendResponse(message:ByteBuffer(data:replyMessage.serialize()),
+                                              trailingMetadata:Metadata())
+                }
               }
             }
           }
@@ -91,6 +91,5 @@ class AppDelegate: NSObject, NSApplicationDelegate {
       }
     }
   }
- */
 }
 

+ 20 - 8
Examples/Echo/Swift/Echo/Base.lproj/MainMenu.xib

@@ -104,14 +104,14 @@
         <window title="Echo" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" releasedWhenClosed="NO" animationBehavior="default" id="QvC-M9-y7g">
             <windowStyleMask key="styleMask" titled="YES" closable="YES" miniaturizable="YES"/>
             <windowPositionMask key="initialPositionMask" leftStrut="YES" rightStrut="YES" topStrut="YES" bottomStrut="YES"/>
-            <rect key="contentRect" x="335" y="390" width="400" height="138"/>
-            <rect key="screenRect" x="0.0" y="0.0" width="1440" height="877"/>
+            <rect key="contentRect" x="335" y="390" width="400" height="179"/>
+            <rect key="screenRect" x="0.0" y="0.0" width="1440" height="900"/>
             <view key="contentView" wantsLayer="YES" id="EiT-Mj-1SZ">
-                <rect key="frame" x="0.0" y="0.0" width="400" height="138"/>
+                <rect key="frame" x="0.0" y="0.0" width="400" height="179"/>
                 <autoresizingMask key="autoresizingMask"/>
                 <subviews>
                     <textField verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="DcE-8I-pH3">
-                        <rect key="frame" x="20" y="96" width="360" height="22"/>
+                        <rect key="frame" x="20" y="137" width="360" 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" placeholderString="Type something here." drawsBackground="YES" usesSingleLineMode="YES" id="dQe-de-Ark">
                             <font key="font" metaFont="system"/>
@@ -123,7 +123,7 @@
                         </connections>
                     </textField>
                     <textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="EyU-Iq-sai">
-                        <rect key="frame" x="18" y="60" width="364" height="17"/>
+                        <rect key="frame" x="18" y="101" width="364" height="17"/>
                         <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
                         <textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" placeholderString="Your message will appear here." id="QFh-Sp-bTp">
                             <font key="font" metaFont="system"/>
@@ -132,7 +132,7 @@
                         </textFieldCell>
                     </textField>
                     <textField verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="jnU-RF-9F0">
-                        <rect key="frame" x="20" y="20" width="360" height="22"/>
+                        <rect key="frame" x="20" y="61" width="360" 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">
                             <font key="font" metaFont="system"/>
@@ -140,16 +140,28 @@
                             <color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
                         </textFieldCell>
                     </textField>
+                    <button fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="5WD-rH-7rC">
+                        <rect key="frame" x="18" y="18" width="84" height="25"/>
+                        <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
+                        <buttonCell key="cell" type="check" title="Streaming" bezelStyle="regularSquare" imagePosition="left" inset="2" id="A9P-Au-0Zu">
+                            <behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
+                            <font key="font" metaFont="system"/>
+                        </buttonCell>
+                        <connections>
+                            <action selector="buttonValueChangedWithSender:" target="8aG-cq-jvr" id="hJq-8b-Uoe"/>
+                        </connections>
+                    </button>
                 </subviews>
             </view>
-            <point key="canvasLocation" x="139" y="-296"/>
+            <point key="canvasLocation" x="139" y="-275.5"/>
         </window>
         <viewController id="8aG-cq-jvr" customClass="EchoViewController" customModule="Echo" customModuleProvider="target">
             <connections>
                 <outlet property="addressField" destination="jnU-RF-9F0" id="8vy-f1-cgl"/>
                 <outlet property="messageField" destination="DcE-8I-pH3" id="G2X-oh-frG"/>
                 <outlet property="outputField" destination="EyU-Iq-sai" id="9O7-AA-RS0"/>
-                <outlet property="view" destination="EiT-Mj-1SZ" id="54o-ys-HZg"/>
+                <outlet property="streamingButton" destination="5WD-rH-7rC" id="QqN-UI-iAY"/>
+                <outlet property="view" destination="EiT-Mj-1SZ" id="HXg-ep-0aP"/>
             </connections>
         </viewController>
     </objects>

+ 28 - 3
Examples/Echo/Swift/Echo/EchoViewController.swift

@@ -38,6 +38,7 @@ class EchoViewController : NSViewController, NSTextFieldDelegate {
   @IBOutlet weak var messageField: NSTextField!
   @IBOutlet weak var outputField: NSTextField!
   @IBOutlet weak var addressField: NSTextField!
+  @IBOutlet weak var streamingButton: NSButton!
 
   private var streaming = false
   var client: Client?
@@ -57,6 +58,15 @@ class EchoViewController : NSViewController, NSTextFieldDelegate {
     }
   }
 
+  @IBAction func buttonValueChanged(sender: NSButton) {
+    print("button value changed \(sender)")
+    if (streaming && (sender.intValue == 0)) {
+      print ("stop streaming")
+      self.sendClose()
+    }
+
+  }
+
   override func viewDidLoad() {
     gRPC.initialize()
   }
@@ -74,12 +84,10 @@ class EchoViewController : NSViewController, NSTextFieldDelegate {
   func callServer(address:String) {
     gRPC.initialize()
 
-    if client == nil {
+    if (self.streamingButton.intValue == 0) {
       client = Client(address:address)
       self.client!.completionQueue.run()
-    }
 
-    if false {
       DispatchQueue.global().async {
         // build the message
         if let requestMessage = self.fileDescriptorSet.createMessage(name:"EchoRequest") {
@@ -117,9 +125,13 @@ class EchoViewController : NSViewController, NSTextFieldDelegate {
     }
     else {
       if (!streaming) {
+        client = Client(address:address)
+        self.client!.completionQueue.run()
+
         call = client?.createCall(host: "foo.test.google.fr",
                                   method: "/echo.Echo/Update",
                                   timeout: 600.0)
+
         self.sendInitialMetadata()
         self.receiveInitialMetadata()
         self.receiveStatus()
@@ -218,6 +230,19 @@ class EchoViewController : NSViewController, NSTextFieldDelegate {
       print("call error \(call_error)")
     }
   }
+
+  func sendClose() {
+    let operation_sendCloseFromClient = Operation_SendCloseFromClient()
+    let operations = OperationGroup(call:call!, operations:[operation_sendCloseFromClient])
+    { (event) in
+      print("send close call status \(event.type) \(event.tag)")
+      self.streaming = false
+    }
+    let call_error = client!.perform(call:call!, operations:operations)
+    if call_error != GRPC_CALL_OK {
+      print("call error \(call_error)")
+    }
+  }
 }
 
 

+ 0 - 1
Packages/gRPC/Sources/Client.swift

@@ -108,7 +108,6 @@ public class Client {
     }
     let call_error = self.perform(call: call, operations: group)
     print ("call error = \(call_error)")
-    print("calling \(completionQueue.cq)")
     return call
   }
 

+ 7 - 5
Packages/gRPC/Sources/CompletionQueue.swift

@@ -60,7 +60,8 @@ public class CompletionQueue {
 
   public func run() {
     DispatchQueue.global().async {
-      while (true) {
+      var running = true
+      while (running) {
         let event = cgrpc_completion_queue_get_next_event(self.cq, -1.0)
         switch (event.type) {
         case GRPC_OP_COMPLETE:
@@ -69,16 +70,17 @@ public class CompletionQueue {
             operations.completion(event)
             self.operationGroups[tag] = nil
           }
-          continue
+          break
         case GRPC_QUEUE_SHUTDOWN:
-          // grpc_completion_queue_destroy(unmanagedQueue);
+          running = false
           break
         case GRPC_QUEUE_TIMEOUT:
-          continue
+          break
         default:
-          continue
+          break
         }
       }
+      print("exiting completion queue loop")
     }
   }
 }

+ 27 - 30
Packages/gRPC/Sources/Handler.swift

@@ -90,35 +90,35 @@ public class Handler {
   /// Request a call for the handler
   ///
   /// Fills the handler properties with information about the received request
-  /// 
+  ///
   /// - Returns: a grpc_call_error indicating the result of requesting the call
   func requestCall(tag: Int) -> grpc_call_error {
     return cgrpc_handler_request_call(h, requestMetadata.array, tag)
   }
-/*
+
   /// Receive the message sent with a call
   ///
   /// - Returns: a tuple containing status codes and a message (if available)
-  public func receiveMessage(initialMetadata: Metadata) -> (grpc_call_error, grpc_completion_type, ByteBuffer?) {
-
+  public func receiveMessage(initialMetadata: Metadata,
+                             completion:((ByteBuffer?) -> Void)) -> Void {
+    let call = self.call()
     let operation_sendInitialMetadata = Operation_SendInitialMetadata(metadata:initialMetadata);
     let operation_receiveMessage = Operation_ReceiveMessage()
-
-    let operations = Operations(operations:[
-      operation_sendInitialMetadata,
-      operation_receiveMessage
-    ]) {(call_error, event) in
-
+    let operations = OperationGroup(
+      call:call,
+      operations:[
+        operation_sendInitialMetadata,
+        operation_receiveMessage])
+    {(event) in
       if (event.type == GRPC_OP_COMPLETE) {
-        return (GRPC_CALL_OK, GRPC_OP_COMPLETE, operation_receiveMessage.message())
+        completion(operation_receiveMessage.message())
       } else {
-        return (GRPC_CALL_OK, event.type, nil)
+        completion(nil)
       }
-
     }
 
-    let call = self.call()
-    let call_error = call.performOperations(operations:operations, tag:222, completionQueue:completionQueue)
+    self.completionQueue.operationGroups[operations.tag] = operations
+    _ = call.performOperations(operations:operations, tag:operations.tag, completionQueue: self.completionQueue)
   }
 
   /// Sends the response to a request
@@ -126,26 +126,23 @@ public class Handler {
   /// - Parameter message: the message to send
   /// - Returns: a tuple containing status codes
   public func sendResponse(message: ByteBuffer,
-                           trailingMetadata: Metadata) -> (grpc_call_error, grpc_completion_type) {
+                           trailingMetadata: Metadata) -> Void {
+    let call = self.call()
     let operation_receiveCloseOnServer = Operation_ReceiveCloseOnServer();
     let operation_sendStatusFromServer = Operation_SendStatusFromServer(status:0,
                                                                         statusDetails:"OK",
                                                                         metadata:trailingMetadata)
     let operation_sendMessage = Operation_SendMessage(message:message)
-
-    let operations = Operations(operations:[
-      operation_receiveCloseOnServer,
-      operation_sendStatusFromServer,
-      operation_sendMessage
-    ])
-
-    let call = self.call()
-    let call_error = call.performOperations(operations:operations, tag:333)
-    if call_error != GRPC_CALL_OK {
-      return (call_error, GRPC_OP_COMPLETE)
+    let operations = OperationGroup(
+      call:call,
+      operations:[
+        operation_receiveCloseOnServer,
+        operation_sendStatusFromServer,
+        operation_sendMessage])
+    {(call_error) in
+      print("server response complete")
     }
-    let event = completionQueue.waitForCompletion(timeout:5.0)
-    return (GRPC_CALL_OK, event.type)
+    self.completionQueue.operationGroups[operations.tag] = operations
+    _ = call.performOperations(operations:operations, tag:operations.tag, completionQueue: self.completionQueue)
   }
- */
 }