1 //
2 // Copyright 2018 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 NNG_COMPAT_NN_H
12 #define NNG_COMPAT_NN_H
13 
14 // This header contains interfaces that are intended to offer compatibility
15 // with nanomsg v1.0.  These are not the "preferred" interfaces for nng,
16 // and consumers should only use these if they are porting software that
17 // previously used nanomsg.  New programs should use the nng native APIs.
18 
19 // Note that compatibility promises are limited to public portions of the
20 // nanomsg API, and specifically do NOT extend to the ABI.  Furthermore,
21 // there may be other limitations around less commonly used portions of the
22 // API; for example only SP headers may be transported in control data for
23 // messages, there is almost no compatibility offered for statistics.
24 // Error values may differ from those returned by nanomsg as well; the nng
25 // error reporting facility expresses only a subset of the possibilities of
26 // nanomsg.
27 
28 // Note that unlike nanomsg, nng does not aggressively recycle socket or
29 // endpoint IDs, which means applications which made assumptions that these
30 // would be relatively small integers (e.g. to use them as array indices)
31 // may break.  (No promise about values was ever made.)
32 
33 #ifdef __cplusplus
34 extern "C" {
35 #endif
36 
37 #include <errno.h>
38 #include <stddef.h>
39 #include <stdint.h>
40 
41 // clang-format gets in the way of most of this file.
42 // We turn it off, at least until it gets smarter about aligning
43 // macro definitions or we adopt enums or somesuch.
44 // clang-format off
45 
46 // NNG_DECL is used on declarations to deal with scope.
47 // For building Windows DLLs, it should be the appropriate __declspec().
48 // For shared libraries with platforms that support hidden visibility,
49 // it should evaluate to __attribute__((visibility("default"))).
50 #ifndef NN_DECL
51 #if defined(_WIN32) && !defined(NNG_STATIC_LIB)
52 #if defined(NNG_SHARED_LIB)
53 #define NN_DECL		__declspec(dllexport)
54 #else
55 #define NN_DECL		__declspec(dllimport)
56 #endif // NNG_SHARED_LIB
57 #else
58 #if defined(NNG_SHARED_LIB) && defined(NNG_HIDDEN_VISIBILITY)
59 #define NN_DECL __attribute__((visibility("default")))
60 #else
61 #define NN_DECL extern
62 #endif
63 #endif // _WIN32 && !NNG_STATIC_LIB
64 #endif  // NN_DECL
65 
66 #define AF_SP			1
67 #define AF_SP_RAW		2
68 
69 #define NN_SOCKADDR_MAX		128
70 #define NN_SOL_SOCKET		0
71 
72 // Flag for send/recv (nonblocking)
73 #define NN_DONTWAIT		1
74 
75 // CMSG data type
76 #define PROTO_SP		1
77 #define SP_HDR			1
78 
79 // Errnos.  Legacy nanomsg uses posix errnos where possible.
80 // If a define is not set, use add NN_ERRBASE.  nng does not
81 // return all of these values, so there may be some loss of
82 // of information for edge cases, but we don't expect that to be
83 // a problem really.
84 #define NN_ERRBASE		(0x10000000)
85 #ifndef ENOTSUP
86 #define ENOTSUP			(NN_ERRBASE+1)
87 #endif
88 #ifndef EPROTONOSUPPORT
89 #define EPROTONOSUPPORT		(NN_ERRBASE+2)
90 #endif
91 #ifndef ENOBUFS
92 #define ENOBUFS			(NN_ERRBASE+3)
93 #endif
94 #ifndef ENETDOWN
95 #define ENETDOWN		(NN_ERRBASE+4)
96 #endif
97 #ifndef EADDRINUSE
98 #define EADDRINUSE		(NN_ERRBASE+5)
99 #endif
100 #ifndef EADDRNOTAVAIL
101 #define EADDRNOTAVAIL		(NN_ERRBASE+6)
102 #endif
103 #ifndef ENOTSOCK
104 #define ENOTSOCK		(NN_ERRBASE+7)
105 #endif
106 #ifndef EAGAIN
107 #define EAGAIN			(NN_ERRBASE+8)
108 #endif
109 #ifndef EBADF
110 #define EBADF			(NN_ERRBASE+9)
111 #endif
112 #ifndef EINVAL
113 #define EINVAL			(NN_ERRBASE+10)
114 #endif
115 #ifndef EMFILE
116 #define EMFILE			(NN_ERRBASE+11)
117 #endif
118 #ifndef EFAULT
119 #define EFAULT			(NN_ERRBASE+12)
120 #endif
121 #ifndef EACCES
122 #define EACCES			(NN_ERRBASE+13)
123 #endif
124 #ifndef ENETRESET
125 #define ENETRESET		(NN_ERRBASE+14)
126 #endif
127 #ifndef ENETUNREACH
128 #define ENETUNREACH		(NN_ERRBASE+15)
129 #endif
130 #ifndef EHOSTUNREACH
131 #define EHOSTUNREACH		(NN_ERRBASE+16)
132 #endif
133 #ifndef EAFNOSUPPORT
134 #define EAFNOSUPPORT		(NN_ERRBASE+17)
135 #endif
136 #ifndef EINPROGRESS
137 #define EINPROGRESS		(NN_ERRBASE+18)
138 #endif
139 #ifndef EPROTO
140 #define EPROTO			(NN_ERRBASE+19)
141 #endif
142 #ifndef ECONNREFUSED
143 #define ECONNREFUSED		(NN_ERRBASE+20)
144 #endif
145 #ifndef ENOTCONN
146 #define ENOTCONN		(NN_ERRBASE+21)
147 #endif
148 #ifndef EMSGSIZE
149 #define EMSGSIZE		(NN_ERRBASE+22)
150 #endif
151 #ifndef ETIMEDOUT
152 #define ETIMEDOUT		(NN_ERRBASE+23)
153 #endif
154 #ifndef ECONNABORTED
155 #define ECONNABORTED		(NN_ERRBASE+24)
156 #endif
157 #ifndef ECONNRESET
158 #define ECONNRESET		(NN_ERRBASE+25)
159 #endif
160 #ifndef ENOPROTOOPT
161 #define ENOPROTOOPT		(NN_ERRBASE+26)
162 #endif
163 #ifndef EISCONN
164 #define EISCONN			(NN_ERRBASE+27)
165 #endif
166 #ifndef ESOCKNOSUPPORT
167 #define ESOCKNOSPPORT		(NN_ERRBASE+28)
168 #endif
169 #ifndef ETERM
170 #define ETERM			(NN_ERRBASE+29)
171 #endif
172 #ifndef EFSM
173 #define EFSM			(NN_ERRBASE+30)
174 #endif
175 #ifndef ENOENT
176 #define ENOENT			(NN_ERRBASE+31)
177 #endif
178 #ifndef EIO
179 #define EIO			(NN_ERRBASE+32)
180 #endif
181 #ifndef EEXIST
182 #define EEXIST			(NN_ERRBASE+33)
183 #endif
184 #ifndef ENOSPC
185 #define ENOSPC			(NN_ERRBASE+34)
186 #endif
187 
188 
189 // Socket options
190 #define NN_LINGER		1
191 #define NN_SNDBUF		2
192 #define NN_RCVBUF		3
193 #define NN_SNDTIMEO		4
194 #define NN_RCVTIMEO		5
195 #define NN_RECONNECT_IVL	6
196 #define NN_RECONNECT_IVL_MAX	7
197 #define NN_SNDPRIO		8
198 #define NN_RCVPRIO		9
199 #define NN_SNDFD		10
200 #define NN_RCVFD		11
201 #define NN_DOMAIN		12
202 #define NN_PROTOCOL		13
203 #define NN_IPV4ONLY		14
204 #define NN_SOCKET_NAME		15
205 #define NN_RCVMAXSIZE		16
206 #define NN_MAXTTL		17
207 
208 // from this point on formatting is fine
209 // clang-format on
210 
211 // Poll stuff
212 #define NN_POLLIN 1
213 #define NN_POLLOUT 2
214 struct nn_pollfd {
215 	int      fd;
216 	uint16_t events;
217 	uint16_t revents;
218 };
219 
220 // Magical size for allocation
221 #define NN_MSG ((size_t) -1)
222 
223 struct nn_iovec {
224 	void * iov_base;
225 	size_t iov_len;
226 };
227 
228 struct nn_msghdr {
229 	struct nn_iovec *msg_iov;
230 	int              msg_iovlen;
231 	void *           msg_control;
232 	size_t           msg_controllen;
233 };
234 
235 struct nn_cmsghdr {
236 	size_t cmsg_len;
237 	int    cmsg_level;
238 	int    cmsg_type;
239 };
240 
241 #define NN_CMSG_ALIGN(len) \
242 	(((len) + sizeof(size_t) - 1) & (size_t) ~(sizeof(size_t) - 1))
243 
244 // Unlike old nanomsg, we explicitly only support the SP header as attached
245 // cmsg data.  It turns out that old nanomsg didn't really store anything
246 // useful otherwise anyway.  (One specific exception was that it stored the
247 // message type of text or binary for the websocket transport.  We don't think
248 // anyone used that in practice though.)
249 #define NN_CMSG_FIRSTHDR(mh) nn_cmsg_next((struct nn_msghdr *) (mh), NULL)
250 #define NN_CMSG_NXTHDR(mh, ch) \
251 	nn_cmsg_next((struct nn_msghdr *) (mh), (struct nn_cmsghdr *) ch)
252 #define NN_CMSG_DATA(ch) ((unsigned char *) (((struct nn_cmsghdr *) (ch)) + 1))
253 #define NN_CMSG_SPACE(len) \
254 	(NN_CMSG_ALIGN(len) + NN_CMSG_ALIGN(sizeof(struct nn_cmsghdr)))
255 #define NN_CMSG_LEN(len) (NN_CMSG_ALIGN(sizeof(struct nn_cmsghdr)) + (len))
256 
257 NN_DECL struct nn_cmsghdr *nn_cmsg_next(
258     struct nn_msghdr *, struct nn_cmsghdr *);
259 NN_DECL int nn_socket(int, int);
260 NN_DECL int nn_setsockopt(int, int, int, const void *, size_t);
261 NN_DECL int nn_getsockopt(int, int, int, void *, size_t *);
262 NN_DECL int nn_bind(int, const char *);
263 NN_DECL int nn_connect(int, const char *);
264 NN_DECL int nn_shutdown(int, int);
265 NN_DECL int nn_send(int, const void *, size_t, int);
266 NN_DECL int nn_recv(int, void *, size_t, int);
267 NN_DECL int nn_sendmsg(int, const struct nn_msghdr *, int);
268 NN_DECL int nn_recvmsg(int, struct nn_msghdr *, int);
269 NN_DECL int nn_close(int);
270 NN_DECL int nn_poll(struct nn_pollfd *, int, int);
271 NN_DECL int nn_device(int, int);
272 NN_DECL uint64_t    nn_get_statistic(int, int);
273 NN_DECL void *      nn_allocmsg(size_t, int);
274 NN_DECL void *      nn_reallocmsg(void *, size_t);
275 NN_DECL int         nn_freemsg(void *);
276 NN_DECL int         nn_errno(void);
277 NN_DECL const char *nn_strerror(int);
278 NN_DECL void        nn_term(void);
279 
280 #ifdef __cplusplus
281 }
282 #endif
283 
284 #endif // NNG_COMPAT_NN_H
285