| /* |
| * |
| * Copyright 2018 gRPC authors. |
| * |
| * 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. |
| * |
| */ |
| |
| #include <grpc/support/port_platform.h> |
| |
| #include "src/core/tsi/local_transport_security.h" |
| |
| #include <stdio.h> |
| #include <stdlib.h> |
| #include <string.h> |
| |
| #include <grpc/support/alloc.h> |
| #include <grpc/support/log.h> |
| #include <grpc/support/string_util.h> |
| |
| #include "src/core/lib/iomgr/exec_ctx.h" |
| #include "src/core/tsi/transport_security_grpc.h" |
| |
| /* Main struct for local TSI zero-copy frame protector. */ |
| typedef struct local_zero_copy_grpc_protector { |
| tsi_zero_copy_grpc_protector base; |
| } local_zero_copy_grpc_protector; |
| |
| /* Main struct for local TSI handshaker result. */ |
| typedef struct local_tsi_handshaker_result { |
| tsi_handshaker_result base; |
| bool is_client; |
| } local_tsi_handshaker_result; |
| |
| /* Main struct for local TSI handshaker. */ |
| typedef struct local_tsi_handshaker { |
| tsi_handshaker base; |
| bool is_client; |
| } local_tsi_handshaker; |
| |
| /* --- tsi_zero_copy_grpc_protector methods implementation. --- */ |
| |
| static tsi_result local_zero_copy_grpc_protector_protect( |
| tsi_zero_copy_grpc_protector* self, grpc_slice_buffer* unprotected_slices, |
| grpc_slice_buffer* protected_slices) { |
| if (self == nullptr || unprotected_slices == nullptr || |
| protected_slices == nullptr) { |
| gpr_log(GPR_ERROR, "Invalid nullptr arguments to zero-copy grpc protect."); |
| return TSI_INVALID_ARGUMENT; |
| } |
| grpc_slice_buffer_move_into(unprotected_slices, protected_slices); |
| return TSI_OK; |
| } |
| |
| static tsi_result local_zero_copy_grpc_protector_unprotect( |
| tsi_zero_copy_grpc_protector* self, grpc_slice_buffer* protected_slices, |
| grpc_slice_buffer* unprotected_slices) { |
| if (self == nullptr || unprotected_slices == nullptr || |
| protected_slices == nullptr) { |
| gpr_log(GPR_ERROR, |
| "Invalid nullptr arguments to zero-copy grpc unprotect."); |
| return TSI_INVALID_ARGUMENT; |
| } |
| grpc_slice_buffer_move_into(protected_slices, unprotected_slices); |
| return TSI_OK; |
| } |
| |
| static void local_zero_copy_grpc_protector_destroy( |
| tsi_zero_copy_grpc_protector* self) { |
| gpr_free(self); |
| } |
| |
| static const tsi_zero_copy_grpc_protector_vtable |
| local_zero_copy_grpc_protector_vtable = { |
| local_zero_copy_grpc_protector_protect, |
| local_zero_copy_grpc_protector_unprotect, |
| local_zero_copy_grpc_protector_destroy}; |
| |
| tsi_result local_zero_copy_grpc_protector_create( |
| tsi_zero_copy_grpc_protector** protector) { |
| if (grpc_core::ExecCtx::Get() == nullptr || protector == nullptr) { |
| gpr_log( |
| GPR_ERROR, |
| "Invalid nullptr arguments to local_zero_copy_grpc_protector create."); |
| return TSI_INVALID_ARGUMENT; |
| } |
| local_zero_copy_grpc_protector* impl = |
| static_cast<local_zero_copy_grpc_protector*>(gpr_zalloc(sizeof(*impl))); |
| impl->base.vtable = &local_zero_copy_grpc_protector_vtable; |
| *protector = &impl->base; |
| return TSI_OK; |
| } |
| |
| /* --- tsi_handshaker_result methods implementation. --- */ |
| |
| static tsi_result handshaker_result_extract_peer( |
| const tsi_handshaker_result* self, tsi_peer* peer) { |
| return TSI_OK; |
| } |
| |
| static tsi_result handshaker_result_create_zero_copy_grpc_protector( |
| const tsi_handshaker_result* self, size_t* max_output_protected_frame_size, |
| tsi_zero_copy_grpc_protector** protector) { |
| if (self == nullptr || protector == nullptr) { |
| gpr_log(GPR_ERROR, |
| "Invalid arguments to create_zero_copy_grpc_protector()"); |
| return TSI_INVALID_ARGUMENT; |
| } |
| tsi_result ok = local_zero_copy_grpc_protector_create(protector); |
| if (ok != TSI_OK) { |
| gpr_log(GPR_ERROR, "Failed to create zero-copy grpc protector"); |
| } |
| return ok; |
| } |
| |
| static void handshaker_result_destroy(tsi_handshaker_result* self) { |
| if (self == nullptr) { |
| return; |
| } |
| local_tsi_handshaker_result* result = |
| reinterpret_cast<local_tsi_handshaker_result*>( |
| const_cast<tsi_handshaker_result*>(self)); |
| gpr_free(result); |
| } |
| |
| static const tsi_handshaker_result_vtable result_vtable = { |
| handshaker_result_extract_peer, |
| handshaker_result_create_zero_copy_grpc_protector, |
| nullptr, /* handshaker_result_create_frame_protector */ |
| nullptr, /* handshaker_result_get_unused_bytes */ |
| handshaker_result_destroy}; |
| |
| static tsi_result create_handshaker_result(bool is_client, |
| tsi_handshaker_result** self) { |
| if (self == nullptr) { |
| gpr_log(GPR_ERROR, "Invalid arguments to create_handshaker_result()"); |
| return TSI_INVALID_ARGUMENT; |
| } |
| local_tsi_handshaker_result* result = |
| static_cast<local_tsi_handshaker_result*>(gpr_zalloc(sizeof(*result))); |
| result->is_client = is_client; |
| result->base.vtable = &result_vtable; |
| *self = &result->base; |
| return TSI_OK; |
| } |
| |
| /* --- tsi_handshaker methods implementation. --- */ |
| |
| static tsi_result handshaker_next( |
| tsi_handshaker* self, const unsigned char* received_bytes, |
| size_t received_bytes_size, const unsigned char** bytes_to_send, |
| size_t* bytes_to_send_size, tsi_handshaker_result** result, |
| tsi_handshaker_on_next_done_cb cb, void* user_data) { |
| if (self == nullptr) { |
| gpr_log(GPR_ERROR, "Invalid arguments to handshaker_next()"); |
| return TSI_INVALID_ARGUMENT; |
| } |
| /* Note that there is no interaction between TSI peers, and all operations are |
| * local. |
| */ |
| local_tsi_handshaker* handshaker = |
| reinterpret_cast<local_tsi_handshaker*>(self); |
| *bytes_to_send_size = 0; |
| create_handshaker_result(handshaker->is_client, result); |
| return TSI_OK; |
| } |
| |
| static void handshaker_destroy(tsi_handshaker* self) { |
| if (self == nullptr) { |
| return; |
| } |
| local_tsi_handshaker* handshaker = |
| reinterpret_cast<local_tsi_handshaker*>(self); |
| gpr_free(handshaker); |
| } |
| |
| static const tsi_handshaker_vtable handshaker_vtable = { |
| nullptr, /* get_bytes_to_send_to_peer -- deprecated */ |
| nullptr, /* process_bytes_from_peer -- deprecated */ |
| nullptr, /* get_result -- deprecated */ |
| nullptr, /* extract_peer -- deprecated */ |
| nullptr, /* create_frame_protector -- deprecated */ |
| handshaker_destroy, |
| handshaker_next, |
| nullptr, /* shutdown */ |
| }; |
| |
| tsi_result local_tsi_handshaker_create(bool is_client, tsi_handshaker** self) { |
| if (self == nullptr) { |
| gpr_log(GPR_ERROR, "Invalid arguments to local_tsi_handshaker_create()"); |
| return TSI_INVALID_ARGUMENT; |
| } |
| local_tsi_handshaker* handshaker = |
| static_cast<local_tsi_handshaker*>(gpr_zalloc(sizeof(*handshaker))); |
| handshaker->is_client = is_client; |
| handshaker->base.vtable = &handshaker_vtable; |
| *self = &handshaker->base; |
| return TSI_OK; |
| } |