1 | /* |
2 | * endpoint.h |
3 | * |
4 | * Copyright (C) 2016 Aerospike, Inc. |
5 | * |
6 | * Portions may be licensed to Aerospike, Inc. under one or more contributor |
7 | * license agreements. |
8 | * |
9 | * This program is free software: you can redistribute it and/or modify it under |
10 | * the terms of the GNU Affero General Public License as published by the Free |
11 | * Software Foundation, either version 3 of the License, or (at your option) any |
12 | * later version. |
13 | * |
14 | * This program is distributed in the hope that it will be useful, but WITHOUT |
15 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS |
16 | * FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more |
17 | * details. |
18 | * |
19 | * You should have received a copy of the GNU Affero General Public License |
20 | * along with this program. If not, see http://www.gnu.org/licenses/ |
21 | */ |
22 | |
23 | /* |
24 | * Overview |
25 | * ======== |
26 | * |
27 | * An endpoint captures all information needed by a peer node to establish a |
28 | * connection to a service (e.g. fabric or heartbeat). The key difference |
29 | * between an endpoint and socket API's cf_sock_cfg, is that cf_sock_cfg captures |
30 | * all information needed by a service to start a server socket and accept |
31 | * connections on it, whereas an endpoint captures all information a peer needs |
32 | * to connect to the service. These two complementary structures overlap in |
33 | * information content, however cf_sock_cfg will carry server side configuration |
34 | * values (e.g. TLS configuration), which are irrelevant for the client using |
35 | * this service. Also an endpoint structure is oriented to be advertised over |
36 | * the wire. |
37 | */ |
38 | |
39 | #pragma once |
40 | |
41 | #include <stdbool.h> |
42 | #include <stddef.h> |
43 | #include <stdint.h> |
44 | |
45 | #include "socket.h" |
46 | |
47 | /** |
48 | * Indicates if this endpoint supports TLS. |
49 | */ |
50 | #define AS_ENDPOINT_TLS_MASK 0x01 |
51 | |
52 | /** |
53 | * Endpoint address type. |
54 | */ |
55 | typedef enum |
56 | { |
57 | /** |
58 | * Undefined address type. |
59 | */ |
60 | AS_ENDPOINT_ADDR_TYPE_UNDEF, |
61 | /** |
62 | * IPv4 address. |
63 | */ |
64 | AS_ENDPOINT_ADDR_TYPE_IPv4, |
65 | /** |
66 | * IPv6 address. |
67 | */ |
68 | AS_ENDPOINT_ADDR_TYPE_IPv6, |
69 | /** |
70 | * Sentinel value. |
71 | */ |
72 | AS_ENDPOINT_ADDR_TYPE_SENTINEL |
73 | } as_endpoint_addr_type; |
74 | |
75 | /** |
76 | * An endpoint definition. |
77 | */ |
78 | typedef struct as_endpoint_s |
79 | { |
80 | /** |
81 | * Bit field of capabilities. currently carries only tls enabled flag. |
82 | */ |
83 | uint8_t capabilities; |
84 | |
85 | /** |
86 | * The type of the address. |
87 | */ |
88 | uint8_t addr_type; |
89 | |
90 | /** |
91 | * The endpoint port. |
92 | */ |
93 | uint16_t port; |
94 | |
95 | /** |
96 | * The network formatted and ordered IPv4 / IPv6 address (or string if |
97 | * we decide to support dns names). The size of this field depends on |
98 | * the address type. |
99 | */ |
100 | uint8_t addr[]; |
101 | }__attribute__((__packed__)) as_endpoint; |
102 | |
103 | /** |
104 | * A list of endpoints. |
105 | */ |
106 | typedef struct as_endpoint_list_s |
107 | { |
108 | /** |
109 | * The number of endpoints contained in the list. Max of 255. |
110 | */ |
111 | uint8_t n_endpoints; |
112 | |
113 | /** |
114 | * The list of endpoints. |
115 | */ |
116 | as_endpoint endpoints[]; |
117 | }__attribute__((__packed__)) as_endpoint_list; |
118 | |
119 | /** |
120 | * Iterate function for iterating over endpoints in an endpoint list. |
121 | * @param endpoint current endpoint in the iteration. |
122 | * @param udata udata passed through from the invoker of the iterate function. |
123 | */ |
124 | typedef void |
125 | (*as_endpoint_iterate_fn)(const as_endpoint* endpoint, void* udata); |
126 | |
127 | /** |
128 | * Filter function for an endpoints in an endpoint list. |
129 | * @param endpoint current endpoint in the iteration. |
130 | * @param udata udata passed through from the invoker of the filter function. |
131 | * @return should return true if this endpoint passes the filter, false if it |
132 | * fails the filter. |
133 | */ |
134 | typedef bool |
135 | (*as_endpoint_filter_fn)(const as_endpoint* endpoint, void* udata); |
136 | |
137 | /** |
138 | * Get the sizeof an endpoint. Accounts for variable size of the address field. |
139 | * @return the size of the endpoint address. Zero if the endpoint address is |
140 | * invalid. |
141 | */ |
142 | size_t |
143 | as_endpoint_sizeof(const as_endpoint* endpoint); |
144 | |
145 | /** |
146 | * Enable a capability on an endpoint given its mask. |
147 | * @param endpoint the endpoint. |
148 | * @param capability_mask the capability mask. |
149 | */ |
150 | void |
151 | as_endpoint_capability_enable(as_endpoint* endpoint, uint8_t capability_mask); |
152 | |
153 | /** |
154 | * Disable a capability on an endpoint given its mask. |
155 | * @param endpoint the endpoint. |
156 | * @param capability_mask the capability mask. |
157 | */ |
158 | void |
159 | as_endpoint_capability_disable(as_endpoint* endpoint, uint8_t capability_mask); |
160 | |
161 | /** |
162 | * Connect to an endpoint. |
163 | * |
164 | * @param endpoint the peer endpoint to connect to. |
165 | * @param owner the socket owner module. |
166 | * @param timeout the overall connect timeout. |
167 | * @param sock (output) will be populated if connections is successful. |
168 | * @return -1 on success, 0 on failure. |
169 | */ |
170 | int |
171 | as_endpoint_connect(const as_endpoint* endpoint, int32_t timeout, cf_socket* sock); |
172 | |
173 | /** |
174 | * Connect to the best matching endpoint in the endpoint list. |
175 | * |
176 | * @param endpoint_list the list of endpoints. |
177 | * @param filter_fn filter function to discard incompatible endpoints. Can be |
178 | * NULL. |
179 | * @param filter_udata udata passed on as is to the filter function. |
180 | * @param timeout the overall connect timeout. |
181 | * @param sock (output) will be populated if connection is successful. |
182 | * @return the connected endpoint on success, NULL if no endpoint count be |
183 | * connected. |
184 | */ |
185 | const as_endpoint* |
186 | as_endpoint_connect_any(const as_endpoint_list* endpoint_list, |
187 | as_endpoint_filter_fn filter_fn, void* filter_udata, int32_t timeout, cf_socket* sock); |
188 | /** |
189 | * Convert a socket configuration to an endpoint inplace. |
190 | * @return a heap allocated, converted endpoint. Should be freed using cf_free |
191 | * once the endpoint is no longer needed. |
192 | */ |
193 | void |
194 | as_endpoint_from_sock_cfg_fill(const cf_sock_cfg* src, as_endpoint* endpoint); |
195 | |
196 | /** |
197 | * Convert a socket configuration to an endpoint. |
198 | * @return a heap allocated, converted endpoint. Should be freed using cf_free |
199 | * once the endpoint is no longer needed. |
200 | */ |
201 | as_endpoint* |
202 | as_endpoint_from_sock_cfg(const cf_sock_cfg* src); |
203 | |
204 | /** |
205 | * Convert an endpoint to a cf_sock_addr. |
206 | * @param endpoint the source endpoint. |
207 | * @param sock_addr the target socket address. |
208 | */ |
209 | int |
210 | as_endpoint_to_sock_addr(const as_endpoint* endpoint, cf_sock_addr* sock_addr); |
211 | |
212 | /** |
213 | * Indicates if an endpoint supports listed capabilities. |
214 | * @return true if the endpoint supports the input capability. |
215 | */ |
216 | bool |
217 | as_endpoint_capability_is_supported(const as_endpoint* endpoint, uint8_t capability_mask); |
218 | |
219 | /** |
220 | * Iterate over endpoints in an endpoint list and invoke the iterate function |
221 | * for each endpoint. |
222 | * @param iterate_fn the iterate function invoked for each endpoint in the list. |
223 | * @param udata passed as is to the iterate function. Useful for getting results |
224 | * out of the iteration. |
225 | * NULL if there is no plugin data. |
226 | * @return the size of the plugin data. 0 if there is no plugin data. |
227 | */ |
228 | void |
229 | as_endpoint_list_iterate(const as_endpoint_list* endpoint_list, as_endpoint_iterate_fn iterate_fn, |
230 | void* udata); |
231 | |
232 | /** |
233 | * Return the in memory size in bytes of the endpoint list. |
234 | * @param endpoint_list the endpoint list. |
235 | * @param size (output) the size of the list on success. |
236 | * @return 0 on successful size calculation, -1 otherwise. |
237 | */ |
238 | int |
239 | as_endpoint_list_sizeof(const as_endpoint_list* endpoint_list, size_t* size); |
240 | |
241 | /** |
242 | * Return the in memory size in bytes of the endpoint list, but abort if the |
243 | * size of the read exceeds the input size. |
244 | * @param endpoint_list the endpoint list. |
245 | * @param size (output) the size of the list on success. |
246 | * @param size_max the maximum size until which parsing will be attempted. |
247 | * @return 0 on successful size calculation, -1 otherwise. |
248 | */ |
249 | int |
250 | as_endpoint_list_nsizeof(const as_endpoint_list* endpoint_list, size_t* size, size_t size_max); |
251 | |
252 | /** |
253 | * Convert a server configuration to an endpoint list in place into the |
254 | * destination endpoint list. |
255 | * @param serv_cfg source server configuration. |
256 | * @param endpoint_list destination endpoint list. |
257 | */ |
258 | void |
259 | as_endpoint_list_from_serv_cfg_fill(const cf_serv_cfg* serv_cfg, as_endpoint_list* endpoint_list); |
260 | |
261 | /** |
262 | * Convert a server configuration to an endpoint list. |
263 | * @param serv_cfg server configuration. |
264 | * @return a heap allocated endpoint list. Should be freed using cf_free |
265 | * once the endpoint is no longer needed. |
266 | */ |
267 | as_endpoint_list* |
268 | as_endpoint_list_from_serv_cfg(const cf_serv_cfg* serv_cfg); |
269 | |
270 | /** |
271 | * Compare two endpoint lists for equality. |
272 | * @param list1 the first. NULL allowed. |
273 | * @param list2 the second list. NULL allowed. |
274 | * @return true iff the lists are equals, false otherwise. |
275 | */ |
276 | bool |
277 | as_endpoint_lists_are_equal(const as_endpoint_list* list1, const as_endpoint_list* list2); |
278 | |
279 | /** |
280 | * Check if two lists overlap in at least one endpoint. |
281 | * @param list1 the first. NULL allowed. |
282 | * @param list2 the second list. NULL allowed. |
283 | * @param ignore_capabilities set to true if the overlap match should ignore |
284 | * node capabilities, false if capabilities should also be matched. |
285 | * @return true iff the lists are overlap, false otherwise. |
286 | */ |
287 | bool |
288 | as_endpoint_lists_are_overlapping(const as_endpoint_list* list1, const as_endpoint_list* list2, |
289 | bool ignore_capabilities); |
290 | |
291 | /** |
292 | * Convert an endpoint list to a string. |
293 | * @param endpoint_list the input list. NULL allowed. |
294 | * @param buffer the output buffer. |
295 | * @buffer_capacity the capacity of the output buffer. |
296 | * @return the number of characters printed (excluding the null byte used to |
297 | end output to strings) |
298 | */ |
299 | int |
300 | as_endpoint_list_to_string(const as_endpoint_list* endpoint_list, char* buffer, |
301 | size_t buffer_capacity); |
302 | |
303 | /** |
304 | * Convert an endpoint list to a string matching capabilities. |
305 | * @param endpoint_list the input list. NULL allowed. |
306 | * @param buffer the output buffer. |
307 | * @param buffer_capacity the capacity of the output buffer. |
308 | * @param capability_mask specifies which bit to match. |
309 | * @param capabilities specifies capabilities to be match for. |
310 | * @return the number of characters printed (excluding the null byte used to |
311 | * end output to strings) |
312 | */ |
313 | int |
314 | as_endpoint_list_to_string_match_capabilities( |
315 | const as_endpoint_list* endpoint_list, char* buffer, |
316 | size_t buffer_capacity, uint8_t capability_mask, uint8_t capabilities); |
317 | |
318 | /** |
319 | * Populate dyn buf with endpoints info. |
320 | * @param endpoint_list the input list. NULL allowed. |
321 | * @param db the dynamic buffer. |
322 | */ |
323 | void |
324 | as_endpoint_list_info(const as_endpoint_list* endpoint_list, cf_dyn_buf* db); |
325 | |