1 /* 2 * 3 * Copyright 2015 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 <grpc/support/port_platform.h> 20 21 #include <string.h> 22 23 #include <grpc/support/alloc.h> 24 #include <grpc/support/string_util.h> 25 26 #include "src/core/lib/channel/channel_args.h" 27 28 #include "src/core/ext/filters/client_channel/lb_policy_factory.h" 29 #include "src/core/ext/filters/client_channel/parse_address.h" 30 31 grpc_lb_addresses* grpc_lb_addresses_create( 32 size_t num_addresses, const grpc_lb_user_data_vtable* user_data_vtable) { 33 grpc_lb_addresses* addresses = 34 static_cast<grpc_lb_addresses*>(gpr_zalloc(sizeof(grpc_lb_addresses))); 35 addresses->num_addresses = num_addresses; 36 addresses->user_data_vtable = user_data_vtable; 37 const size_t addresses_size = sizeof(grpc_lb_address) * num_addresses; 38 addresses->addresses = 39 static_cast<grpc_lb_address*>(gpr_zalloc(addresses_size)); 40 return addresses; 41 } 42 43 grpc_lb_addresses* grpc_lb_addresses_copy(const grpc_lb_addresses* addresses) { 44 grpc_lb_addresses* new_addresses = grpc_lb_addresses_create( 45 addresses->num_addresses, addresses->user_data_vtable); 46 memcpy(new_addresses->addresses, addresses->addresses, 47 sizeof(grpc_lb_address) * addresses->num_addresses); 48 for (size_t i = 0; i < addresses->num_addresses; ++i) { 49 if (new_addresses->addresses[i].balancer_name != nullptr) { 50 new_addresses->addresses[i].balancer_name = 51 gpr_strdup(new_addresses->addresses[i].balancer_name); 52 } 53 if (new_addresses->addresses[i].user_data != nullptr) { 54 new_addresses->addresses[i].user_data = addresses->user_data_vtable->copy( 55 new_addresses->addresses[i].user_data); 56 } 57 } 58 return new_addresses; 59 } 60 61 void grpc_lb_addresses_set_address(grpc_lb_addresses* addresses, size_t index, 62 const void* address, size_t address_len, 63 bool is_balancer, const char* balancer_name, 64 void* user_data) { 65 GPR_ASSERT(index < addresses->num_addresses); 66 if (user_data != nullptr) GPR_ASSERT(addresses->user_data_vtable != nullptr); 67 grpc_lb_address* target = &addresses->addresses[index]; 68 memcpy(target->address.addr, address, address_len); 69 target->address.len = static_cast<socklen_t>(address_len); 70 target->is_balancer = is_balancer; 71 target->balancer_name = gpr_strdup(balancer_name); 72 target->user_data = user_data; 73 } 74 75 bool grpc_lb_addresses_set_address_from_uri(grpc_lb_addresses* addresses, 76 size_t index, const grpc_uri* uri, 77 bool is_balancer, 78 const char* balancer_name, 79 void* user_data) { 80 grpc_resolved_address address; 81 if (!grpc_parse_uri(uri, &address)) return false; 82 grpc_lb_addresses_set_address(addresses, index, address.addr, address.len, 83 is_balancer, balancer_name, user_data); 84 return true; 85 } 86 87 int grpc_lb_addresses_cmp(const grpc_lb_addresses* addresses1, 88 const grpc_lb_addresses* addresses2) { 89 if (addresses1->num_addresses > addresses2->num_addresses) return 1; 90 if (addresses1->num_addresses < addresses2->num_addresses) return -1; 91 if (addresses1->user_data_vtable > addresses2->user_data_vtable) return 1; 92 if (addresses1->user_data_vtable < addresses2->user_data_vtable) return -1; 93 for (size_t i = 0; i < addresses1->num_addresses; ++i) { 94 const grpc_lb_address* target1 = &addresses1->addresses[i]; 95 const grpc_lb_address* target2 = &addresses2->addresses[i]; 96 if (target1->address.len > target2->address.len) return 1; 97 if (target1->address.len < target2->address.len) return -1; 98 int retval = memcmp(target1->address.addr, target2->address.addr, 99 target1->address.len); 100 if (retval != 0) return retval; 101 if (target1->is_balancer > target2->is_balancer) return 1; 102 if (target1->is_balancer < target2->is_balancer) return -1; 103 const char* balancer_name1 = 104 target1->balancer_name != nullptr ? target1->balancer_name : ""; 105 const char* balancer_name2 = 106 target2->balancer_name != nullptr ? target2->balancer_name : ""; 107 retval = strcmp(balancer_name1, balancer_name2); 108 if (retval != 0) return retval; 109 if (addresses1->user_data_vtable != nullptr) { 110 retval = addresses1->user_data_vtable->cmp(target1->user_data, 111 target2->user_data); 112 if (retval != 0) return retval; 113 } 114 } 115 return 0; 116 } 117 118 void grpc_lb_addresses_destroy(grpc_lb_addresses* addresses) { 119 for (size_t i = 0; i < addresses->num_addresses; ++i) { 120 gpr_free(addresses->addresses[i].balancer_name); 121 if (addresses->addresses[i].user_data != nullptr) { 122 addresses->user_data_vtable->destroy(addresses->addresses[i].user_data); 123 } 124 } 125 gpr_free(addresses->addresses); 126 gpr_free(addresses); 127 } 128 129 static void* lb_addresses_copy(void* addresses) { 130 return grpc_lb_addresses_copy(static_cast<grpc_lb_addresses*>(addresses)); 131 } 132 static void lb_addresses_destroy(void* addresses) { 133 grpc_lb_addresses_destroy(static_cast<grpc_lb_addresses*>(addresses)); 134 } 135 static int lb_addresses_cmp(void* addresses1, void* addresses2) { 136 return grpc_lb_addresses_cmp(static_cast<grpc_lb_addresses*>(addresses1), 137 static_cast<grpc_lb_addresses*>(addresses2)); 138 } 139 static const grpc_arg_pointer_vtable lb_addresses_arg_vtable = { 140 lb_addresses_copy, lb_addresses_destroy, lb_addresses_cmp}; 141 142 grpc_arg grpc_lb_addresses_create_channel_arg( 143 const grpc_lb_addresses* addresses) { 144 return grpc_channel_arg_pointer_create( 145 (char*)GRPC_ARG_LB_ADDRESSES, (void*)addresses, &lb_addresses_arg_vtable); 146 } 147 148 grpc_lb_addresses* grpc_lb_addresses_find_channel_arg( 149 const grpc_channel_args* channel_args) { 150 const grpc_arg* lb_addresses_arg = 151 grpc_channel_args_find(channel_args, GRPC_ARG_LB_ADDRESSES); 152 if (lb_addresses_arg == nullptr || lb_addresses_arg->type != GRPC_ARG_POINTER) 153 return nullptr; 154 return static_cast<grpc_lb_addresses*>(lb_addresses_arg->value.pointer.p); 155 } 156 157 bool grpc_lb_addresses_contains_balancer_address( 158 const grpc_lb_addresses& addresses) { 159 for (size_t i = 0; i < addresses.num_addresses; ++i) { 160 if (addresses.addresses[i].is_balancer) return true; 161 } 162 return false; 163 } 164