|
1 | | -// |
2 | | -// Created by Johannes Zottele on 11.07.25. |
3 | | -// |
| 1 | +/* |
| 2 | + * Copyright 2023-2025 JetBrains s.r.o and contributors. Use of this source code is governed by the Apache 2.0 license. |
| 3 | + */ |
4 | 4 |
|
5 | 5 | #include <grpcpp_c.h> |
6 | 6 |
|
7 | | -#include <memory> |
8 | | -#include <grpcpp/grpcpp.h> |
9 | | -#include <grpcpp/generic/generic_stub.h> |
10 | | -#include <grpcpp/impl/client_unary_call.h> |
11 | | -#include <google/protobuf/io/coded_stream.h> |
12 | | -#include <google/protobuf/io/zero_copy_stream_impl_lite.h> |
13 | 7 | #include "src/core/lib/iomgr/iomgr.h" |
14 | 8 |
|
15 | | -namespace pb = google::protobuf; |
16 | | - |
17 | | -struct grpc_client { |
18 | | - std::shared_ptr<grpc::Channel> channel; |
19 | | - std::unique_ptr<grpc::GenericStub> stub; |
20 | | -}; |
21 | | - |
22 | | -struct grpc_method { |
23 | | - std::string name_str; |
24 | | - std::unique_ptr<grpc::internal::RpcMethod> method; |
25 | | -}; |
26 | | - |
27 | | -struct grpc_context { |
28 | | - std::unique_ptr<grpc::ClientContext> context; |
29 | | -}; |
30 | | - |
31 | | -// struct grpc_channel { |
32 | | -// std::shared_ptr<grpc::Channel> channel; |
33 | | -// }; |
34 | | - |
35 | 9 | extern "C" { |
36 | 10 |
|
37 | | - grpc_client_t *grpc_client_create_insecure(const char *target) { |
38 | | - std::string target_str = target; |
39 | | - auto client = new grpc_client; |
40 | | - client->channel = grpc::CreateChannel(target_str, grpc::InsecureChannelCredentials()); |
41 | | - client->stub = std::make_unique<grpc::GenericStub>(client->channel); |
42 | | - return client; |
43 | | - } |
44 | | - |
45 | | - void grpc_client_delete(const grpc_client_t *client) { |
46 | | - delete client; |
47 | | - } |
48 | | - |
49 | | - grpc_method_t *grpc_method_create(const char *method_name) { |
50 | | - auto *method = new grpc_method; |
51 | | - method->name_str = method_name; |
52 | | - method->method = std::make_unique<grpc::internal::RpcMethod>(method->name_str.c_str(), grpc::internal::RpcMethod::NORMAL_RPC); |
53 | | - return method; |
54 | | - } |
55 | | - |
56 | | - void grpc_method_delete(const grpc_method_t *method) { |
57 | | - delete method; |
58 | | - } |
59 | | - |
60 | | - const char *grpc_method_name(const grpc_method_t *method) { |
61 | | - return method->method->name(); |
62 | | - } |
63 | | - |
64 | | - grpc_context_t *grpc_context_create() { |
65 | | - auto *context = new grpc_context; |
66 | | - context->context = std::make_unique<grpc::ClientContext>(); |
67 | | - return context; |
68 | | - } |
69 | | - |
70 | | - void grpc_context_delete(const grpc_context_t *context) { |
71 | | - delete context; |
72 | | - } |
73 | | - |
74 | | - static grpc_status_code_t status_to_c(grpc::StatusCode status); |
75 | | - |
76 | | - grpc_status_code_t grpc_client_call_unary_blocking(grpc_client_t *client, const char *method, |
77 | | - grpc_slice req_slice, grpc_slice *resp_slice) { |
78 | | - |
79 | | - if (!client || !method) return GRPC_C_STATUS_INVALID_ARGUMENT; |
80 | | - |
81 | | - grpc::Slice cc_req_slice(req_slice, grpc::Slice::ADD_REF); |
82 | | - grpc::ByteBuffer req_bb(&cc_req_slice, 1); |
83 | | - |
84 | | - grpc::ClientContext context; |
85 | | - grpc::ByteBuffer resp_bb; |
86 | | - |
87 | | - const std::string method_path = "/Greeter/SayHello"; |
88 | | - grpc::internal::RpcMethod rpc(method_path.c_str(), |
89 | | - grpc::internal::RpcMethod::NORMAL_RPC); |
90 | | - |
91 | | - grpc::Status st = |
92 | | - grpc::internal::BlockingUnaryCall<grpc::ByteBuffer, grpc::ByteBuffer>( |
93 | | - client->channel.get(), rpc, &context, req_bb, &resp_bb); |
94 | | - |
95 | | - |
96 | | - if (!st.ok()) { |
97 | | - // if not ok, no resp_buf is left null |
98 | | - return status_to_c(st.error_code()); |
99 | | - } |
100 | | - |
101 | | - grpc::Slice cc_resp_slice; |
102 | | - resp_bb.DumpToSingleSlice(&cc_resp_slice); |
103 | | - *resp_slice = cc_resp_slice.c_slice(); |
104 | | - |
105 | | - grpc::Slice test_slice(*resp_slice, grpc::Slice::ADD_REF); |
106 | | - pb::io::ArrayInputStream ais(test_slice.begin(), test_slice.size()); |
107 | | - pb::io::CodedInputStream cis(&ais); |
108 | | - |
109 | | - |
110 | | - cis.ReadTag(); |
111 | | - uint32_t id = 0; |
112 | | - if (!cis.ReadVarint32(&id)) { |
113 | | - std::cerr << "Failed to read id field\n"; |
114 | | - } |
115 | | - |
116 | | - return status_to_c(st.error_code()); |
117 | | - } |
118 | | - |
119 | | - void grpc_client_call_unary_callback(grpc_client_t *client, grpc_method_t *method, grpc_context_t *context, |
120 | | - grpc_byte_buffer **req_buf, grpc_byte_buffer **resp_buf, void* callback_context, void (*callback)(grpc_status_code_t,void*)) { |
121 | | - // the grpc::ByteBuffer representation is identical to (* grpc_byte_buffer) so we can safely cast it. |
122 | | - // so a **grpc_byte_buffer can be cast to *grpc::ByteBuffer. |
123 | | - static_assert(sizeof(grpc::ByteBuffer) == sizeof(grpc_byte_buffer*), |
124 | | - "ByteBuffer must have same representation as " |
125 | | - "grpc_byte_buffer*"); |
126 | | - const auto req_bb = reinterpret_cast<grpc::ByteBuffer *>(req_buf); |
127 | | - const auto resp_bb = reinterpret_cast<grpc::ByteBuffer *>(resp_buf); |
128 | | - grpc::internal::CallbackUnaryCall<grpc::ByteBuffer, grpc::ByteBuffer>(client->channel.get(), *method->method, context->context.get(), req_bb, resp_bb, [callback, callback_context](grpc::Status st) { |
129 | | - const auto c_st = status_to_c(st.error_code()); |
130 | | - callback(c_st, callback_context); |
131 | | - }); |
132 | | - } |
133 | | - |
134 | | - grpc_status_code_t status_to_c(grpc::StatusCode status) { |
135 | | - switch (status) { |
136 | | - case grpc::OK: |
137 | | - return GRPC_C_STATUS_OK; |
138 | | - case grpc::CANCELLED: |
139 | | - return GRPC_C_STATUS_CANCELLED; |
140 | | - case grpc::UNKNOWN: |
141 | | - return GRPC_C_STATUS_UNKNOWN; |
142 | | - case grpc::INVALID_ARGUMENT: |
143 | | - return GRPC_C_STATUS_INVALID_ARGUMENT; |
144 | | - case grpc::DEADLINE_EXCEEDED: |
145 | | - return GRPC_C_STATUS_DEADLINE_EXCEEDED; |
146 | | - case grpc::NOT_FOUND: |
147 | | - return GRPC_C_STATUS_NOT_FOUND; |
148 | | - case grpc::ALREADY_EXISTS: |
149 | | - return GRPC_C_STATUS_ALREADY_EXISTS; |
150 | | - case grpc::PERMISSION_DENIED: |
151 | | - return GRPC_C_STATUS_PERMISSION_DENIED; |
152 | | - case grpc::UNAUTHENTICATED: |
153 | | - return GRPC_C_STATUS_UNAUTHENTICATED; |
154 | | - case grpc::RESOURCE_EXHAUSTED: |
155 | | - return GRPC_C_STATUS_RESOURCE_EXHAUSTED; |
156 | | - case grpc::FAILED_PRECONDITION: |
157 | | - return GRPC_C_STATUS_FAILED_PRECONDITION; |
158 | | - case grpc::ABORTED: |
159 | | - return GRPC_C_STATUS_ABORTED; |
160 | | - case grpc::UNIMPLEMENTED: |
161 | | - return GRPC_C_STATUS_UNIMPLEMENTED; |
162 | | - case grpc::OUT_OF_RANGE: |
163 | | - return GRPC_C_STATUS_OUT_OF_RANGE; |
164 | | - case grpc::INTERNAL: |
165 | | - return GRPC_C_STATUS_INTERNAL; |
166 | | - case grpc::UNAVAILABLE: |
167 | | - return GRPC_C_STATUS_UNAVAILABLE; |
168 | | - case grpc::DATA_LOSS: |
169 | | - return GRPC_C_STATUS_DATA_LOSS; |
170 | | - case grpc::DO_NOT_USE: |
171 | | - return GRPC_C_STATUS_DO_NOT_USE; |
172 | | - } |
173 | | - } |
174 | | - |
175 | | - |
176 | | - uint32_t pb_decode_greeter_sayhello_response(grpc_slice response) { |
177 | | - grpc::Slice cc_resp_slice(response, grpc::Slice::ADD_REF); |
178 | | - pb::io::ArrayInputStream asi(cc_resp_slice.begin(), cc_resp_slice.size()); |
179 | | - pb::io::CodedInputStream cis(&asi); |
180 | | - |
181 | | - const auto tag = cis.ReadTag(); |
182 | | - if (tag != 8) { |
183 | | - std::cerr << "Failed to read tag. Got: " << tag << std::endl; |
184 | | - } |
185 | | - |
186 | | - uint32_t result; |
187 | | - if (!cis.ReadVarint32(&result)) { |
188 | | - std::cerr << "Failed to read result" << std::endl; |
189 | | - } else { |
190 | | - |
191 | | - } |
192 | | - return result; |
193 | | - } |
194 | | - |
195 | | - |
196 | | - grpc_status_code_t grpc_byte_buffer_dump_to_single_slice(grpc_byte_buffer *byte_buffer, grpc_slice *slice) { |
197 | | - auto bb = reinterpret_cast<grpc::ByteBuffer*>(&byte_buffer); |
198 | | - grpc::Slice cc_slice; |
199 | | - bb->DumpToSingleSlice(&cc_slice); |
200 | | - *slice = cc_slice.c_slice(); |
201 | | - return GRPC_C_STATUS_OK; |
202 | | - } |
203 | | - |
204 | | - |
205 | | - //// CHANNEL //// |
206 | | - |
207 | 11 | bool kgrpc_iomgr_run_in_background() { |
208 | 12 | return grpc_iomgr_run_in_background(); |
209 | 13 | } |
210 | 14 |
|
211 | | - |
212 | 15 | } |
213 | 16 |
|
214 | 17 |
|
0 commit comments