1 /*
2 *
3 * Copyright 2018 gRPC authors.
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
17 */
18
19 #include <atomic>
20
21 #include <grpc++/grpc++.h>
22 #include <jni.h>
23
24 #include "helloworld.grpc.pb.h"
25
26 using grpc::Channel;
27 using grpc::ClientContext;
28 using grpc::Server;
29 using grpc::ServerBuilder;
30 using grpc::ServerContext;
31 using grpc::Status;
32 using helloworld::Greeter;
33 using helloworld::HelloReply;
34 using helloworld::HelloRequest;
35
36 std::atomic<bool> stop_server(false);
37
38 // Logic and data behind the server's behavior.
39 class GreeterServiceImpl final : public Greeter::Service {
SayHello(ServerContext * context,const HelloRequest * request,HelloReply * reply)40 Status SayHello(ServerContext* context, const HelloRequest* request,
41 HelloReply* reply) override {
42 std::string prefix("Hello ");
43 reply->set_message(prefix + request->name());
44 return Status::OK;
45 }
46 };
47
StartServer(JNIEnv * env,jobject obj,jmethodID is_cancelled_mid,int port)48 void StartServer(JNIEnv* env, jobject obj, jmethodID is_cancelled_mid,
49 int port) {
50 const int host_port_buf_size = 1024;
51 char host_port[host_port_buf_size];
52 snprintf(host_port, host_port_buf_size, "0.0.0.0:%d", port);
53
54 GreeterServiceImpl service;
55 ServerBuilder builder;
56 // Listen on the given address without any authentication mechanism.
57 builder.AddListeningPort(host_port, grpc::InsecureServerCredentials());
58 // Register "service" as the instance through which we'll communicate with
59 // clients. In this case it corresponds to an *synchronous* service.
60 builder.RegisterService(&service);
61 // Finally assemble the server.
62 std::unique_ptr<Server> server(builder.BuildAndStart());
63 while (!stop_server.load()) {
64 // Check with the Java code to see if the user has requested the server stop or the app is no
65 // longer in the foreground.
66 jboolean is_cancelled = env->CallBooleanMethod(obj, is_cancelled_mid);
67 if (is_cancelled == JNI_TRUE) {
68 stop_server = true;
69 }
70 }
71 }
72
73 class GreeterClient {
74 public:
GreeterClient(std::shared_ptr<Channel> channel)75 GreeterClient(std::shared_ptr<Channel> channel)
76 : stub_(Greeter::NewStub(channel)) {}
77
78 // Assembles the client's payload, sends it and presents the response back
79 // from the server.
SayHello(const std::string & user)80 std::string SayHello(const std::string& user) {
81 // Data we are sending to the server.
82 HelloRequest request;
83 request.set_name(user);
84
85 // Container for the data we expect from the server.
86 HelloReply reply;
87
88 // Context for the client. It could be used to convey extra information to
89 // the server and/or tweak certain RPC behaviors.
90 ClientContext context;
91 // The actual RPC.
92 Status status = stub_->SayHello(&context, request, &reply);
93
94 if (status.ok()) {
95 return reply.message();
96 } else {
97 return status.error_message();
98 }
99 }
100
101 private:
102 std::unique_ptr<Greeter::Stub> stub_;
103 };
104
105 // Send an RPC and return the response. Invoked from Java code.
106 extern "C" JNIEXPORT jstring JNICALL
Java_io_grpc_helloworldexample_cpp_HelloworldActivity_sayHello(JNIEnv * env,jobject obj_unused,jstring host_raw,jint port_raw,jstring message_raw)107 Java_io_grpc_helloworldexample_cpp_HelloworldActivity_sayHello(
108 JNIEnv* env, jobject obj_unused, jstring host_raw, jint port_raw,
109 jstring message_raw) {
110 const char* host_chars = env->GetStringUTFChars(host_raw, (jboolean*)0);
111 std::string host(host_chars, env->GetStringUTFLength(host_raw));
112
113 int port = static_cast<int>(port_raw);
114
115 const char* message_chars = env->GetStringUTFChars(message_raw, (jboolean*)0);
116 std::string message(message_chars, env->GetStringUTFLength(message_raw));
117
118 const int host_port_buf_size = 1024;
119 char host_port[host_port_buf_size];
120 snprintf(host_port, host_port_buf_size, "%s:%d", host.c_str(), port);
121
122 GreeterClient greeter(
123 grpc::CreateChannel(host_port, grpc::InsecureChannelCredentials()));
124 std::string reply = greeter.SayHello(message);
125
126 return env->NewStringUTF(reply.c_str());
127 }
128
129 // Start the server. Invoked from Java code.
130 extern "C" JNIEXPORT void JNICALL
Java_io_grpc_helloworldexample_cpp_HelloworldActivity_startServer(JNIEnv * env,jobject obj_this,jint port_raw)131 Java_io_grpc_helloworldexample_cpp_HelloworldActivity_startServer(
132 JNIEnv* env, jobject obj_this, jint port_raw) {
133 int port = static_cast<int>(port_raw);
134
135 jclass cls = env->GetObjectClass(obj_this);
136 jmethodID is_cancelled_mid =
137 env->GetMethodID(cls, "isRunServerTaskCancelled", "()Z");
138
139 stop_server = false;
140
141 StartServer(env, obj_this, is_cancelled_mid, port);
142 }
143