|
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