From 2574efba78d3046f6c35bbb1d55c522fb2125c94 Mon Sep 17 00:00:00 2001 From: Garrett D'Amore Date: Wed, 7 Jul 2021 22:30:06 -0700 Subject: Move transport.[ch] to SP --- src/core/CMakeLists.txt | 2 - src/core/nng_impl.h | 2 +- src/core/pipe.h | 2 +- src/core/transport.c | 179 ------------------------------------------- src/core/transport.h | 196 ------------------------------------------------ src/sp/CMakeLists.txt | 5 ++ src/sp/transport.c | 179 +++++++++++++++++++++++++++++++++++++++++++ src/sp/transport.h | 196 ++++++++++++++++++++++++++++++++++++++++++++++++ 8 files changed, 382 insertions(+), 379 deletions(-) delete mode 100644 src/core/transport.c delete mode 100644 src/core/transport.h create mode 100644 src/sp/transport.c create mode 100644 src/sp/transport.h diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index 459e5f23..040df7f4 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -73,8 +73,6 @@ nng_sources( thread.h timer.c timer.h - transport.c - transport.h url.c url.h ) diff --git a/src/core/nng_impl.h b/src/core/nng_impl.h index cfcd0e08..a9e5560d 100644 --- a/src/core/nng_impl.h +++ b/src/core/nng_impl.h @@ -50,7 +50,7 @@ #include "core/url.h" // transport needs to come after url -#include "core/transport.h" +#include "sp/transport.h" // These have to come after the others - particularly transport.h diff --git a/src/core/pipe.h b/src/core/pipe.h index 79c48500..fe908936 100644 --- a/src/core/pipe.h +++ b/src/core/pipe.h @@ -17,7 +17,7 @@ #include "core/defs.h" #include "core/thread.h" -#include "core/transport.h" +#include "sp/transport.h" extern int nni_pipe_sys_init(void); extern void nni_pipe_sys_fini(void); diff --git a/src/core/transport.c b/src/core/transport.c deleted file mode 100644 index 78859078..00000000 --- a/src/core/transport.c +++ /dev/null @@ -1,179 +0,0 @@ -// -// Copyright 2019 Staysail Systems, Inc. -// Copyright 2018 Capitar IT Group BV -// Copyright 2019 Devolutions -// -// 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. -// - -#include "core/nng_impl.h" - -#ifdef NNG_TRANSPORT_INPROC -#include "nng/transport/inproc/inproc.h" -#endif -#ifdef NNG_TRANSPORT_IPC -#include "nng/transport/ipc/ipc.h" -#endif -#ifdef NNG_TRANSPORT_TCP -#include "nng/transport/tcp/tcp.h" -#endif -#ifdef NNG_TRANSPORT_TLS -#include "nng/transport/tls/tls.h" -#endif -#ifdef NNG_TRANSPORT_WS -#include "nng/transport/ws/websocket.h" -#endif -#ifdef NNG_TRANSPORT_ZEROTIER -#include "nng/transport/zerotier/zerotier.h" -#endif - -#include -#include - -// For now the list of transports is hard-wired. Adding new transports -// to the system dynamically is something that might be considered later. -extern nni_tran nni_tcp_tran; -extern nni_tran nni_ipc_tran; - -typedef struct nni_transport { - nni_tran t_tran; - nni_list_node t_node; -} nni_transport; - -static nni_list nni_tran_list; -static nni_mtx nni_tran_lk; -static int nni_tran_inited; - -int -nni_tran_register(const nni_tran *tran) -{ - nni_transport *t; - int rv; - - // Its entirely possible that we are called before any sockets - // are opened. Make sure we are initialized. This has to be - // protected by a guard to prevent infinite recursion, since - // nni_init also winds up calling us. - if (!nni_tran_inited) { - nni_init(); - } - - if (tran->tran_version != NNI_TRANSPORT_VERSION) { - return (NNG_ENOTSUP); - } - - nni_mtx_lock(&nni_tran_lk); - // Check to see if the transport is already registered... - NNI_LIST_FOREACH (&nni_tran_list, t) { - if (strcmp(tran->tran_scheme, t->t_tran.tran_scheme) == 0) { - if (tran->tran_init == t->t_tran.tran_init) { - // duplicate. - nni_mtx_unlock(&nni_tran_lk); - return (0); - } - nni_mtx_unlock(&nni_tran_lk); - return (NNG_ESTATE); - } - } - if ((t = NNI_ALLOC_STRUCT(t)) == NULL) { - nni_mtx_unlock(&nni_tran_lk); - return (NNG_ENOMEM); - } - - t->t_tran = *tran; - if ((rv = t->t_tran.tran_init()) != 0) { - nni_mtx_unlock(&nni_tran_lk); - NNI_FREE_STRUCT(t); - return (rv); - } - nni_list_append(&nni_tran_list, t); - nni_mtx_unlock(&nni_tran_lk); - return (0); -} - -nni_tran * -nni_tran_find(nni_url *url) -{ - // address is of the form "://blah..." - nni_transport *t; - - nni_mtx_lock(&nni_tran_lk); - NNI_LIST_FOREACH (&nni_tran_list, t) { - if (strcmp(url->u_scheme, t->t_tran.tran_scheme) == 0) { - nni_mtx_unlock(&nni_tran_lk); - return (&t->t_tran); - } - } - nni_mtx_unlock(&nni_tran_lk); - return (NULL); -} - -// nni_tran_sys_init initializes the entire transport subsystem, including -// each individual transport. - -typedef int (*nni_tran_ctor)(void); - -// These are just the statically compiled in constructors. -// In the future we might want to support dynamic additions. -static nni_tran_ctor nni_tran_ctors[] = { -#ifdef NNG_TRANSPORT_INPROC - nng_inproc_register, -#endif -#ifdef NNG_TRANSPORT_IPC - nng_ipc_register, -#endif -#ifdef NNG_TRANSPORT_TCP - nng_tcp_register, -#endif -#ifdef NNG_TRANSPORT_TLS - nng_tls_register, -#endif -#ifdef NNG_TRANSPORT_WS - nng_ws_register, -#endif -#ifdef NNG_TRANSPORT_WSS - nng_wss_register, -#endif -#ifdef NNG_TRANSPORT_ZEROTIER - nng_zt_register, -#endif - NULL, -}; - -int -nni_tran_sys_init(void) -{ - int i; - - nni_tran_inited = 1; - NNI_LIST_INIT(&nni_tran_list, nni_transport, t_node); - nni_mtx_init(&nni_tran_lk); - - for (i = 0; nni_tran_ctors[i] != NULL; i++) { - int rv; - if ((rv = (nni_tran_ctors[i])()) != 0) { - nni_tran_sys_fini(); - return (rv); - } - } - return (0); -} - -// nni_tran_sys_fini finalizes the entire transport system, including all -// transports. -void -nni_tran_sys_fini(void) -{ - nni_transport *t; - - while ((t = nni_list_first(&nni_tran_list)) != NULL) { - nni_list_remove(&nni_tran_list, t); - t->t_tran.tran_fini(); - NNI_FREE_STRUCT(t); - } - nni_mtx_fini(&nni_tran_lk); - nni_tran_inited = 0; -} diff --git a/src/core/transport.h b/src/core/transport.h deleted file mode 100644 index b2da2c7a..00000000 --- a/src/core/transport.h +++ /dev/null @@ -1,196 +0,0 @@ -// -// Copyright 2020 Staysail Systems, Inc. -// Copyright 2018 Capitar IT Group BV -// Copyright 2018 Devolutions -// -// 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 CORE_TRANSPORT_H -#define CORE_TRANSPORT_H - -#include "core/options.h" - -// We quite intentionally use a signature where the upper word is nonzero, -// which ensures that if we get garbage we will reject it. This is more -// likely to mismatch than all zero bytes would. The actual version is -// stored in the lower word; this is not semver -- the numbers are just -// increasing - we doubt it will increase more than a handful of times -// during the life of the project. If we add a new version, please keep -// the old version around -- it may be possible to automatically convert -// older versions in the future. -#define NNI_TRANSPORT_V0 0x54520000 -#define NNI_TRANSPORT_V1 0x54520001 -#define NNI_TRANSPORT_V2 0x54520002 -#define NNI_TRANSPORT_V3 0x54520003 -#define NNI_TRANSPORT_V4 0x54520004 -#define NNI_TRANSPORT_V5 0x54520005 -#define NNI_TRANSPORT_V6 0x54220006 -#define NNI_TRANSPORT_V7 0x54220006 -#define NNI_TRANSPORT_VERSION NNI_TRANSPORT_V7 - -// 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_tran_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_tran_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_tran_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_tran { - // tran_version is the version of the transport ops that this - // transport implements. We only bother to version the main - // ops vector. - uint32_t tran_version; - - // tran_scheme is the transport scheme, such as "tcp" or "inproc". - const char *tran_scheme; - - // tran_dialer links our dialer-specific operations. - const nni_tran_dialer_ops *tran_dialer; - - // tran_listener links our listener-specific operations. - const nni_tran_listener_ops *tran_listener; - - // tran_pipe links our pipe-specific operations. - const nni_tran_pipe_ops *tran_pipe; - - // tran_init, if not NULL, is called once during library - // initialization. - int (*tran_init)(void); - - // tran_fini, if not NULL, is called during library deinitialization. - // It should release any global resources, close any open files, etc. - void (*tran_fini)(void); -}; - -// These APIs are used by the framework internally, and not for use by -// transport implementations. -extern nni_tran *nni_tran_find(nni_url *); -extern int nni_tran_sys_init(void); -extern void nni_tran_sys_fini(void); -extern int nni_tran_register(const nni_tran *); - -#endif // CORE_TRANSPORT_H diff --git a/src/sp/CMakeLists.txt b/src/sp/CMakeLists.txt index b84952ee..aa790c09 100644 --- a/src/sp/CMakeLists.txt +++ b/src/sp/CMakeLists.txt @@ -11,3 +11,8 @@ nng_directory(sp) add_subdirectory(protocol) add_subdirectory(transport) + +nng_sources( + transport.c + transport.h +) diff --git a/src/sp/transport.c b/src/sp/transport.c new file mode 100644 index 00000000..78859078 --- /dev/null +++ b/src/sp/transport.c @@ -0,0 +1,179 @@ +// +// Copyright 2019 Staysail Systems, Inc. +// Copyright 2018 Capitar IT Group BV +// Copyright 2019 Devolutions +// +// 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. +// + +#include "core/nng_impl.h" + +#ifdef NNG_TRANSPORT_INPROC +#include "nng/transport/inproc/inproc.h" +#endif +#ifdef NNG_TRANSPORT_IPC +#include "nng/transport/ipc/ipc.h" +#endif +#ifdef NNG_TRANSPORT_TCP +#include "nng/transport/tcp/tcp.h" +#endif +#ifdef NNG_TRANSPORT_TLS +#include "nng/transport/tls/tls.h" +#endif +#ifdef NNG_TRANSPORT_WS +#include "nng/transport/ws/websocket.h" +#endif +#ifdef NNG_TRANSPORT_ZEROTIER +#include "nng/transport/zerotier/zerotier.h" +#endif + +#include +#include + +// For now the list of transports is hard-wired. Adding new transports +// to the system dynamically is something that might be considered later. +extern nni_tran nni_tcp_tran; +extern nni_tran nni_ipc_tran; + +typedef struct nni_transport { + nni_tran t_tran; + nni_list_node t_node; +} nni_transport; + +static nni_list nni_tran_list; +static nni_mtx nni_tran_lk; +static int nni_tran_inited; + +int +nni_tran_register(const nni_tran *tran) +{ + nni_transport *t; + int rv; + + // Its entirely possible that we are called before any sockets + // are opened. Make sure we are initialized. This has to be + // protected by a guard to prevent infinite recursion, since + // nni_init also winds up calling us. + if (!nni_tran_inited) { + nni_init(); + } + + if (tran->tran_version != NNI_TRANSPORT_VERSION) { + return (NNG_ENOTSUP); + } + + nni_mtx_lock(&nni_tran_lk); + // Check to see if the transport is already registered... + NNI_LIST_FOREACH (&nni_tran_list, t) { + if (strcmp(tran->tran_scheme, t->t_tran.tran_scheme) == 0) { + if (tran->tran_init == t->t_tran.tran_init) { + // duplicate. + nni_mtx_unlock(&nni_tran_lk); + return (0); + } + nni_mtx_unlock(&nni_tran_lk); + return (NNG_ESTATE); + } + } + if ((t = NNI_ALLOC_STRUCT(t)) == NULL) { + nni_mtx_unlock(&nni_tran_lk); + return (NNG_ENOMEM); + } + + t->t_tran = *tran; + if ((rv = t->t_tran.tran_init()) != 0) { + nni_mtx_unlock(&nni_tran_lk); + NNI_FREE_STRUCT(t); + return (rv); + } + nni_list_append(&nni_tran_list, t); + nni_mtx_unlock(&nni_tran_lk); + return (0); +} + +nni_tran * +nni_tran_find(nni_url *url) +{ + // address is of the form "://blah..." + nni_transport *t; + + nni_mtx_lock(&nni_tran_lk); + NNI_LIST_FOREACH (&nni_tran_list, t) { + if (strcmp(url->u_scheme, t->t_tran.tran_scheme) == 0) { + nni_mtx_unlock(&nni_tran_lk); + return (&t->t_tran); + } + } + nni_mtx_unlock(&nni_tran_lk); + return (NULL); +} + +// nni_tran_sys_init initializes the entire transport subsystem, including +// each individual transport. + +typedef int (*nni_tran_ctor)(void); + +// These are just the statically compiled in constructors. +// In the future we might want to support dynamic additions. +static nni_tran_ctor nni_tran_ctors[] = { +#ifdef NNG_TRANSPORT_INPROC + nng_inproc_register, +#endif +#ifdef NNG_TRANSPORT_IPC + nng_ipc_register, +#endif +#ifdef NNG_TRANSPORT_TCP + nng_tcp_register, +#endif +#ifdef NNG_TRANSPORT_TLS + nng_tls_register, +#endif +#ifdef NNG_TRANSPORT_WS + nng_ws_register, +#endif +#ifdef NNG_TRANSPORT_WSS + nng_wss_register, +#endif +#ifdef NNG_TRANSPORT_ZEROTIER + nng_zt_register, +#endif + NULL, +}; + +int +nni_tran_sys_init(void) +{ + int i; + + nni_tran_inited = 1; + NNI_LIST_INIT(&nni_tran_list, nni_transport, t_node); + nni_mtx_init(&nni_tran_lk); + + for (i = 0; nni_tran_ctors[i] != NULL; i++) { + int rv; + if ((rv = (nni_tran_ctors[i])()) != 0) { + nni_tran_sys_fini(); + return (rv); + } + } + return (0); +} + +// nni_tran_sys_fini finalizes the entire transport system, including all +// transports. +void +nni_tran_sys_fini(void) +{ + nni_transport *t; + + while ((t = nni_list_first(&nni_tran_list)) != NULL) { + nni_list_remove(&nni_tran_list, t); + t->t_tran.tran_fini(); + NNI_FREE_STRUCT(t); + } + nni_mtx_fini(&nni_tran_lk); + nni_tran_inited = 0; +} diff --git a/src/sp/transport.h b/src/sp/transport.h new file mode 100644 index 00000000..b2da2c7a --- /dev/null +++ b/src/sp/transport.h @@ -0,0 +1,196 @@ +// +// Copyright 2020 Staysail Systems, Inc. +// Copyright 2018 Capitar IT Group BV +// Copyright 2018 Devolutions +// +// 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 CORE_TRANSPORT_H +#define CORE_TRANSPORT_H + +#include "core/options.h" + +// We quite intentionally use a signature where the upper word is nonzero, +// which ensures that if we get garbage we will reject it. This is more +// likely to mismatch than all zero bytes would. The actual version is +// stored in the lower word; this is not semver -- the numbers are just +// increasing - we doubt it will increase more than a handful of times +// during the life of the project. If we add a new version, please keep +// the old version around -- it may be possible to automatically convert +// older versions in the future. +#define NNI_TRANSPORT_V0 0x54520000 +#define NNI_TRANSPORT_V1 0x54520001 +#define NNI_TRANSPORT_V2 0x54520002 +#define NNI_TRANSPORT_V3 0x54520003 +#define NNI_TRANSPORT_V4 0x54520004 +#define NNI_TRANSPORT_V5 0x54520005 +#define NNI_TRANSPORT_V6 0x54220006 +#define NNI_TRANSPORT_V7 0x54220006 +#define NNI_TRANSPORT_VERSION NNI_TRANSPORT_V7 + +// 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_tran_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_tran_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_tran_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_tran { + // tran_version is the version of the transport ops that this + // transport implements. We only bother to version the main + // ops vector. + uint32_t tran_version; + + // tran_scheme is the transport scheme, such as "tcp" or "inproc". + const char *tran_scheme; + + // tran_dialer links our dialer-specific operations. + const nni_tran_dialer_ops *tran_dialer; + + // tran_listener links our listener-specific operations. + const nni_tran_listener_ops *tran_listener; + + // tran_pipe links our pipe-specific operations. + const nni_tran_pipe_ops *tran_pipe; + + // tran_init, if not NULL, is called once during library + // initialization. + int (*tran_init)(void); + + // tran_fini, if not NULL, is called during library deinitialization. + // It should release any global resources, close any open files, etc. + void (*tran_fini)(void); +}; + +// These APIs are used by the framework internally, and not for use by +// transport implementations. +extern nni_tran *nni_tran_find(nni_url *); +extern int nni_tran_sys_init(void); +extern void nni_tran_sys_fini(void); +extern int nni_tran_register(const nni_tran *); + +#endif // CORE_TRANSPORT_H -- cgit v1.2.3-70-g09d2