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