Browse Source

Add Echo2 sample with a service definition split among multiple files.

Tim Burks 8 years ago
parent
commit
20e4a304cd

+ 12 - 0
Examples/Echo2/Makefile

@@ -0,0 +1,12 @@
+
+all:
+	swift build -c release
+	cp .build/release/Echo .
+
+project:
+	swift package generate-xcodeproj
+
+clean :
+	rm -rf Packages googleapis .build
+	rm -f Package.pins Echo Sources/*.pb.swift Sources/swiftgrpc.log google.json
+	rm -rf Package.resolved Echo.xcodeproj

+ 23 - 0
Examples/Echo2/Package.swift

@@ -0,0 +1,23 @@
+/*
+ * Copyright 2016, gRPC Authors All rights reserved.
+ *
+ * Licensed 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 PackageDescription
+let package = Package (
+    name: "Echo",
+    dependencies: [
+        .Package(url: "https://github.com/grpc/grpc-swift.git", Version(0,3,1)),
+        .Package(url: "https://github.com/apple/swift-protobuf.git", Version(1,0,2)),
+    ]
+)

+ 33 - 0
Examples/Echo2/Protos/echo.proto

@@ -0,0 +1,33 @@
+// Copyright (c) 2015, Google Inc.
+//
+// Licensed 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.
+
+syntax = "proto3";
+
+package echo;
+
+import "echo_messages.proto";
+
+service Echo {
+  // Immediately returns an echo of a request.
+  rpc Get(EchoRequest) returns (EchoResponse) {}
+  
+  // Splits a request into words and returns each word in a stream of messages.
+  rpc Expand(EchoRequest) returns (stream EchoResponse) {}  
+  
+  // Collects a stream of messages and returns them concatenated when the caller closes.
+  rpc Collect(stream EchoRequest) returns (EchoResponse) {}
+  
+  // Streams back messages as they are received in an input stream.
+  rpc Update(stream EchoRequest) returns (stream EchoResponse) {}
+}

+ 27 - 0
Examples/Echo2/Protos/echo_messages.proto

@@ -0,0 +1,27 @@
+// Copyright (c) 2015, Google Inc.
+//
+// Licensed 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.
+
+syntax = "proto3";
+
+package echo;
+
+message EchoRequest {
+  // The text of a message to be echoed.
+  string text = 1;
+}
+
+message EchoResponse {
+  // The text of an echo response.
+  string text = 1;
+}

+ 6 - 0
Examples/Echo2/README.md

@@ -0,0 +1,6 @@
+# Echo2
+
+This directory contains a minor variation of the Echo
+sample that divides the echo.proto into two parts: one
+containing message definitions and one for service 
+definitions.

+ 15 - 0
Examples/Echo2/RUNME

@@ -0,0 +1,15 @@
+#!/bin/sh
+#
+# Use this script to regenerate the Protocol Buffer and gRPC files
+# needed to build the example.
+#
+# Note that it requires updated protoc, protoc-gen-swift, and
+# protoc-gen-swiftgrpc binaries and assumes that protoc-gen-swift 
+# is installed in $HOME/local/bin.
+
+protoc \
+	Protos/*.proto \
+	--swift_out=Sources \
+	--swiftgrpc_out=Sources \
+ 	-IProtos 
+

+ 81 - 0
Examples/Echo2/Sources/EchoProvider.swift

@@ -0,0 +1,81 @@
+/*
+ * Copyright 2016, gRPC Authors All rights reserved.
+ *
+ * Licensed 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 Foundation
+import Dispatch
+
+class EchoProvider : Echo_EchoProvider {
+
+  // get returns requests as they were received.
+  func get(request : Echo_EchoRequest, session : Echo_EchoGetSession) throws -> Echo_EchoResponse {
+    var response = Echo_EchoResponse()
+    response.text = "Swift echo get: " + request.text
+    return response
+  }
+
+  // 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 {
+      var response = Echo_EchoResponse()
+      response.text = "Swift echo expand (\(i)): \(part)"
+      let sem = DispatchSemaphore(value: 0)
+      try session.send(response) {sem.signal()}
+      _ = sem.wait(timeout: DispatchTime.distantFuture)
+      i += 1
+      sleep(1)
+    }
+  }
+
+  // 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)")
+      }
+    }
+    var response = Echo_EchoResponse()
+    response.text = "Swift echo collect: " + parts.joined(separator: " ")
+    try session.sendAndClose(response)
+  }
+
+  // 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
+        var response = Echo_EchoResponse()
+        response.text = "Swift echo update (\(count)): \(request.text)"
+        let sem = DispatchSemaphore(value: 0)
+        try session.send(response) {sem.signal()}
+        _ = sem.wait(timeout: DispatchTime.distantFuture)
+      } catch Echo_EchoServerError.endOfStream {
+        break
+      } catch (let error) {
+        print("\(error)")
+      }
+    }
+    try session.close()
+  }
+}

+ 214 - 0
Examples/Echo2/Sources/main.swift

@@ -0,0 +1,214 @@
+/*
+ * Copyright 2016, gRPC Authors All rights reserved.
+ *
+ * Licensed 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 Foundation
+import gRPC
+import CgRPC
+import Dispatch
+
+print("\(CommandLine.arguments)")
+
+// server options
+var server : Bool = false
+
+// client options
+var client : String = ""
+var message : String = "Testing 1 2 3"
+var address : String = ""
+var port : String = ""
+
+// self-test mode
+var test : Bool = false
+
+// general configuration
+var useSSL : Bool = false
+
+var i : Int = 0
+while i < Int(CommandLine.argc) {
+  let arg = CommandLine.arguments[i]
+  i = i + 1
+  if i == 1 {
+    continue // skip the first argument
+  }
+
+  if arg == "test" {
+    test = true
+  } else if arg == "serve" {
+    server = true
+  } else if (arg == "get") || (arg == "expand") || (arg == "collect") || (arg == "update") {
+    client = arg
+  } else if arg == "-ssl" {
+    useSSL = true
+  } else if arg == "-m" && (i < Int(CommandLine.argc)) {
+    message = CommandLine.arguments[i]
+    i = i + 1
+  } else if arg == "-a" && (i < Int(CommandLine.argc)) {
+    address = CommandLine.arguments[i]
+    i = i + 1
+  } else if arg == "-p" && (i < Int(CommandLine.argc)) {
+    port = CommandLine.arguments[i]
+    i = i + 1
+  }
+}
+
+if address == "" {
+  if server {
+    address = "0.0.0.0"
+  } else {
+    address = "localhost"
+  }
+}
+
+if port == "" {
+  if useSSL {
+    port = "8443"
+  } else {
+    port = "8081"
+  }
+}
+
+print(address + ":" + port + "\n")
+
+let sem = DispatchSemaphore(value: 0)
+
+gRPC.initialize()
+
+if server {
+  let echoProvider = EchoProvider()
+  var echoServer: Echo_EchoServer!
+
+  if useSSL {
+    print("Starting secure server")
+    let certificateURL = URL(fileURLWithPath:"ssl.crt")
+    let keyURL = URL(fileURLWithPath:"ssl.key")
+    echoServer = Echo_EchoServer(address:address + ":" + port,
+                                 certificateURL:certificateURL,
+                                 keyURL:keyURL,
+                                 provider:echoProvider)
+  } else {
+    print("Starting insecure server")
+    echoServer = Echo_EchoServer(address:address + ":" + port,
+                                 provider:echoProvider)
+  }
+  echoServer.start()
+  // Block to keep the main thread from finishing while the server runs.
+  // This server never exits. Kill the process to stop it.
+  _ = sem.wait(timeout: DispatchTime.distantFuture)
+}
+
+if client != "" {
+  do {
+
+    print("Starting client")
+
+    var service : Echo_EchoService
+    if useSSL {
+      let certificateURL = URL(fileURLWithPath:"ssl.crt")
+      let certificates = try! String(contentsOf: certificateURL)
+      service = Echo_EchoService(address:address + ":" + port, certificates:certificates, host:"example.com")
+      service.host = "example.com" // sample override
+    } else {
+      service = Echo_EchoService(address:address + ":" + port, secure:false)
+    }
+
+    service.metadata = Metadata(["x-goog-api-key":"YOUR_API_KEY",
+                                 "x-ios-bundle-identifier":"com.google.echo"])
+
+    // Unary
+    if client == "get" {
+      var requestMessage = Echo_EchoRequest()
+      requestMessage.text = message
+      print("Sending: " + requestMessage.text)
+      let responseMessage = try service.get(requestMessage)
+      print("get received: " + responseMessage.text)
+    }
+
+    // Server streaming
+    if client == "expand" {
+      var requestMessage = Echo_EchoRequest()
+      requestMessage.text = message
+      print("Sending: " + requestMessage.text)
+      let expandCall = try service.expand(requestMessage) {result in }
+      var running = true
+      while running {
+        do {
+          let responseMessage = try expandCall.receive()
+          print("Received: \(responseMessage.text)")
+        } catch Echo_EchoClientError.endOfStream {
+          print("expand closed")
+          running = false
+        }
+      }
+    }
+
+    // Client streaming
+    if client == "collect" {
+      let collectCall = try service.collect() {result in }
+
+      let parts = message.components(separatedBy:" ")
+      for part in parts {
+        var requestMessage = Echo_EchoRequest()
+        requestMessage.text = part
+        print("Sending: " + part)
+        try collectCall.send(requestMessage) {error in print(error)}
+        sleep(1)
+      }
+
+      let responseMessage = try collectCall.closeAndReceive()
+      print("Received: \(responseMessage.text)")
+    }
+
+    // Bidirectional streaming
+    if client == "update" {
+      let updateCall = try service.update() {result in}
+
+      DispatchQueue.global().async {
+        var running = true
+        while running {
+          do {
+            let responseMessage = try updateCall.receive()
+            print("Received: \(responseMessage.text)")
+          } catch Echo_EchoClientError.endOfStream {
+            print("update closed")
+            sem.signal()
+            running = false
+          } catch (let error) {
+            print("error: \(error)")
+          }
+        }
+      }
+
+      let parts = message.components(separatedBy:" ")
+      for part in parts {
+        var requestMessage = Echo_EchoRequest()
+        requestMessage.text = part
+        print("Sending: " + requestMessage.text)
+        try updateCall.send(requestMessage) {error in print(error)}
+        sleep(1)
+      }
+      try updateCall.closeSend()
+
+      // Wait for the call to complete.
+      _ = sem.wait(timeout: DispatchTime.distantFuture)
+    }
+
+  } catch let error {
+    print("error:\(error)")
+  }
+}
+
+if test {
+  print("self test")
+}