1 //
2 // Copyright 2021 Staysail Systems, Inc. <info@staysail.tech>
3 // Copyright 2018 Capitar IT Group BV <info@capitar.com>
4 //
5 // This software is supplied under the terms of the MIT License, a
6 // copy of which should be located in the distribution where this
7 // file was obtained (LICENSE.txt).  A copy of the license may also be
8 // found online at https://opensource.org/licenses/MIT.
9 //
10 
11 #ifndef CORE_PROTOCOL_H
12 #define CORE_PROTOCOL_H
13 
14 #include "core/options.h"
15 
16 // Protocol implementation details.  Protocols must implement the
17 // interfaces in this file.  Note that implementing new protocols is
18 // not necessarily intended to be a trivial task.  The protocol developer
19 // must understand the nature of nng, as they are responsible for handling
20 // most of the logic.  The protocol generally does most of the work for
21 // locking, and calls into the transport's pipe functions to do actual
22 // work, and the pipe functions generally assume no locking is needed.
23 // As a consequence, most of the concurrency in nng exists in the protocol
24 // implementations.
25 
26 // nni_proto_pipe contains protocol-specific per-pipe operations.
27 struct nni_proto_pipe_ops {
28 	// pipe_size is the size of a protocol pipe object.  The common
29 	// code allocates this memory for the protocol private state.
30 	size_t pipe_size;
31 
32 	// pipe_init initializes the protocol-specific pipe data structure.
33 	// The last argument is the per-socket protocol private data.
34 	int (*pipe_init)(void *, nni_pipe *, void *);
35 
36 	// pipe_fini releases any pipe data structures.  This is called after
37 	// the pipe has been removed from the protocol, and the generic
38 	// pipe threads have been stopped.
39 	void (*pipe_fini)(void *);
40 
41 	// pipe_start is called to register a pipe with the protocol.  The
42 	// protocol can reject this, for example if another pipe is already
43 	// active on a 1:1 protocol.  The protocol may not block during this.
44 	int (*pipe_start)(void *);
45 
46 	// pipe_close is an idempotent, non-blocking, operation, called
47 	// when the pipe is being closed.  Any operations pending on the
48 	// pipe should be canceled with NNG_ECLOSED.  (Best option is to
49 	// use nng_aio_close() on them)
50 	void (*pipe_close)(void *);
51 
52 	// pipe_stop is called during finalization, to ensure that
53 	// the protocol is absolutely finished with the pipe.  It should
54 	// wait if necessary to ensure that the pipe is not referenced
55 	// any more by the protocol.  It should not destroy resources.
56 	void (*pipe_stop)(void *);
57 };
58 
59 struct nni_proto_ctx_ops {
60 	// ctx_size is the size of a protocol context object.  The common
61 	// code allocates this memory for the protocol private state.
62 	size_t ctx_size;
63 
64 	// ctx_init initializes a new context. The second argument is the
65 	// protocol specific socket structure.
66 	int (*ctx_init)(void *, void *);
67 
68 	// ctx_fini destroys a context.
69 	void (*ctx_fini)(void *);
70 
71 	// ctx_recv is an asynchronous recv.
72 	void (*ctx_recv)(void *, nni_aio *);
73 
74 	// ctx_send is an asynchronous send.
75 	void (*ctx_send)(void *, nni_aio *);
76 
77 	// ctx_options array.
78 	nni_option *ctx_options;
79 };
80 
81 struct nni_proto_sock_ops {
82 	// ctx_size is the size of a protocol socket object.  The common
83 	// code allocates this memory for the protocol private state.
84 	size_t sock_size;
85 
86 	// sock_init initializes the protocol instance, which will be stored
87 	// on the socket. This is run without the sock lock held.
88 	int (*sock_init)(void *, nni_sock *);
89 
90 	// sock_fini destroys the protocol instance.  This is run without the
91 	// socket lock held, and is intended to release resources.  It may
92 	// block as needed.
93 	void (*sock_fini)(void *);
94 
95 	// Open the protocol instance.  This is run with the lock held,
96 	// and intended to allow the protocol to start any asynchronous
97 	// processing.
98 	void (*sock_open)(void *);
99 
100 	// Close the protocol instance.  This is run with the lock held,
101 	// and intended to initiate closure of the socket.  For example,
102 	// it can signal the socket worker threads to exit.
103 	void (*sock_close)(void *);
104 
105 	// Send a message.
106 	void (*sock_send)(void *, nni_aio *);
107 
108 	// Receive a message.
109 	void (*sock_recv)(void *, nni_aio *);
110 
111 	// Options. Must not be NULL. Final entry should have NULL name.
112 	nni_option *sock_options;
113 };
114 
115 typedef struct nni_proto_id {
116 	uint16_t    p_id;
117 	const char *p_name;
118 } nni_proto_id;
119 
120 struct nni_proto {
121 	uint32_t                  proto_version;  // Ops vector version
122 	nni_proto_id              proto_self;     // Our identity
123 	nni_proto_id              proto_peer;     // Peer identity
124 	uint32_t                  proto_flags;    // Protocol flags
125 	const nni_proto_sock_ops *proto_sock_ops; // Per-socket operations
126 	const nni_proto_pipe_ops *proto_pipe_ops; // Per-pipe operations
127 	const nni_proto_ctx_ops * proto_ctx_ops;  // Context operations
128 };
129 
130 // We quite intentionally use a signature where the upper word is nonzero,
131 // which ensures that if we get garbage we will reject it.  This is more
132 // likely to mismatch than all zero bytes would.  The actual version is
133 // stored in the lower word; this is not semver -- the numbers are just
134 // increasing - we doubt it will increase more than a handful of times
135 // during the life of the project.  If we add a new version, please keep
136 // the old version around -- it may be possible to automatically convert
137 // older versions in the future.
138 #define NNI_PROTOCOL_V3 0x50520003u // "pr\0\3"
139 #define NNI_PROTOCOL_VERSION NNI_PROTOCOL_V3
140 
141 // These flags determine which operations make sense.  We use them so that
142 // we can reject attempts to create notification fds for operations that make
143 // no sense.  Also, we can detect raw mode, thereby providing handling for
144 // that at the socket layer (NNG_PROTO_FLAG_RAW).
145 #define NNI_PROTO_FLAG_RCV 1u    // Protocol can receive
146 #define NNI_PROTO_FLAG_SND 2u    // Protocol can send
147 #define NNI_PROTO_FLAG_SNDRCV 3u // Protocol can both send & recv
148 #define NNI_PROTO_FLAG_RAW 4u    // Protocol is raw
149 
150 // nni_proto_open is called by the protocol to create a socket instance
151 // with its ops vector.  The intent is that applications will only see
152 // the single protocol-specific constructor, like nng_pair_v0_open(),
153 // which should just be a thin wrapper around this.  If the protocol has
154 // not been initialized yet, this routine will do so.
155 extern int nni_proto_open(nng_socket *, const nni_proto *);
156 
157 // Protocol numbers.
158 // These values are used on the wire, so must not be changed.  The major
159 // number of the protocol is shifted left by 4 bits, and a sub-protocol is
160 // assigned in the lower 4 bits.
161 //
162 // There are gaps in the list, which are obsolete or unsupported protocols.
163 // Protocol numbers are never more than 16 bits.  Also, there will never be
164 // a valid protocol numbered 0 (NNG_PROTO_NONE).
165 #define NNI_PROTO(major, minor) (((major) *16) + (minor))
166 
167 // Protocol major numbers.  This is here for documentation only, and
168 // to serve as a "registry" for managing new protocol numbers.  Consider
169 // updating this table when adding new protocols.
170 //
171 // Protocol     Maj Min Name       Notes
172 // -------------------------------------------
173 // NONE          0   0             reserved
174 // PAIRv0        1   0  pair
175 // PAIRv1        1   1  pair1      nng only, experimental
176 // PUBv0         2   0  pub
177 // SUBv0         2   1  sub
178 // REQv0         3   0  req
179 // REPv0         3   1  rep
180 // PUSHv0        5   0  push
181 // PULLv0        5   1  pull
182 // SURVEYORv0    6   2  surveyor   minors 0 & 1 retired
183 // RESPONDENTv0  6   3  respondent
184 // BUSv0         7   0  bus
185 // STARv0      100   0  star       mangos only, experimental
186 //
187 
188 #endif // CORE_PROTOCOL_H
189