1 /*
2 *
3 * Copyright 2021 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 <ruby/ruby.h>
20
21 #include "rb_xds_server_credentials.h"
22
23 #include "rb_grpc.h"
24 #include "rb_grpc_imports.generated.h"
25 #include "rb_server_credentials.h"
26
27 #include <grpc/grpc.h>
28 #include <grpc/grpc_security.h>
29 #include <grpc/support/log.h>
30
31 /* grpc_rb_cXdsServerCredentials is the ruby class that proxies
32 grpc_server_credentials. */
33 static VALUE grpc_rb_cXdsServerCredentials = Qnil;
34
35 /* grpc_rb_xds_server_credentials wraps a grpc_server_credentials. It provides
36 a peer ruby object, 'mark' to hold references to objects involved in
37 constructing the server credentials. */
38 typedef struct grpc_rb_xds_server_credentials {
39 /* Holder of ruby objects involved in constructing the server credentials */
40 VALUE mark;
41 /* The actual server credentials */
42 grpc_server_credentials* wrapped;
43 } grpc_rb_xds_server_credentials;
44
45 /* Destroys the server credentials instances. */
grpc_rb_xds_server_credentials_free_internal(void * p)46 static void grpc_rb_xds_server_credentials_free_internal(void* p) {
47 grpc_rb_xds_server_credentials* wrapper = NULL;
48 if (p == NULL) {
49 return;
50 };
51 wrapper = (grpc_rb_xds_server_credentials*)p;
52
53 /* Delete the wrapped object if the mark object is Qnil, which indicates that
54 no other object is the actual owner. */
55 if (wrapper->wrapped != NULL && wrapper->mark == Qnil) {
56 grpc_server_credentials_release(wrapper->wrapped);
57 wrapper->wrapped = NULL;
58 }
59
60 xfree(p);
61 }
62
63 /* Destroys the server credentials instances. */
grpc_rb_xds_server_credentials_free(void * p)64 static void grpc_rb_xds_server_credentials_free(void* p) {
65 grpc_rb_xds_server_credentials_free_internal(p);
66 }
67
68 /* Protects the mark object from GC */
grpc_rb_xds_server_credentials_mark(void * p)69 static void grpc_rb_xds_server_credentials_mark(void* p) {
70 if (p == NULL) {
71 return;
72 }
73 grpc_rb_xds_server_credentials* wrapper = (grpc_rb_xds_server_credentials*)p;
74
75 /* If it's not already cleaned up, mark the mark object */
76 if (wrapper->mark != Qnil) {
77 rb_gc_mark(wrapper->mark);
78 }
79 }
80
81 static const rb_data_type_t grpc_rb_xds_server_credentials_data_type = {
82 "grpc_xds_server_credentials",
83 {grpc_rb_xds_server_credentials_mark, grpc_rb_xds_server_credentials_free,
84 GRPC_RB_MEMSIZE_UNAVAILABLE, NULL},
85 NULL,
86 NULL,
87 #ifdef RUBY_TYPED_FREE_IMMEDIATELY
88 RUBY_TYPED_FREE_IMMEDIATELY
89 #endif
90 };
91
92 /* Allocates ServerCredential instances.
93 Provides safe initial defaults for the instance fields. */
grpc_rb_xds_server_credentials_alloc(VALUE cls)94 static VALUE grpc_rb_xds_server_credentials_alloc(VALUE cls) {
95 grpc_ruby_init();
96 grpc_rb_xds_server_credentials* wrapper =
97 ALLOC(grpc_rb_xds_server_credentials);
98 wrapper->wrapped = NULL;
99 wrapper->mark = Qnil;
100 return TypedData_Wrap_Struct(cls, &grpc_rb_xds_server_credentials_data_type,
101 wrapper);
102 }
103
104 /* The attribute used on the mark object to preserve the fallback_creds. */
105 static ID id_fallback_creds;
106
107 /*
108 call-seq:
109 creds = ServerCredentials.new(fallback_creds)
110 fallback_creds: (ServerCredentials) fallback credentials to create
111 XDS credentials.
112 Initializes ServerCredential instances. */
grpc_rb_xds_server_credentials_init(VALUE self,VALUE fallback_creds)113 static VALUE grpc_rb_xds_server_credentials_init(VALUE self,
114 VALUE fallback_creds) {
115 grpc_rb_xds_server_credentials* wrapper = NULL;
116 grpc_server_credentials* creds = NULL;
117
118 grpc_server_credentials* grpc_fallback_creds =
119 grpc_rb_get_wrapped_server_credentials(fallback_creds);
120 creds = grpc_xds_server_credentials_create(grpc_fallback_creds);
121
122 if (creds == NULL) {
123 rb_raise(rb_eRuntimeError,
124 "the call to grpc_xds_server_credentials_create() failed, could "
125 "not create a credentials, see "
126 "https://github.com/grpc/grpc/blob/master/TROUBLESHOOTING.md for "
127 "debugging tips");
128 return Qnil;
129 }
130 TypedData_Get_Struct(self, grpc_rb_xds_server_credentials,
131 &grpc_rb_xds_server_credentials_data_type, wrapper);
132 wrapper->wrapped = creds;
133
134 /* Add the input objects as hidden fields to preserve them. */
135 rb_ivar_set(self, id_fallback_creds, fallback_creds);
136
137 return self;
138 }
139
Init_grpc_xds_server_credentials()140 void Init_grpc_xds_server_credentials() {
141 grpc_rb_cXdsServerCredentials = rb_define_class_under(
142 grpc_rb_mGrpcCore, "XdsServerCredentials", rb_cObject);
143
144 /* Allocates an object managed by the ruby runtime */
145 rb_define_alloc_func(grpc_rb_cXdsServerCredentials,
146 grpc_rb_xds_server_credentials_alloc);
147
148 /* Provides a ruby constructor and support for dup/clone. */
149 rb_define_method(grpc_rb_cXdsServerCredentials, "initialize",
150 grpc_rb_xds_server_credentials_init, 1);
151 rb_define_method(grpc_rb_cXdsServerCredentials, "initialize_copy",
152 grpc_rb_cannot_init_copy, 1);
153
154 id_fallback_creds = rb_intern("__fallback_creds");
155 }
156
157 /* Gets the wrapped grpc_server_credentials from the ruby wrapper */
grpc_rb_get_wrapped_xds_server_credentials(VALUE v)158 grpc_server_credentials* grpc_rb_get_wrapped_xds_server_credentials(VALUE v) {
159 grpc_rb_xds_server_credentials* wrapper = NULL;
160 Check_TypedStruct(v, &grpc_rb_xds_server_credentials_data_type);
161 TypedData_Get_Struct(v, grpc_rb_xds_server_credentials,
162 &grpc_rb_xds_server_credentials_data_type, wrapper);
163 return wrapper->wrapped;
164 }
165
166 /* Check if v is kind of ServerCredentials */
grpc_rb_is_xds_server_credentials(VALUE v)167 bool grpc_rb_is_xds_server_credentials(VALUE v) {
168 return rb_typeddata_is_kind_of(v, &grpc_rb_xds_server_credentials_data_type);
169 }
170