1 #include <sys/types.h>
2 #include <sys/socket.h>
3 #include <netinet/in.h> /* ipv4 support */
4 #include <sys/un.h> /* local (aka unix) support */
5 #include <string.h>
6
7 #include "config.h"
8 #include "gsksocketaddress.h"
9 #include "gskipv4.h"
10 #include "gskerror.h"
11 #include "gskghelpers.h"
12 #include "gskmacros.h"
13
14 G_DEFINE_ABSTRACT_TYPE(GskSocketAddress, gsk_socket_address, G_TYPE_OBJECT);
15 G_DEFINE_TYPE(GskSocketAddressIpv4, gsk_socket_address_ipv4, GSK_TYPE_SOCKET_ADDRESS);
16 G_DEFINE_TYPE(GskSocketAddressIpv6, gsk_socket_address_ipv6, GSK_TYPE_SOCKET_ADDRESS);
17 G_DEFINE_TYPE(GskSocketAddressEthernet, gsk_socket_address_ethernet, GSK_TYPE_SOCKET_ADDRESS);
18 G_DEFINE_TYPE(GskSocketAddressLocal, gsk_socket_address_local, GSK_TYPE_SOCKET_ADDRESS);
19
20 /* Macro to initialize the sa_len-like member of
21 sockaddr, if it exists. */
22 #if HAS_SOCKADDR_SA_LEN
23 #define MAYBE_SET_LENGTH_MEMBER(addr_member, type) \
24 G_STMT_START{ addr_member = sizeof(type); }G_STMT_END
25 #else
26 #define MAYBE_SET_LENGTH_MEMBER(addr_member, type)
27 #endif
28
29 /* Define GSK_[AP]F_LOCAL as portible wrappers for [AP]F_LOCAL. */
30 #if HAS_PF_LOCAL
31 #define GSK_PF_LOCAL PF_LOCAL
32 #define GSK_AF_LOCAL AF_LOCAL
33 #elif HAS_PF_UNIX
34 #define GSK_PF_LOCAL PF_UNIX
35 #define GSK_AF_LOCAL AF_UNIX
36 #else
37 #warn "no PF_UNIX or PF_LOCAL macros (?)"
38 #endif
39
40 /* --- GskSocketAddress implementation --- */
41 static void
gsk_socket_address_init(GskSocketAddress * socket_address)42 gsk_socket_address_init (GskSocketAddress *socket_address)
43 {
44 }
45
46 static void
gsk_socket_address_class_init(GskSocketAddressClass * class)47 gsk_socket_address_class_init (GskSocketAddressClass *class)
48 {
49 }
50
51 /* --- GskSocketAddressIpv4 implementation --- */
52
53 static gboolean
gsk_socket_address_ipv4_to_native(GskSocketAddress * address,gpointer output)54 gsk_socket_address_ipv4_to_native (GskSocketAddress *address,
55 gpointer output)
56 {
57 GskSocketAddressIpv4 *ipv4 = GSK_SOCKET_ADDRESS_IPV4 (address);
58 struct sockaddr_in *addr = output;
59 memset (addr, 0, sizeof (struct sockaddr_in));
60 addr->sin_family = PF_INET;
61 MAYBE_SET_LENGTH_MEMBER (addr->sin_len, struct sockaddr_in);
62 addr->sin_port = GUINT16_TO_BE (ipv4->ip_port);
63 memcpy (&addr->sin_addr, ipv4->ip_address, 4);
64 return TRUE;
65 }
66
67 static gboolean
gsk_socket_address_ipv4_from_native(GskSocketAddress * address,gconstpointer sockaddr_data,gsize sockaddr_length)68 gsk_socket_address_ipv4_from_native (GskSocketAddress *address,
69 gconstpointer sockaddr_data,
70 gsize sockaddr_length)
71 {
72 GskSocketAddressIpv4 *ipv4 = GSK_SOCKET_ADDRESS_IPV4 (address);
73 const struct sockaddr_in *addr = sockaddr_data;
74 ipv4->ip_port = GUINT16_FROM_BE (addr->sin_port);
75 memcpy (ipv4->ip_address, &addr->sin_addr, 4);
76 return TRUE;
77 }
78
79 static char *
gsk_socket_address_ipv4_to_string(GskSocketAddress * address)80 gsk_socket_address_ipv4_to_string (GskSocketAddress *address)
81 {
82 GskSocketAddressIpv4 *ipv4 = GSK_SOCKET_ADDRESS_IPV4 (address);
83 if (ipv4->ip_port != 0)
84 return g_strdup_printf ("%d.%d.%d.%d:%d",
85 ipv4->ip_address[0],
86 ipv4->ip_address[1],
87 ipv4->ip_address[2],
88 ipv4->ip_address[3],
89 ipv4->ip_port);
90 else
91 return g_strdup_printf ("%d.%d.%d.%d",
92 ipv4->ip_address[0],
93 ipv4->ip_address[1],
94 ipv4->ip_address[2],
95 ipv4->ip_address[3]);
96 }
97
98 static gboolean
gsk_socket_address_ipv4_equals(GskSocketAddress * a,GskSocketAddress * b)99 gsk_socket_address_ipv4_equals (GskSocketAddress *a,
100 GskSocketAddress *b)
101 {
102 GskSocketAddressIpv4 *ipv4_a = GSK_SOCKET_ADDRESS_IPV4 (a);
103 GskSocketAddressIpv4 *ipv4_b = GSK_SOCKET_ADDRESS_IPV4 (b);
104 return ipv4_a->ip_address[0] == ipv4_b->ip_address[0]
105 && ipv4_a->ip_address[1] == ipv4_b->ip_address[1]
106 && ipv4_a->ip_address[2] == ipv4_b->ip_address[2]
107 && ipv4_a->ip_address[3] == ipv4_b->ip_address[3]
108 && ipv4_a->ip_port == ipv4_b->ip_port;
109 }
110
111 static guint
gsk_socket_address_ipv4_hash(GskSocketAddress * a)112 gsk_socket_address_ipv4_hash (GskSocketAddress *a)
113 {
114 GskSocketAddressIpv4 *ipv4 = GSK_SOCKET_ADDRESS_IPV4 (a);
115 guint hash = ipv4->ip_address[0];
116 hash *= 33;
117 hash += ipv4->ip_address[1];
118 hash *= 33;
119 hash += ipv4->ip_address[2];
120 hash *= 33;
121 hash += ipv4->ip_address[3];
122 hash *= 33;
123 hash += ipv4->ip_port;
124 return hash;
125 }
126
127 static void
gsk_socket_address_ipv4_init(GskSocketAddressIpv4 * socket_address_ipv4)128 gsk_socket_address_ipv4_init (GskSocketAddressIpv4 *socket_address_ipv4)
129 {
130 }
131
132 static void
gsk_socket_address_ipv4_class_init(GskSocketAddressIpv4Class * ipv4_class)133 gsk_socket_address_ipv4_class_init (GskSocketAddressIpv4Class *ipv4_class)
134 {
135 GskSocketAddressClass *class = GSK_SOCKET_ADDRESS_CLASS (ipv4_class);
136 class->address_family = AF_INET;
137 class->protocol_family = PF_INET;
138 class->sizeof_native_address = sizeof (struct sockaddr_in);
139 class->from_native = gsk_socket_address_ipv4_from_native;
140 class->to_native = gsk_socket_address_ipv4_to_native;
141 class->to_string = gsk_socket_address_ipv4_to_string;
142 class->hash = gsk_socket_address_ipv4_hash;
143 class->equals = gsk_socket_address_ipv4_equals;
144 gsk_socket_address_register_subclass (class);
145 }
146
147 /* --- ipv6 implementation --- */
148 #if SUPPORTS_IPV6
149 static gboolean
gsk_socket_address_ipv6_to_native(GskSocketAddress * address,gpointer output)150 gsk_socket_address_ipv6_to_native (GskSocketAddress *address,
151 gpointer output)
152 {
153 GskSocketAddressIpv6 *ipv6 = GSK_SOCKET_ADDRESS_IPV6 (address);
154 struct sockaddr_in6 *addr = output;
155 MAYBE_SET_LENGTH_MEMBER (addr->sin6_len, struct sockaddr_in6);
156 addr->sin6_family = AF_INET6;
157 addr->sin6_port = GUINT16_TO_BE (ipv6->port);
158 addr->sin6_flowinfo = GUINT32_TO_BE (ipv6->flow_info);
159 addr->sin6_scope_id = GUINT32_TO_BE (ipv6->scope_id);
160 g_assert (sizeof (addr->sin6_addr) == 16);
161 memcpy (&addr->sin6_addr, ipv6->address, 16);
162 return TRUE;
163 }
164
165 static gboolean
gsk_socket_address_ipv6_from_native(GskSocketAddress * address,gconstpointer sockaddr_data,gsize sockaddr_length)166 gsk_socket_address_ipv6_from_native (GskSocketAddress *address,
167 gconstpointer sockaddr_data,
168 gsize sockaddr_length)
169 {
170 GskSocketAddressIpv6 *ipv6 = GSK_SOCKET_ADDRESS_IPV6 (address);
171 const struct sockaddr_in6 *addr = sockaddr_data;
172 ipv6->port = GUINT16_FROM_BE (addr->sin6_port);
173 ipv6->flow_info = GUINT32_FROM_BE (addr->sin6_flowinfo);
174 ipv6->scope_id = GUINT32_FROM_BE (addr->sin6_scope_id);
175 memcpy (ipv6->address, &addr->sin6_addr, 16);
176 return TRUE;
177 }
178 #endif
179
180 static char *
gsk_socket_address_ipv6_to_string(GskSocketAddress * address)181 gsk_socket_address_ipv6_to_string (GskSocketAddress *address)
182 {
183 GString *str = g_string_new ("");
184 GskSocketAddressIpv6 *ipv6 = GSK_SOCKET_ADDRESS_IPV6 (address);
185 guint8 *a = ipv6->address;
186 guint i;
187 g_string_printf (str, "%d@%x", ipv6->port, a[0]);
188 for (i = 1; i < 16; i++)
189 g_string_append_printf (str, ":%x", a[1]);
190 return g_string_free (str, FALSE);
191 }
192
193 static gboolean
gsk_socket_address_ipv6_equals(GskSocketAddress * a,GskSocketAddress * b)194 gsk_socket_address_ipv6_equals (GskSocketAddress *a,
195 GskSocketAddress *b)
196 {
197 GskSocketAddressIpv6 *ipv6_a = GSK_SOCKET_ADDRESS_IPV6 (a);
198 GskSocketAddressIpv6 *ipv6_b = GSK_SOCKET_ADDRESS_IPV6 (b);
199 return ipv6_a->port == ipv6_b->port
200 && memcmp (ipv6_a->address, ipv6_b->address, 16) == 0;
201 }
202
203 static guint
gsk_socket_address_ipv6_hash(GskSocketAddress * a)204 gsk_socket_address_ipv6_hash (GskSocketAddress *a)
205 {
206 GskSocketAddressIpv6 *ipv6 = GSK_SOCKET_ADDRESS_IPV6 (a);
207 guint hash = ipv6->port;
208 guint i;
209 for (i = 0; i < 16; i++)
210 {
211 hash *= 33;
212 hash += ipv6->address[i];
213 }
214 return hash;
215 }
216
217 static void
gsk_socket_address_ipv6_init(GskSocketAddressIpv6 * socket_address_ipv6)218 gsk_socket_address_ipv6_init (GskSocketAddressIpv6 *socket_address_ipv6)
219 {
220 }
221
222 static void
gsk_socket_address_ipv6_class_init(GskSocketAddressIpv6Class * ipv6_class)223 gsk_socket_address_ipv6_class_init (GskSocketAddressIpv6Class *ipv6_class)
224 {
225 GskSocketAddressClass *class = GSK_SOCKET_ADDRESS_CLASS (ipv6_class);
226 #if SUPPORTS_IPV6
227 class->address_family = AF_INET6;
228 class->protocol_family = PF_INET6;
229 class->sizeof_native_address = sizeof (struct sockaddr_in6);
230 class->from_native = gsk_socket_address_ipv6_from_native;
231 class->to_native = gsk_socket_address_ipv6_to_native;
232 #endif
233 class->to_string = gsk_socket_address_ipv6_to_string;
234 class->hash = gsk_socket_address_ipv6_hash;
235 class->equals = gsk_socket_address_ipv6_equals;
236 gsk_socket_address_register_subclass (class);
237 }
238
239 /* --- local (aka unix) socket address implementation --- */
240 static gboolean
gsk_socket_address_local_to_native(GskSocketAddress * address,gpointer output)241 gsk_socket_address_local_to_native (GskSocketAddress *address,
242 gpointer output)
243 {
244 GskSocketAddressLocal *local = GSK_SOCKET_ADDRESS_LOCAL (address);
245 struct sockaddr_un *addr = output;
246 MAYBE_SET_LENGTH_MEMBER (addr->sun_len, struct sockaddr_un);
247 addr->sun_family = GSK_PF_LOCAL;
248 /* XXX: zero out other (a priori, unknown) arguments */
249 strncpy (addr->sun_path, local->path, sizeof (addr->sun_path));
250 return TRUE;
251 }
252
253
254 static gboolean
gsk_socket_address_local_from_native(GskSocketAddress * address,gconstpointer sockaddr_data,gsize sockaddr_length)255 gsk_socket_address_local_from_native (GskSocketAddress *address,
256 gconstpointer sockaddr_data,
257 gsize sockaddr_length)
258 {
259 GskSocketAddressLocal *local = GSK_SOCKET_ADDRESS_LOCAL (address);
260 const struct sockaddr_un *native = sockaddr_data;
261 gint max_len;
262 guint len;
263 if (GSK_STRUCT_IS_LAST_MEMBER (struct sockaddr_un, sun_path))
264 max_len = sockaddr_length - G_STRUCT_OFFSET(struct sockaddr_un, sun_path);
265 else
266 max_len = sizeof (native->sun_path);
267 if (max_len <= 0)
268 return FALSE;
269
270 g_free (local->path);
271 len = gsk_strnlen (native->sun_path, max_len);
272 local->path = g_new (char, len + 1);
273 memcpy (local->path, native->sun_path, len);
274 local->path[len] = '\0';
275 return TRUE;
276 }
277
278 static char *
gsk_socket_address_local_to_string(GskSocketAddress * address)279 gsk_socket_address_local_to_string (GskSocketAddress *address)
280 {
281 GskSocketAddressLocal *local = GSK_SOCKET_ADDRESS_LOCAL (address);
282 return g_strdup (local->path);
283 }
284
285 static gboolean
gsk_socket_address_local_equals(GskSocketAddress * a,GskSocketAddress * b)286 gsk_socket_address_local_equals (GskSocketAddress *a,
287 GskSocketAddress *b)
288 {
289 GskSocketAddressLocal *local_a = GSK_SOCKET_ADDRESS_LOCAL (a);
290 GskSocketAddressLocal *local_b = GSK_SOCKET_ADDRESS_LOCAL (b);
291 return strcmp (local_a->path, local_b->path) == 0;
292 }
293
294 static guint
gsk_socket_address_local_hash(GskSocketAddress * a)295 gsk_socket_address_local_hash (GskSocketAddress *a)
296 {
297 GskSocketAddressLocal *local = GSK_SOCKET_ADDRESS_LOCAL (a);
298 return g_str_hash (local->path);
299 }
300
301 static void
gsk_socket_address_local_init(GskSocketAddressLocal * socket_address_local)302 gsk_socket_address_local_init (GskSocketAddressLocal *socket_address_local)
303 {
304 }
305
306 static void
gsk_socket_address_local_finalize(GObject * object)307 gsk_socket_address_local_finalize (GObject *object)
308 {
309 GskSocketAddressLocal *local = GSK_SOCKET_ADDRESS_LOCAL (object);
310 g_free (local->path);
311 G_OBJECT_CLASS (gsk_socket_address_local_parent_class)->finalize (object);
312 }
313
314 static void
gsk_socket_address_local_class_init(GskSocketAddressLocalClass * class)315 gsk_socket_address_local_class_init (GskSocketAddressLocalClass *class)
316 {
317 GskSocketAddressClass *address_class = GSK_SOCKET_ADDRESS_CLASS (class);
318 GObjectClass *object_class = G_OBJECT_CLASS (class);
319 class->max_path_length = GSK_STRUCT_MEMBER_SIZE (struct sockaddr_un, sun_path);
320 address_class->sizeof_native_address = sizeof (struct sockaddr_un);
321 address_class->address_family = GSK_AF_LOCAL;
322 address_class->protocol_family = GSK_PF_LOCAL;
323 address_class->to_native = gsk_socket_address_local_to_native;
324 address_class->from_native = gsk_socket_address_local_from_native;
325 address_class->to_string = gsk_socket_address_local_to_string;
326 address_class->equals = gsk_socket_address_local_equals;
327 address_class->hash = gsk_socket_address_local_hash;
328 gsk_socket_address_register_subclass (address_class);
329 object_class->finalize = gsk_socket_address_local_finalize;
330 }
331
332 /**
333 * gsk_socket_address_local_new:
334 * @path: path in filesystem to hook this socket up.
335 *
336 * Create a socket-address which is associated with a path
337 * in the local filesystem. Such socket-addresses
338 * are useful for fast communication between processes on the same
339 * host.
340 *
341 * Sometimes, these types of addresses are called unix-domain addresses,
342 * but it is better to avoid the term unix for a generic concept.
343 *
344 * returns: the newly allocated socket address.
345 */
346 GskSocketAddress *
gsk_socket_address_local_new(const char * path)347 gsk_socket_address_local_new (const char *path)
348 {
349 GskSocketAddressLocalClass *class = g_type_class_ref (GSK_TYPE_SOCKET_ADDRESS_LOCAL);
350 guint path_len = strlen (path);
351 GskSocketAddressLocal *rv;
352 if (path_len > class->max_path_length)
353 return NULL;
354 rv = g_object_new (G_OBJECT_CLASS_TYPE (class), NULL);
355 rv->path = g_strdup (path);
356 g_type_class_unref (class);
357 return GSK_SOCKET_ADDRESS (rv);
358 }
359
360 /* --- Ethernet (MAC) addresses --- */
361 #if 0 /* TODO: conversions to/from native */
362 static gboolean
363 gsk_socket_address_ethernet_to_native (GskSocketAddress *address,
364 gpointer output)
365 {
366 GskSocketAddressEthernet *ethernet = GSK_SOCKET_ADDRESS_ETHERNET (address);
367 ...
368 }
369
370 static gboolean
371 gsk_socket_address_ethernet_from_native (GskSocketAddress *address,
372 gconstpointer sockaddr_data,
373 gsize sockaddr_length)
374 {
375 GskSocketAddressEthernet *ethernet = GSK_SOCKET_ADDRESS_ETHERNET (address);
376 ...
377 }
378 #endif
379
380 static guint
gsk_socket_address_ethernet_hash(GskSocketAddress * addr)381 gsk_socket_address_ethernet_hash (GskSocketAddress *addr)
382 {
383 GskSocketAddressEthernet *ethernet = GSK_SOCKET_ADDRESS_ETHERNET (addr);
384 guint i;
385 guint rv = 0;
386 for (i = 0; i < 6; i++)
387 {
388 rv *= 167;
389 rv += ethernet->mac_address[i];
390 }
391 return rv;
392 }
393
394 static char *
gsk_socket_address_ethernet_to_string(GskSocketAddress * address)395 gsk_socket_address_ethernet_to_string (GskSocketAddress *address)
396 {
397 GskSocketAddressEthernet *ethernet = GSK_SOCKET_ADDRESS_ETHERNET (address);
398 return g_strdup_printf ("%02X:%02X:%02X:%02X:%02X:%02X",
399 ethernet->mac_address[0],
400 ethernet->mac_address[1],
401 ethernet->mac_address[2],
402 ethernet->mac_address[3],
403 ethernet->mac_address[4],
404 ethernet->mac_address[5]);
405 }
406
407 static gboolean
gsk_socket_address_ethernet_equals(GskSocketAddress * addr1,GskSocketAddress * addr2)408 gsk_socket_address_ethernet_equals (GskSocketAddress *addr1,
409 GskSocketAddress *addr2)
410 {
411 GskSocketAddressEthernet *ethernet1 = GSK_SOCKET_ADDRESS_ETHERNET (addr1);
412 GskSocketAddressEthernet *ethernet2 = GSK_SOCKET_ADDRESS_ETHERNET (addr2);
413 return memcmp (ethernet1->mac_address, ethernet2->mac_address, 6) == 0;
414 }
415
416 /* --- functions --- */
417 static void
gsk_socket_address_ethernet_init(GskSocketAddressEthernet * socket_address_ethernet)418 gsk_socket_address_ethernet_init (GskSocketAddressEthernet *socket_address_ethernet)
419 {
420 }
421
422 static void
gsk_socket_address_ethernet_class_init(GskSocketAddressEthernetClass * eth_class)423 gsk_socket_address_ethernet_class_init (GskSocketAddressEthernetClass *eth_class)
424 {
425 GskSocketAddressClass *class = GSK_SOCKET_ADDRESS_CLASS (eth_class);
426 class->hash = gsk_socket_address_ethernet_hash;
427 class->to_string = gsk_socket_address_ethernet_to_string;
428 class->equals = gsk_socket_address_ethernet_equals;
429 /* TODO: convert to/from native */
430 #if 0
431 class->to_native = gsk_socket_address_ethernet_to_native;
432 class->from_native = gsk_socket_address_ethernet_from_native;
433 class->address_family = AF_???;
434 class->protocol_family = PF_???;
435 class->sizeof_native_address = sizeof (struct sockaddr_??? );
436 gsk_socket_address_register_subclass (class);
437 #endif
438 }
439
440 /**
441 * gsk_socket_address_ethernet_new:
442 * @mac_addr: the 6-byte unique address of this ethernet device.
443 *
444 * Allocate a new socket address corresponding to an
445 * ethernet device.
446 *
447 * returns: the newly allocated socket-address.
448 */
449 GskSocketAddress *
gsk_socket_address_ethernet_new(const guint8 * mac_addr)450 gsk_socket_address_ethernet_new (const guint8 *mac_addr)
451 {
452 GskSocketAddressEthernet *eth = g_object_new (GSK_TYPE_SOCKET_ADDRESS_ETHERNET, NULL);
453 memcpy (eth->mac_address, mac_addr, 6);
454 return GSK_SOCKET_ADDRESS (eth);
455 }
456
457 /* --- public methods --- */
458 static GHashTable *native_to_gtype = NULL;
459 static GStaticRWLock native_to_gtype_lock = G_STATIC_RW_LOCK_INIT;
460
461 #define N2G_WRITE_LOCK() g_static_rw_lock_writer_lock(&native_to_gtype_lock)
462 #define N2G_WRITE_UNLOCK() g_static_rw_lock_writer_unlock(&native_to_gtype_lock)
463 #define N2G_READ_LOCK() g_static_rw_lock_reader_lock(&native_to_gtype_lock)
464 #define N2G_READ_UNLOCK() g_static_rw_lock_reader_unlock(&native_to_gtype_lock)
465
466 /**
467 * gsk_socket_address_from_native:
468 * @native_data: a struct sockaddr_t*.
469 * @native_size: length of native_data.
470 *
471 * Allocate a new GskSocketAddress based on
472 * native_data, if we know how.
473 *
474 * returns: a new GskSocketAddress or NULL if we could not interpret the sockaddr.
475 */
476 GskSocketAddress *
gsk_socket_address_from_native(gconstpointer native_data,gsize native_size)477 gsk_socket_address_from_native (gconstpointer native_data,
478 gsize native_size)
479 {
480 const struct sockaddr *addr = native_data;
481 GType type;
482 GskSocketAddressClass *class;
483 GObject *rv_object;
484 GskSocketAddress *rv;
485 guint family;
486 N2G_READ_LOCK ();
487 if (native_to_gtype == NULL)
488 {
489 N2G_READ_UNLOCK ();
490 return NULL;
491 }
492 family = (guint) addr->sa_family;
493 type = (GType) g_hash_table_lookup (native_to_gtype, GUINT_TO_POINTER (family));
494 N2G_READ_UNLOCK ();
495 if (type == 0)
496 {
497 return NULL;
498 }
499 rv_object = g_object_new (type, NULL);
500 rv = GSK_SOCKET_ADDRESS (rv_object);
501 class = GSK_SOCKET_ADDRESS_GET_CLASS (rv);
502 if (!((*class->from_native) (rv, native_data, native_size)))
503 {
504 g_object_unref (rv);
505 return NULL;
506 }
507 return GSK_SOCKET_ADDRESS (rv);
508 }
509
510 /**
511 * gsk_socket_address_sizeof_native:
512 * @address: a socket address.
513 *
514 * Determine how many bytes of storage the sockaddr_t
515 * based on this object will require.
516 *
517 * returns: the size in bytes of the native sockaddr type.
518 */
519 guint
gsk_socket_address_sizeof_native(GskSocketAddress * address)520 gsk_socket_address_sizeof_native (GskSocketAddress *address)
521 {
522 return GSK_SOCKET_ADDRESS_GET_CLASS (address)->sizeof_native_address;
523 }
524
525 /**
526 * gsk_socket_address_protocol_family:
527 * @address: a socket address.
528 *
529 * Get the PF_* macro value corresponding to this address.
530 *
531 * returns: the protocol family.
532 */
533 gint
gsk_socket_address_protocol_family(GskSocketAddress * address)534 gsk_socket_address_protocol_family (GskSocketAddress *address)
535 {
536 return GSK_SOCKET_ADDRESS_GET_CLASS (address)->protocol_family;
537 }
538
539 /**
540 * gsk_socket_address_address_family:
541 * @address: a socket address.
542 *
543 * Get the AF_* macro value corresponding to this address.
544 *
545 * returns: the address family.
546 */
547 gint
gsk_socket_address_address_family(GskSocketAddress * address)548 gsk_socket_address_address_family (GskSocketAddress *address)
549 {
550 return GSK_SOCKET_ADDRESS_GET_CLASS (address)->address_family;
551 }
552
553 /**
554 * gsk_socket_address_to_native:
555 * @address: a socket address.
556 * @output: a struct sockaddr_t (at least conceptually)
557 * @error: optional error return value.
558 *
559 * Convert a socket-address to its native form.
560 *
561 * returns: whether it was able to convert the address.
562 */
563 gboolean
gsk_socket_address_to_native(GskSocketAddress * address,gpointer output,GError ** error)564 gsk_socket_address_to_native (GskSocketAddress *address,
565 gpointer output,
566 GError **error)
567 {
568 GskSocketAddressClass *class = GSK_SOCKET_ADDRESS_GET_CLASS (address);
569 if (G_UNLIKELY (!class->to_native (address, output)))
570 {
571 g_set_error (error, GSK_G_ERROR_DOMAIN, GSK_ERROR_FOREIGN_ADDRESS,
572 "error making a native socket-address for %s",
573 g_type_name (G_OBJECT_CLASS_TYPE (class)));
574 return FALSE;
575 }
576 return TRUE;
577 }
578
579 /**
580 * gsk_socket_address_to_string:
581 * @address: a socket address.
582 *
583 * Convert a socket-address to a newly allocated string,
584 * which the caller must free.
585 *
586 * returns: a string for the user to free.
587 */
588 char *
gsk_socket_address_to_string(GskSocketAddress * address)589 gsk_socket_address_to_string (GskSocketAddress *address)
590 {
591 GskSocketAddressClass *class = GSK_SOCKET_ADDRESS_GET_CLASS (address);
592 return class->to_string (address);
593 }
594
595 /**
596 * gsk_socket_address_ipv4_new:
597 * @ip_address: the 4-byte IP address
598 * @port: the port number.
599 *
600 * Allocate a new IPv4 address given a numeric IP and port number.
601 *
602 * returns: a new GskSocketAddress
603 */
604 GskSocketAddress *
gsk_socket_address_ipv4_new(const guint8 * ip_address,guint16 port)605 gsk_socket_address_ipv4_new (const guint8 *ip_address,
606 guint16 port)
607 {
608 GskSocketAddressIpv4 *ipv4;
609 ipv4 = g_object_new (GSK_TYPE_SOCKET_ADDRESS_IPV4, NULL);
610 ipv4->ip_port = port;
611 memcpy (ipv4->ip_address, ip_address, 4);
612 return GSK_SOCKET_ADDRESS (ipv4);
613 }
614
615 /**
616 * gsk_socket_address_equals:
617 * @address_a_ptr: a pointer to a #GskSocketAddress.
618 * @address_b_ptr: a pointer to a #GskSocketAddress.
619 *
620 * This function is a GEqualFunc which can determine
621 * if two socket address are the same.
622 * This is principally used with #gsk_socket_address_hash
623 * to make a hash-table mapping from socket-addresses.
624 *
625 * (This just uses the virtual method of GskSocketAddressClass)
626 *
627 * returns: whether the addresses are equal.
628 */
629 gboolean
gsk_socket_address_equals(gconstpointer address_a_ptr,gconstpointer address_b_ptr)630 gsk_socket_address_equals (gconstpointer address_a_ptr,
631 gconstpointer address_b_ptr)
632 {
633 GskSocketAddress *address_a = (GskSocketAddress *) address_a_ptr;
634 GskSocketAddress *address_b = (GskSocketAddress *) address_b_ptr;
635 GskSocketAddressClass *class;
636 GType type_a, type_b;
637 g_return_val_if_fail (GSK_IS_SOCKET_ADDRESS (address_a)
638 && GSK_IS_SOCKET_ADDRESS (address_b), FALSE);
639 type_a = G_OBJECT_TYPE (address_a);
640 type_b = G_OBJECT_TYPE (address_b);
641 if (type_a != type_b)
642 return FALSE;
643 class = GSK_SOCKET_ADDRESS_GET_CLASS (address_a);
644 return (*class->equals) (address_a, address_b);
645 }
646
647 /**
648 * gsk_socket_address_hash:
649 * @address_ptr: a pointer to a #GskSocketAddress.
650 *
651 * This function is a GHashFunc which can determine
652 * a hash value for a socket-address.
653 *
654 * This is principally used with #gsk_socket_address_equals
655 * to make a hash-table mapping from socket-addresses.
656 *
657 * (This just uses the virtual method of GskSocketAddressClass)
658 *
659 * returns: the hash value for the socket-address.
660 */
661 guint
gsk_socket_address_hash(gconstpointer address_ptr)662 gsk_socket_address_hash (gconstpointer address_ptr)
663 {
664 GskSocketAddress *address = (GskSocketAddress *) address_ptr;
665 GskSocketAddressClass *class;
666 g_return_val_if_fail (GSK_IS_SOCKET_ADDRESS (address), 0);
667 class = GSK_SOCKET_ADDRESS_GET_CLASS (address);
668 return (*class->hash) (address);
669 }
670
671 /* --- protected methods --- */
672 /**
673 * gsk_socket_address_register_subclass:
674 * @klass: a concrete derived class.
675 *
676 * Add the class to a per address-family hash table
677 * for use converting from native.
678 */
679 void
gsk_socket_address_register_subclass(GskSocketAddressClass * klass)680 gsk_socket_address_register_subclass (GskSocketAddressClass *klass)
681 {
682 GType type = G_OBJECT_CLASS_TYPE (klass);
683 N2G_WRITE_LOCK ();
684 if (native_to_gtype == NULL)
685 native_to_gtype = g_hash_table_new (NULL, NULL);
686 g_hash_table_insert (native_to_gtype,
687 GUINT_TO_POINTER (klass->address_family),
688 (gpointer) type);
689 N2G_WRITE_UNLOCK ();
690 }
691
692 /* --- public: a few useful quarks, for use with g_object_set_qdata --- */
693 GQuark
gsk_socket_address_get_remote_quark()694 gsk_socket_address_get_remote_quark()
695 {
696 static GQuark rv = 0;
697 if (rv == 0)
698 rv = g_quark_from_static_string ("gsk-socket-address-remote-quark");
699 return rv;
700 }
701
702 GQuark
gsk_socket_address_get_local_quark()703 gsk_socket_address_get_local_quark()
704 {
705 static GQuark rv = 0;
706 if (rv == 0)
707 rv = g_quark_from_static_string ("gsk-socket-address-local-quark");
708 return rv;
709 }
710
711 /* Deprecated. included for binary compatibility */
712 #undef gsk_socket_address_new_local
gsk_socket_address_new_local(const char * path)713 GskSocketAddress *gsk_socket_address_new_local (const char *path)
714 {
715 return gsk_socket_address_local_new (path);
716 }
717 #undef gsk_socket_address_new_ethernet
gsk_socket_address_new_ethernet(const guint8 * mac_addr)718 GskSocketAddress *gsk_socket_address_new_ethernet (const guint8 *mac_addr)
719 {
720 return gsk_socket_address_ethernet_new (mac_addr);
721 }
722
723