//
|
// Copyright 2021 Staysail Systems, Inc. <info@staysail.tech>
|
// Copyright 2018 Capitar IT Group BV <info@capitar.com>
|
// Copyright 2018 Devolutions <info@devolutions.net>
|
//
|
// This software is supplied under the terms of the MIT License, a
|
// copy of which should be located in the distribution where this
|
// file was obtained (LICENSE.txt). A copy of the license may also be
|
// found online at https://opensource.org/licenses/MIT.
|
//
|
|
#ifndef PROTOCOL_SP_TRANSPORT_H
|
#define PROTOCOL_SP_TRANSPORT_H
|
|
#include "core/options.h"
|
|
// Endpoint operations are called by the socket in a
|
// protocol-independent fashion. The socket makes individual calls,
|
// which are expected to block if appropriate (except for destroy), or
|
// run asynchronously if an aio is provided. Endpoints are unable to
|
// call back into the socket, to prevent recusive entry and deadlock.
|
//
|
// For a given endpoint, the framework holds a lock so that each entry
|
// point is run exclusively of the others. (Transports must still guard
|
// against any asynchronous operations they manage themselves, though.)
|
|
struct nni_sp_dialer_ops {
|
// d_init creates a vanilla dialer. The value created is
|
// used for the first argument for all other dialer functions.
|
int (*d_init)(void **, nni_url *, nni_dialer *);
|
|
// d_fini frees the resources associated with the dialer.
|
// The dialer will already have been closed.
|
void (*d_fini)(void *);
|
|
// d_connect establishes a connection. It can return errors
|
// NNG_EACCESS, NNG_ECONNREFUSED, NNG_EBADADDR,
|
// NNG_ECONNFAILED, NNG_ETIMEDOUT, and NNG_EPROTO.
|
void (*d_connect)(void *, nni_aio *);
|
|
// d_close stops the dialer from operating altogether. It
|
// does not affect pipes that have already been created. It is
|
// nonblocking.
|
void (*d_close)(void *);
|
|
// d_getopt is used to obtain an option.
|
int (*d_getopt)(void *, const char *, void *, size_t *, nni_type);
|
|
// d_setopt is used to set or change an option.
|
int (*d_setopt)(void *, const char *, const void *, size_t, nni_type);
|
|
// d_options is an array of dialer options. The final
|
// element must have a NULL name. If this member is NULL, then
|
// no dialer specific options are available.
|
nni_option *d_options;
|
};
|
|
struct nni_sp_listener_ops {
|
// l_init creates a vanilla listener. The value created is
|
// used for the first argument for all other listener functions.
|
int (*l_init)(void **, nni_url *, nni_listener *);
|
|
// l_fini frees the resources associated with the listener.
|
// The listener will already have been closed.
|
void (*l_fini)(void *);
|
|
// l_bind just does the bind() and listen() work,
|
// reserving the address but not creating any connections.
|
// It should return NNG_EADDRINUSE if the address is already
|
// taken. It can also return NNG_EBADADDR for an unsuitable
|
// address, or NNG_EACCESS for permission problems.
|
int (*l_bind)(void *);
|
|
// l_accept accepts an inbound connection.
|
void (*l_accept)(void *, nni_aio *);
|
|
// l_close stops the listener from operating altogether. It
|
// does not affect pipes that have already been created. It is
|
// nonblocking.
|
void (*l_close)(void *);
|
|
// l_getopt is used to obtain an option.
|
int (*l_getopt)(void *, const char *, void *, size_t *, nni_type);
|
|
// l_setopt is used to set or change an option.
|
int (*l_setopt)(void *, const char *, const void *, size_t, nni_type);
|
|
// l_options is an array of listener options. The final
|
// element must have a NULL name. If this member is NULL, then
|
// no dialer specific options are available.
|
nni_option *l_options;
|
};
|
|
// Pipe operations are entry points called by the socket. These may be
|
// called with socket locks held, so it is forbidden for the transport
|
// to call back into the socket at this point. (Which is one reason
|
// pointers back to socket or even enclosing pipe state, are not
|
// provided.)
|
struct nni_sp_pipe_ops {
|
// p_init initializes the pipe data structures. The main
|
// purpose of this is so that the pipe will see the upper
|
// layer nni_pipe and get a chance to register stats and such.
|
int (*p_init)(void *, nni_pipe *);
|
|
// p_fini destroys the pipe. This should clean up all local
|
// resources, including closing files and freeing memory, used
|
// by the pipe. After this call returns, the system will not
|
// make further calls on the same pipe.
|
void (*p_fini)(void *);
|
|
// p_stop stops the pipe, waiting for any callbacks that are
|
// outstanding to complete. This is done before tearing down
|
// resources with p_fini.
|
void (*p_stop)(void *);
|
|
// p_aio_send queues the message for transmit. If this fails,
|
// then the caller may try again with the same message (or free
|
// it). If the call succeeds, then the transport has taken
|
// ownership of the message, and the caller may not use it
|
// again. The transport will have the responsibility to free
|
// the message (nng_msg_free()) when it is finished with it.
|
void (*p_send)(void *, nni_aio *);
|
|
// p_recv schedules a message receive. This will be performed
|
// even for cases where no data is expected, to allow detection
|
// of a remote disconnect.
|
void (*p_recv)(void *, nni_aio *);
|
|
// p_close closes the pipe. Further recv or send operations
|
// should return back NNG_ECLOSED.
|
void (*p_close)(void *);
|
|
// p_peer returns the peer protocol. This may arrive in
|
// whatever transport specific manner is appropriate.
|
uint16_t (*p_peer)(void *);
|
|
// p_getopt is used to obtain an option. Pipes don't implement
|
// option setting.
|
int (*p_getopt)(void *, const char *, void *, size_t *, nni_type);
|
};
|
|
// Transport implementation details. Transports must implement the
|
// interfaces in this file.
|
struct nni_sp_tran {
|
// tran_link is for framework use only - it must initialized
|
// to zero before registration.
|
nni_list_node tran_link;
|
|
// tran_scheme is the transport scheme, such as "tcp" or "inproc".
|
const char *tran_scheme;
|
|
// tran_dialer links our dialer-specific operations.
|
const nni_sp_dialer_ops *tran_dialer;
|
|
// tran_listener links our listener-specific operations.
|
const nni_sp_listener_ops *tran_listener;
|
|
// tran_pipe links our pipe-specific operations.
|
const nni_sp_pipe_ops *tran_pipe;
|
|
// tran_init is called once during library initialization.
|
void (*tran_init)(void);
|
|
// tran_fini is called during library shutdown.
|
// It should release any global resources.
|
void (*tran_fini)(void);
|
};
|
|
// These APIs are used by the framework internally, and not for use by
|
// transport implementations.
|
extern nni_sp_tran *nni_sp_tran_find(nni_url *);
|
extern int nni_sp_tran_sys_init(void);
|
extern void nni_sp_tran_sys_fini(void);
|
extern void nni_sp_tran_register(nni_sp_tran *);
|
|
#endif // PROTOCOL_SP_TRANSPORT_H
|