summaryrefslogtreecommitdiff
path: root/3rdparty/plibsys/src/psocketaddress.h
blob: d77ca1c83a80d36983ae6d1fb8f7d2cf46d20ca3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
/*
 * The MIT License
 *
 * Copyright (C) 2010-2017 Alexander Saprykin <saprykin.spb@gmail.com>
 *
 * Permission is hereby granted, free of charge, to any person obtaining
 * a copy of this software and associated documentation files (the
 * 'Software'), to deal in the Software without restriction, including
 * without limitation the rights to use, copy, modify, merge, publish,
 * distribute, sublicense, and/or sell copies of the Software, and to
 * permit persons to whom the Software is furnished to do so, subject to
 * the following conditions:
 *
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */

/**
 * @file psocketaddress.h
 * @brief Socket address wrapper
 * @author Alexander Saprykin
 *
 * A socket address is usually represented by a network address (IPv4 or IPv6)
 * and a port number (though some other naming schemes and parameters are
 * possible).
 *
 * Socket address parameters are stored inside a special system (native)
 * structure in the binary (raw) form. The native structure varies with an
 * operating system and a network protocol. #PSocketAddress acts like a thin
 * wrapper around that native address structure and unifies manipulation of
 * socket address data.
 *
 * #PSocketAddress supports IPv4 and IPv6 addresses which consist of an IP
 * address and a port number. IPv6 support is system dependent and not provided
 * for all the platforms. Sometimes you may also need to enable IPv6 support in
 * the system to make it working.
 *
 * Convenient methods to create special addresses are provided: for the loopback
 * interface use p_socket_address_new_loopback(), for the any-address interface
 * use p_socket_address_new_any().
 *
 * If you want to get the underlying native address structure for further usage
 * in system calls use p_socket_address_to_native(), and
 * p_socket_address_new_from_native() for a vice versa conversion.
 */

#if !defined (PLIBSYS_H_INSIDE) && !defined (PLIBSYS_COMPILATION)
#  error "Header files shouldn't be included directly, consider using <plibsys.h> instead."
#endif

#ifndef PLIBSYS_HEADER_PSOCKETADDRESS_H
#define PLIBSYS_HEADER_PSOCKETADDRESS_H

#include <pmacros.h>
#include <ptypes.h>

#ifndef P_OS_WIN
#  include <sys/types.h>
#  include <sys/socket.h>
#  include <netinet/in.h>
#endif

P_BEGIN_DECLS

/** Socket address family. */
typedef enum PSocketFamily_ {
	P_SOCKET_FAMILY_UNKNOWN = 0,		/**< Unknown family.	*/
	P_SOCKET_FAMILY_INET	= AF_INET,	/**< IPv4 family.	*/
#ifdef AF_INET6
	P_SOCKET_FAMILY_INET6	= AF_INET6	/**< IPv6 family.	*/
#else
	P_SOCKET_FAMILY_INET6	= -1		/**< No IPv6 family.	*/
#endif
} PSocketFamily;

/** Socket address opaque structure. */
typedef struct PSocketAddress_ PSocketAddress;

/**
 * @brief Creates new #PSocketAddress from the native socket address raw data.
 * @param native Pointer to the native socket address raw data.
 * @param len Raw data length, in bytes.
 * @return Pointer to #PSocketAddress in case of success, NULL otherwise.
 * @since 0.0.1
 */
P_LIB_API PSocketAddress *	p_socket_address_new_from_native	(pconstpointer		native,
									 psize			len);

/**
 * @brief Creates new #PSocketAddress.
 * @param address String representation of an address (i.e. "172.146.45.5").
 * @param port Port number.
 * @return Pointer to #PSocketAddress in case of success, NULL otherwise.
 * @since 0.0.1
 * @note It tries to automatically detect a socket family.
 *
 * If the @a address is an IPv6 address, it can also contain a scope index
 * separated from the address by the '%' literal). Most target platforms should
 * correctly parse such an address though some old operating systems may fail in
 * case of lack of the getaddrinfo() call.
 */
P_LIB_API PSocketAddress *	p_socket_address_new			(const pchar		*address,
									 puint16		port);

/**
 * @brief Creates new #PSocketAddress for the any-address representation.
 * @param family Socket family.
 * @param port Port number.
 * @return Pointer to #PSocketAddress in case of success, NULL otherwise.
 * @since 0.0.1
 * @note This call creates a network address for the set of all possible
 * addresses, so you can't use it for receiving or sending data on a particular
 * network address. If you need to bind a socket to the specific address
 * (i.e. 127.0.0.1) use p_socket_address_new() instead.
 */
P_LIB_API PSocketAddress *	p_socket_address_new_any		(PSocketFamily		family,
									 puint16		port);

/**
 * @brief Creates new #PSocketAddress for the loopback interface.
 * @param family Socket family.
 * @param port Port number.
 * @return Pointer to #PSocketAddress in case of success, NULL otherwise.
 * @since 0.0.1
 * @note This call creates a network address for the entire loopback network
 * interface, so you can't use it for receiving or sending data on a particular
 * network address. If you need to bind a socket to the specific address
 * (i.e. 127.0.0.1) use p_socket_address_new() instead.
 */
P_LIB_API PSocketAddress *	p_socket_address_new_loopback		(PSocketFamily		family,
									 puint16		port);

/**
 * @brief Converts #PSocketAddress to the native socket address raw data.
 * @param addr #PSocketAddress to convert.
 * @param[out] dest Output buffer for raw data.
 * @param destlen Length in bytes of the @a dest buffer.
 * @return TRUE in case of success, FALSE otherwise.
 * @since 0.0.1
 */
P_LIB_API pboolean		p_socket_address_to_native		(const PSocketAddress	*addr,
									 ppointer		dest,
									 psize			destlen);

/**
 * @brief Gets the size of the native socket address raw data, in bytes.
 * @param addr #PSocketAddress to get the size of native address raw data for.
 * @return Size of the native socket address raw data in case of success, 0
 * otherwise.
 * @since 0.0.1
 */
P_LIB_API psize			p_socket_address_get_native_size	(const PSocketAddress	*addr);

/**
 * @brief Gets a family of a socket address.
 * @param addr #PSocketAddress to get the family for.
 * @return #PSocketFamily of the socket address.
 * @since 0.0.1
 */
P_LIB_API PSocketFamily		p_socket_address_get_family		(const PSocketAddress	*addr);

/**
 * @brief Gets a socket address in a string representation, i.e. "172.146.45.5".
 * @param addr #PSocketAddress to get address string for.
 * @return Pointer to the string representation of the socket address in case of
 * success, NULL otherwise. The caller takes ownership of the returned pointer.
 * @since 0.0.1
 */
P_LIB_API pchar *		p_socket_address_get_address		(const PSocketAddress	*addr);

/**
 * @brief Gets a port number of a socket address.
 * @param addr #PSocketAddress to get the port number for.
 * @return Port number in case of success, 0 otherwise.
 * @since 0.0.1
 */
P_LIB_API puint16		p_socket_address_get_port		(const PSocketAddress	*addr);

/**
 * @brief Gets IPv6 traffic class and flow information.
 * @param addr #PSocketAddress to get flow information for.
 * @return IPv6 traffic class and flow information.
 * @since 0.0.1
 * @note This call is valid only for an IPv6 address, otherwise 0 is returned.
 * @note Some operating systems may not support this property.
 * @sa p_socket_address_is_flow_info_supported()
 */
P_LIB_API puint32		p_socket_address_get_flow_info		(const PSocketAddress	*addr);

/**
 * @brief Gets an IPv6 set of interfaces for a scope.
 * @param addr #PSocketAddress to get the set of interfaces for.
 * @return Index that identifies the set of interfaces for a scope.
 * @since 0.0.1
 * @note This call is valid only for an IPv6 address, otherwise 0 is returned.
 * @note Some operating systems may not support this property.
 * @sa p_socket_address_is_scope_id_supported()
 */
P_LIB_API puint32		p_socket_address_get_scope_id		(const PSocketAddress	*addr);

/**
 * @brief Sets IPv6 traffic class and flow information.
 * @param addr #PSocketAddress to set flow information for.
 * @param flowinfo Flow information to set.
 * @since 0.0.1
 * @note This call is valid only for an IPv6 address.
 * @note Some operating systems may not support this property.
 * @sa p_socket_address_is_flow_info_supported()
 */
P_LIB_API void			p_socket_address_set_flow_info		(PSocketAddress		*addr,
									 puint32		flowinfo);

/**
 * @brief Sets an IPv6 set of interfaces for a scope.
 * @param addr #PSocketAddress to set the set of interfaces for.
 * @param scope_id Index that identifies the set of interfaces for a scope.
 * @since 0.0.1
 * @note This call is valid only for an IPv6 address.
 * @note Some operating systems may not support this property.
 * @sa p_socket_address_is_scope_id_supported()
 */
P_LIB_API void			p_socket_address_set_scope_id		(PSocketAddress		*addr,
									 puint32		scope_id);

/**
 * @brief Checks whether flow information is supported in IPv6.
 * @return TRUE in case of success, FALSE otherwise.
 * @since 0.0.1
 */
P_LIB_API pboolean		p_socket_address_is_flow_info_supported	(void);

/**
 * @brief Checks whether a set of interfaces for a scope is supported in IPv6.
 * @return TRUE in case of success, FALSE otherwise.
 * @since 0.0.1
 */
P_LIB_API pboolean		p_socket_address_is_scope_id_supported	(void);

/**
 * @brief Checks whether IPv6 protocol is supported.
 * @return TRUE in case of success, FALSE otherwise.
 * @since 0.0.3
 */
P_LIB_API pboolean		p_socket_address_is_ipv6_supported	(void);

/**
 * @brief Checks whether a given socket address is an any-address
 * representation. Such an address is a 0.0.0.0.
 * @param addr #PSocketAddress to check.
 * @return TRUE if the @a addr is the any-address representation, FALSE
 * otherwise.
 * @since 0.0.1
 * @sa p_socket_address_new_any()
 */
P_LIB_API pboolean		p_socket_address_is_any			(const PSocketAddress	*addr);

/**
 * @brief Checks whether a given socket address is for the loopback interface.
 * Such an address is a 127.x.x.x.
 * @param addr #PSocketAddress to check.
 * @return TRUE if the @a addr is for the loopback interface, FALSE otherwise.
 * @since 0.0.1
 * @sa p_socket_address_new_loopback()
 */
P_LIB_API pboolean		p_socket_address_is_loopback		(const PSocketAddress	*addr);

/**
 * @brief Frees a socket address structure and its resources.
 * @param addr #PSocketAddress to free.
 * @since 0.0.1
 */
P_LIB_API void			p_socket_address_free			(PSocketAddress		*addr);

P_END_DECLS

#endif /* PLIBSYS_HEADER_PSOCKETADDRESS_H */