forked from bloomberg/comdb2
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathportmuxapi.h
393 lines (353 loc) · 13.7 KB
/
portmuxapi.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
/*
Copyright 2015 Bloomberg Finance L.P.
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.
*/
#ifndef INCLUDED_PORTMUXAPI
#define INCLUDED_PORTMUXAPI
/* register/get port through portmux
example:
app=comdb2
service=replication
instance=secdb
For full background, FAQs and api recommendations, see
{TEAM SYSI:PORTMUX<go>}.
*/
#include <sys/types.h>
#include <netinet/in.h>
#if defined __cplusplus
extern "C" {
#endif
typedef enum {
PORTMUX_PORT_SUPPRESS = 1 /* Do not allocate a portmux port for this
connection (in 1 port mode) */
} portmux_options_t;
/* ***
* The following calls are wrappers to make portmux usage easier.
* They give ability to do TCP connect//listen with a port returned
* by portmux.
* Underneath they use tcputil.h wrappers.
* It is recommended to use other calls from tcplib to do read//write.
* *** */
/**
* @brief Registers with portmux then starts listening for connections.
* It will call accept_hndl() with received connection fd.
*
* @param[in] app Application to register.
* @param[in] service Service to register.
* @param[in] instance Instance to register.
* @param[in] accept_hndl Handler to call on connection.
* It is responsability of this
* callback to do close(fd).
*
* @return -1 for error before accepting connection.
* Will block otherwise
*
* @example:
* static pthread_attr_t attr;
* void client_thr(int fd)
* {
* printf("yeah, got a friend on fd# %d\n", fd);
* close(fd);
* }
*
*
* void accept_hndl(int fd, void *user_data)
* {
* pthread_t tid;
* int rc;
*
* // ok, spawn a client thread and go wait for somebody else
* rc = pthread_create(&tid, &attr,
* (void*(*)(void*))client_thr, (void*)fd);
* if (rc) {
* fprintf(stderr, "accept_hndl:pthread_create(): errno=[%d] %s\n",
* rc, strerror(rc));
* close(fd); // close fd
* }
* }
*
*
* int main(int argc, char *argv[])
* {
* // initialize attribute for client threads
* Pthread_attr_init(&attr);
* pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
*
* // alright wait for client
* portmux_listen("comdb2", "replication", "dbtest", accept_hndl, NULL);
* fprintf(stderr, "portmux_listen: errno=[%d] %s\n",
* errno, strerror(errno));
* exit(1);
* }
*/
int portmux_listen(const char *app, const char *service, const char *instance,
void (*accept_hndl)(int fd, void *user_data),
void *user_data);
int portmux_listen_options(const char *app, const char *service,
const char *instance,
void (*accept_hndl)(int fd, void *user_data),
void *user_data, uint32_t options);
/** If you dont want to use portmux_listen() (due to callback
* mechanism or any other reason). You can use the following 3 calls
* (portmux_listen, simply wraps them):
*
* 1. portmux_listen_setup() to create a portmux_fd_t
* 2. call portmux_accept() to retrieve 1 connection. This is a
* blocking call.
* 3. when done call portmux_close to cleanup.
*
* @example:
* static void server(char *server_name)
* {
* portmux_fd_t *portmux_hndl;
* int clientfd;
*
* // Get a connection with portmux for our service
* portmux_hndl = portmux_listen_setup(server_name, server_name,
*server_name);
* if (!portmux_hndl)
* {
* fprintf(stderr, "portmux_listen returned NULL\n");
* exit(1);
* }
*
* while (1)
* {
* // Patiently wait for our clients to connect using portmux_connect()
* clientfd = portmux_accept(portmux_hndl, 0);
* if (clientfd <= 0)
* {
* fprintf(stderr, "error in portmux_accept\n");
* break;
* }
*
* // Serve the client, this function will call close(clientfd);
* server_accept_hndl(clientfd);
* }
*
* // all done cleanup
* portmux_close(portmux_hndl);
* exit(1);
* }
*/
typedef struct portmux_fd portmux_fd_t;
/**
* @brief Create a "portmux File descriptor"
*
* @param[in] app Application to register.
* @param[in] service Service to register.
* @param[in] instance Instance to register.
*
* @return
*/
portmux_fd_t *portmux_listen_setup(const char *app, const char *service,
const char *instance, int tcplistenfd);
/**
* @brief Create a "portmux File descriptor"
*
* @param[in] app Application to register.
* @param[in] service Service to register.
* @param[in] instance Instance to register.
* @param[in] options Options.
*
* @return
*/
portmux_fd_t *portmux_listen_options_setup(const char *app, const char *service,
const char *instance,
int tcplistenfd, uint32_t options);
/**
* @brief Wait for a connection on portmux_fd.
*
* @param[in/out] fds Created from portmux_listen_setup().
* @param[in/out] timeoutms Optional timeout in ms. Will block until
* connection if <= 0.
*
* @return File descriptor of connection or -1 on error.
* On timeout it will return 0 (like poll()) and errno
* will be set to ETIMEDOUT.
* If connectivity with portmux is dropped and timeout
* expires before recovery succeed, rc will be -1
* and errno will be set to EAGAIN (meaning should retry).
*/
int portmux_accept(portmux_fd_t *fds, int timeoutms);
/**
* @brief Wait for a connection on a vector of portmux_fd.
*
* @param[in/out] fds Created from portmux_listen_setup() or
* portmux_listen_options_setup().
* @param[in/out] nfds Number of entries in fds.
* @param[in/out] timeoutms Optional timeout in ms. Will block until
* connection if <= 0.
* @param[in] accept_hndl Handler to call on connection.
* It is responsability of this
* callback to do close(fd).
*
* @return File descriptor of connection or -1 on error.
* On timeout it will return 0 (like poll()) and errno
* will be set to ETIMEDOUT.
* If connectivity with portmux is dropped and timeout
* expires before recovery succeed, rc will be -1
* and errno will be set to EAGAIN (meaning should retry).
*
* Successful connections will be passed to accept_hndl() with
* 'which' indicating the index into fds of the corresponding
* listening socket.
*
* @note If no callback function is given then this function will return
* a file descriptor for a connection that we have accepted. As
* there is no context as to which of the fds the connection was made it
* is likely of little use.
*
* A non-zero return from the accept_hndl callback function will cause this
* function to return with that value.
*/
int portmux_acceptv(portmux_fd_t **fds, int nfds, int timeoutms,
int (*accept_hndl)(int which, int fd, void *user_data),
void *user_data);
/**
* @brief Close and free previously attributed portmux_fd.
*
* @param[in/out] fds Portmux_fd to release (invalid after call)
*/
void portmux_close(portmux_fd_t *fds);
/**
* @brief Using portmux_fds a TCP port may or may not be attributed
* by portmux. One can use this call to retrieve it, knowing that it
* can return 0 if no port# has been given.
*
* @param[in/out] fds Portmux_fd to query.
*
* @return TCP port# if one was given else 0.
*/
int portmux_fds_get_tcpport(portmux_fd_t *fds);
/**
* @brief Return details of the triplet passed when fds was created.
*
* @param[in/out] fds Portmux_fd to query.
*
* @return The application, service or instance
*/
const char *portmux_fds_get_app(portmux_fd_t *fds);
const char *portmux_fds_get_service(portmux_fd_t *fds);
const char *portmux_fds_get_instance(portmux_fd_t *fds);
void set_portmux_port(int port);
int set_portmux_bind_path(const char *path);
char *get_portmux_bind_path(void);
void clear_portmux_bind_path();
/**
* @brief Connects to remote_host using portmux registered
* app/service/instance.
*
* @param[in] remote_host Where to connect to.
* @param[in] app Application to connect to.
* @param[in] service Service to connect to.
* @param[in] instance Instance to connect to.
*
* @return A valid connected fd to use if >= 0, else error. (@see tcplib)
*/
int portmux_connect(const char *remote_host, const char *app,
const char *service, const char *instance);
/**
* @brief Same as portmux_connect() with timeout option.
*
* @param[in] remote_host Where to connect to.
* @param[in] app Application to connect to.
* @param[in] service Service to connect to.
* @param[in] instance Instance to connect to.
* @param[in] timeoutms Optional timeout in ms.
*
* @return A valid connected fd to use if >= 0, else error. (@see tcplib)
*/
int portmux_connect_to(const char *remote_host, const char *app,
const char *service, const char *instance,
int timeoutms);
/**
* @brief Same as portmux_connect() but use given address.
*
* @param[in/out] addr Address to connect to
* @param[in] app Application to connect to.
* @param[in] service Service to connect to.
* @param[in] instance Instance to connect to.
*
* @return A valid connected fd to use if >= 0, else error. (@see tcplib)
*/
int portmux_connecti(struct in_addr addr, const char *app, const char *service,
const char *instance);
/**
* @brief Same as portmux_connecti() with a timeout option
*
* @param[in/out] addr Address to connect to
* @param[in] app Application to connect to.
* @param[in] service Service to connect to.
* @param[in] instance Instance to connect to.
* @param[in] timeoutms Optional timeout in ms.
*
* @return A valid connected fd to use if >= 0, else error. (@see tcplib)
*/
int portmux_connecti_to(struct in_addr addr, const char *app,
const char *service, const char *instance,
int timeoutms);
/******************************************************************************
******************************************************************************
** **
** THE APIS BELOW ARE CONSIDERED DEPRECATED **
** **
** New software should use the APIs above, which support "single port" **
** mode. See {SYSI:PORTMUX<go>}. **
** **
******************************************************************************
******************************************************************************/
/* This is called by servers to register themselves with portmux and
* obtain a port that they can bind to and accept on.
*
* Returns port number, or -1 for error
*/
int portmux_register(const char *app, const char *service,
const char *instance);
/**
* Tell portmux that we're now using this port
*/
int portmux_use(const char *app, const char *service, const char *instance,
int port);
/**
* Deregister a port number previous registered with portmux_register().
*
* In practice there is very little reason to ever call this. It is certainly
* not required that a server call this before it shuts down, as from the
* clients point of view there is really no practical difference between
* portmux not being able to return a port for a service, and portmux returning
* a port but the server itself not running to accept connections.
*
* Returns 0 on success, non-zero if the deregistration fails.
*/
int portmux_deregister(const char *app, const char *serivce,
const char *instance);
/* returns port number, or -1 for error*/
int portmux_get(const char *remote_host, const char *app, const char *service,
const char *instance);
int portmux_get_to(const char *remote_host, const char *app,
const char *service, const char *instance, int timeout_ms);
/* same as above by take an address rather than host name */
int portmux_geti(struct in_addr addr, const char *app, const char *service,
const char *instance);
int portmux_geti_to(struct in_addr addr, const char *app, const char *service,
const char *instance, int timeout_ms);
int portmux_hello(char *host, char *name, int *fdout);
/* override default portmux timeout */
void portmux_set_default_timeout(unsigned timeoutms);
void portmux_set_max_wait_timeout(unsigned timeoutms);
void portmux_register_reconnect_callback(int (*callback)(void *), void *);
int get_portmux_port(void);
void set_portmux_port(int);
#if defined __cplusplus
}
#endif
#endif