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 */
55typedef 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 */
78typedef 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 */
106typedef 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 */
124typedef 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 */
134typedef 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 */
142size_t
143as_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 */
150void
151as_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 */
158void
159as_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 */
170int
171as_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 */
185const as_endpoint*
186as_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 */
193void
194as_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 */
201as_endpoint*
202as_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 */
209int
210as_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 */
216bool
217as_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 */
228void
229as_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 */
238int
239as_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 */
249int
250as_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 */
258void
259as_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 */
267as_endpoint_list*
268as_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 */
276bool
277as_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 */
287bool
288as_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 */
299int
300as_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 */
313int
314as_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 */
323void
324as_endpoint_list_info(const as_endpoint_list* endpoint_list, cf_dyn_buf* db);
325