Ticket #1798: 0001-Implement-support-for-IPv6.patch
| File 0001-Implement-support-for-IPv6.patch, 26.6 KB (added by mstapelberg, 3 years ago) |
|---|
-
MANIFEST
From 688231c304b1ee922bf1d693ad9e1fd33ebff52e Mon Sep 17 00:00:00 2001 From: Michael Stapelberg <michael@stapelberg.de> Date: Wed, 22 Sep 2010 17:41:58 +0200 Subject: [PATCH] Implement support for IPv6 connect() and bind() use an Addrinfo PMC (contains multiple socket addresses in the right order [RFC 3484]) instead of a Sockaddr PMC. It is no longer necessary to create the socket before calling bind() or connect() as both need to create sockets with the appropriate address family on their own. Also, the Sockaddr PMC internally uses a struct sockaddr_storage in combination with a length field instead of an struct sockaddr_in. This commit also implements the local_address and remote_address methods for the Socket PMC. The Sockaddr PMC can now be converted to string. --- MANIFEST | 1 + MANIFEST.generated | 2 + include/parrot/io_unix.h | 44 ++++++- src/io/socket_unix.c | 292 ++++++++++++++++++++++++++++++++++++++++------ src/pmc/addrinfo.pmc | 140 ++++++++++++++++++++++ src/pmc/sockaddr.pmc | 54 +++++++-- src/pmc/socket.pmc | 46 +++++++- 7 files changed, 525 insertions(+), 54 deletions(-) create mode 100644 src/pmc/addrinfo.pmc diff --git a/MANIFEST b/MANIFEST index c5a941b..90f0095 100644
a b 1347 1347 src/pbc_dump.c [] 1348 1348 src/pbc_merge.c [] 1349 1349 src/pmc.c [] 1350 src/pmc/addrinfo.pmc [] 1350 1351 src/pmc/addrregistry.pmc [] 1351 1352 src/pmc/arrayiterator.pmc [] 1352 1353 src/pmc/bigint.pmc [] -
MANIFEST.generated
diff --git a/MANIFEST.generated b/MANIFEST.generated index f6fadae..365d0f4 100644
a b 37 37 include/parrot/platform.h [main]include 38 38 include/parrot/platform_limits.h [devel]include 39 39 include/parrot/vtable.h [main]include 40 include/pmc/pmc_addrinfo.h [devel]include 40 41 include/pmc/pmc_addrregistry.h [devel]include 41 42 include/pmc/pmc_arrayiterator.h [devel]include 42 43 include/pmc/pmc_bigint.h [devel]include … … 333 334 src/nci.c [] 334 335 src/null_config.c [] 335 336 src/parrot_config.c [] 337 src/pmc/addrinfo.dump [devel]src 336 338 src/pmc/addrregistry.dump [devel]src 337 339 src/pmc/arrayiterator.dump [devel]src 338 340 src/pmc/bigint.dump [devel]src -
include/parrot/io_unix.h
diff --git a/include/parrot/io_unix.h b/include/parrot/io_unix.h index 7cc8ee2..b97e288 100644
a b 182 182 FUNC_MODIFIES(*socket); 183 183 184 184 INTVAL Parrot_io_bind_unix(PARROT_INTERP, 185 ARGMOD(PMC *sock et),185 ARGMOD(PMC *sock), 186 186 ARGMOD(PMC *sockaddr)) 187 187 __attribute__nonnull__(1) 188 188 __attribute__nonnull__(2) 189 189 __attribute__nonnull__(3) 190 FUNC_MODIFIES(*sock et)190 FUNC_MODIFIES(*sock) 191 191 FUNC_MODIFIES(*sockaddr); 192 192 193 193 INTVAL Parrot_io_connect_unix(PARROT_INTERP, 194 ARGMOD(PMC *sock et),194 ARGMOD(PMC *sock), 195 195 ARGIN(PMC *r)) 196 196 __attribute__nonnull__(1) 197 197 __attribute__nonnull__(2) 198 198 __attribute__nonnull__(3) 199 FUNC_MODIFIES(*socket); 199 FUNC_MODIFIES(*sock); 200 201 PARROT_WARN_UNUSED_RESULT 202 PARROT_CANNOT_RETURN_NULL 203 PMC * Parrot_io_getaddrinfo(PARROT_INTERP, 204 ARGIN(STRING *addr), 205 INTVAL port, 206 INTVAL protocol, 207 INTVAL family, 208 INTVAL passive) 209 __attribute__nonnull__(1) 210 __attribute__nonnull__(2); 200 211 201 212 INTVAL Parrot_io_listen_unix(SHIM_INTERP, ARGMOD(PMC *socket), INTVAL sec) 202 213 __attribute__nonnull__(2) 203 214 FUNC_MODIFIES(*socket); 204 215 216 PARROT_WARN_UNUSED_RESULT 217 PARROT_CANNOT_RETURN_NULL 218 PMC * Parrot_io_local_address(PARROT_INTERP, ARGIN(PMC *sock)) 219 __attribute__nonnull__(1) 220 __attribute__nonnull__(2); 221 205 222 INTVAL Parrot_io_poll_unix(SHIM_INTERP, 206 223 ARGMOD(PMC *socket), 207 224 int which, … … 219 236 FUNC_MODIFIES(*socket) 220 237 FUNC_MODIFIES(*s); 221 238 239 PARROT_WARN_UNUSED_RESULT 240 PARROT_CANNOT_RETURN_NULL 241 PMC * Parrot_io_remote_address(PARROT_INTERP, ARGIN(PMC *sock)) 242 __attribute__nonnull__(1) 243 __attribute__nonnull__(2); 244 222 245 INTVAL Parrot_io_send_unix(SHIM_INTERP, 223 246 ARGMOD(PMC *socket), 224 247 ARGMOD(STRING *s)) … … 248 271 , PARROT_ASSERT_ARG(socket)) 249 272 #define ASSERT_ARGS_Parrot_io_bind_unix __attribute__unused__ int _ASSERT_ARGS_CHECK = (\ 250 273 PARROT_ASSERT_ARG(interp) \ 251 , PARROT_ASSERT_ARG(sock et) \274 , PARROT_ASSERT_ARG(sock) \ 252 275 , PARROT_ASSERT_ARG(sockaddr)) 253 276 #define ASSERT_ARGS_Parrot_io_connect_unix __attribute__unused__ int _ASSERT_ARGS_CHECK = (\ 254 277 PARROT_ASSERT_ARG(interp) \ 255 , PARROT_ASSERT_ARG(sock et) \278 , PARROT_ASSERT_ARG(sock) \ 256 279 , PARROT_ASSERT_ARG(r)) 280 #define ASSERT_ARGS_Parrot_io_getaddrinfo __attribute__unused__ int _ASSERT_ARGS_CHECK = (\ 281 PARROT_ASSERT_ARG(interp) \ 282 , PARROT_ASSERT_ARG(addr)) 257 283 #define ASSERT_ARGS_Parrot_io_listen_unix __attribute__unused__ int _ASSERT_ARGS_CHECK = (\ 258 284 PARROT_ASSERT_ARG(socket)) 285 #define ASSERT_ARGS_Parrot_io_local_address __attribute__unused__ int _ASSERT_ARGS_CHECK = (\ 286 PARROT_ASSERT_ARG(interp) \ 287 , PARROT_ASSERT_ARG(sock)) 259 288 #define ASSERT_ARGS_Parrot_io_poll_unix __attribute__unused__ int _ASSERT_ARGS_CHECK = (\ 260 289 PARROT_ASSERT_ARG(socket)) 261 290 #define ASSERT_ARGS_Parrot_io_recv_unix __attribute__unused__ int _ASSERT_ARGS_CHECK = (\ 262 291 PARROT_ASSERT_ARG(interp) \ 263 292 , PARROT_ASSERT_ARG(socket) \ 264 293 , PARROT_ASSERT_ARG(s)) 294 #define ASSERT_ARGS_Parrot_io_remote_address __attribute__unused__ int _ASSERT_ARGS_CHECK = (\ 295 PARROT_ASSERT_ARG(interp) \ 296 , PARROT_ASSERT_ARG(sock)) 265 297 #define ASSERT_ARGS_Parrot_io_send_unix __attribute__unused__ int _ASSERT_ARGS_CHECK = (\ 266 298 PARROT_ASSERT_ARG(socket) \ 267 299 , PARROT_ASSERT_ARG(s)) -
src/io/socket_unix.c
diff --git a/src/io/socket_unix.c b/src/io/socket_unix.c index 9dcb8f9..cc70398 100644
a b 31 31 #include "parrot/parrot.h" 32 32 #include "io_private.h" 33 33 #include "pmc/pmc_socket.h" 34 #include "pmc/pmc_sockaddr.h" 34 35 35 36 #ifdef PIO_OS_UNIX 36 37 … … 41 42 /* HEADERIZER BEGIN: static */ 42 43 /* Don't modify between HEADERIZER BEGIN / HEADERIZER END. Your changes will be lost. */ 43 44 45 static void get_addrinfo(PARROT_INTERP, 46 ARGIN(PMC * addrinfo), 47 ARGIN(const char *host), 48 int port, 49 int protocol, 50 int family, 51 int passive) 52 __attribute__nonnull__(1) 53 __attribute__nonnull__(2) 54 __attribute__nonnull__(3); 55 44 56 static void get_sockaddr_in(PARROT_INTERP, 45 57 ARGIN(PMC * sockaddr), 46 58 ARGIN(const char* host), … … 49 61 __attribute__nonnull__(2) 50 62 __attribute__nonnull__(3); 51 63 64 #define ASSERT_ARGS_get_addrinfo __attribute__unused__ int _ASSERT_ARGS_CHECK = (\ 65 PARROT_ASSERT_ARG(interp) \ 66 , PARROT_ASSERT_ARG(addrinfo) \ 67 , PARROT_ASSERT_ARG(host)) 52 68 #define ASSERT_ARGS_get_sockaddr_in __attribute__unused__ int _ASSERT_ARGS_CHECK = (\ 53 69 PARROT_ASSERT_ARG(interp) \ 54 70 , PARROT_ASSERT_ARG(sockaddr) \ … … 59 75 /* 60 76 static void get_sockaddr_in(PARROT_INTERP, ARGIN(PMC * sockaddr), 61 77 ARGIN(const char* host), ARGIN(int port)); 78 static void 79 get_addrinfo(PARROT_INTERP, ARGIN(PMC * addrinfo), ARGIN(const char *host), ARGIN(int port)); 62 80 */ 63 81 64 82 /* … … 107 125 return sockaddr; 108 126 } 109 127 128 /* 129 130 =item C<PMC * Parrot_io_getaddrinfo(PARROT_INTERP, STRING *addr, INTVAL port, 131 INTVAL protocol, INTVAL family, INTVAL passive)> 132 133 C<Parrot_io_getaddrinfo()> calls get_addrinfo() to convert hostnames or IP 134 addresses to sockaddrs (and more) and returns an Addrinfo PMC which can be 135 passed to C<Parrot_io_connect_unix()> or C<Parrot_io_bind_unix()>. 136 137 =cut 138 139 */ 140 141 /* TODO: where to move this to? originally from src/io/socket_api.c */ 142 static int pio_pf[PIO_PF_MAX+1] = { 143 #ifdef PF_LOCAL 144 PF_LOCAL, /* PIO_PF_LOCAL */ 145 #else 146 -1, /* PIO_PF_LOCAL */ 147 #endif 148 #ifdef PF_UNIX 149 PF_UNIX, /* PIO_PF_UNIX */ 150 #else 151 -1, /* PIO_PF_UNIX */ 152 #endif 153 #ifdef PF_INET 154 PF_INET, /* PIO_PF_INET */ 155 #else 156 -1, /* PIO_PF_INET */ 157 #endif 158 #ifdef PF_INET6 159 PF_INET6, /* PIO_PF_INET6 */ 160 #else 161 -1, /* PIO_PF_INET6 */ 162 #endif 163 }; 164 165 PARROT_WARN_UNUSED_RESULT 166 PARROT_CANNOT_RETURN_NULL 167 PMC * 168 Parrot_io_getaddrinfo(PARROT_INTERP, ARGIN(STRING *addr), INTVAL port, INTVAL protocol, INTVAL family, INTVAL passive) 169 { 170 ASSERT_ARGS(Parrot_io_getaddrinfo) 171 172 char * const s = Parrot_str_to_cstring(interp, addr); 173 PMC * const addrinfo = Parrot_pmc_new(interp, enum_class_Addrinfo); 174 175 /* set family: 0 means any (AF_INET or AF_INET6) for getaddrinfo, so treat 176 * it specially */ 177 int fam = (family != 0 ? pio_pf[family] : 0); 178 179 get_addrinfo(interp, addrinfo, s, port, protocol, fam, passive); 180 Parrot_str_free_cstring(s); 181 return addrinfo; 182 } 183 184 185 /* 186 187 =item C<PMC * Parrot_io_remote_address(PARROT_INTERP, PMC *sock)> 188 189 C<Parrot_io_remote_address()> returns the remote address of the given sock 190 PMC. It can be used to find out to which address the connection was actually 191 established (in case of the remote server having multiple IPv4 and/or IPv6 192 addresses. 193 194 =cut 195 196 */ 197 PARROT_WARN_UNUSED_RESULT 198 PARROT_CANNOT_RETURN_NULL 199 PMC * 200 Parrot_io_remote_address(PARROT_INTERP, ARGIN(PMC *sock)) 201 { 202 ASSERT_ARGS(Parrot_io_remote_address) 203 204 PMC * const addrinfo = VTABLE_clone(interp, PARROT_SOCKET(sock)->remote); 205 206 return addrinfo; 207 } 208 209 /* 210 211 =item C<PMC * Parrot_io_local_address(PARROT_INTERP, PMC *sock)> 212 213 C<Parrot_io_local_address()> returns the local address of the given sock 214 PMC. It can be used to find out to which address the socket was actually 215 bound (when binding to "localhost" without explicitly specifying an address 216 family, for example). 217 218 =cut 219 220 */ 221 PARROT_WARN_UNUSED_RESULT 222 PARROT_CANNOT_RETURN_NULL 223 PMC * 224 Parrot_io_local_address(PARROT_INTERP, ARGIN(PMC *sock)) 225 { 226 ASSERT_ARGS(Parrot_io_local_address) 227 228 PMC * const addrinfo = VTABLE_clone(interp, PARROT_SOCKET(sock)->local); 229 230 return addrinfo; 231 } 232 110 233 111 234 /* 112 235 … … 139 262 140 263 /* 141 264 142 =item C<INTVAL Parrot_io_connect_unix(PARROT_INTERP, PMC *sock et, PMC *r)>265 =item C<INTVAL Parrot_io_connect_unix(PARROT_INTERP, PMC *sock, PMC *r)> 143 266 144 Connects C<*io>'s socket to address C<*r>. 267 Takes the Addrinfo PMC C<*r> and tries to establish a connection. A new socket 268 PMC will be created because the Addrinfo may contain addresses of multiple 269 families (IPv4 and IPv6). 145 270 146 271 =cut 147 272 148 273 */ 149 274 150 275 INTVAL 151 Parrot_io_connect_unix(PARROT_INTERP, ARGMOD(PMC *sock et), ARGIN(PMC *r))276 Parrot_io_connect_unix(PARROT_INTERP, ARGMOD(PMC *sock), ARGIN(PMC *r)) 152 277 { 153 278 ASSERT_ARGS(Parrot_io_connect_unix) 154 const Parrot_Socket_attributes * const io = PARROT_SOCKET(socket); 279 const Parrot_Socket_attributes * const io = PARROT_SOCKET(sock); 280 struct addrinfo *res = VTABLE_get_pointer(interp, r); 281 struct addrinfo *walk; 282 int fd = -1; 283 int i = 1; 155 284 156 285 if (!r) 157 286 return -1; 158 287 159 PARROT_SOCKET(socket)->remote = r; 288 289 for (walk = res; walk != NULL; walk = walk->ai_next) { 290 fd = socket(walk->ai_family, walk->ai_socktype, walk->ai_protocol); 291 if (fd < 0) { 292 /* Cannot create socket. Not necessarily an error, for example not 293 * on FreeBSD, where getaddrinfo() returns IPv6 addresses even 294 * when the libc does not offer IPv6 support and thus fails in 295 * socket(). */ 296 continue; 297 } 298 299 if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &i, sizeof(i)) == -1) { 300 perror("Error setting SO_REUSEADDR:"); 301 continue; 302 } 303 304 /* XXX: this effectively overwrites any previously set sockets. is that alright? */ 305 Parrot_io_set_os_handle(interp, sock, fd); 160 306 161 307 AGAIN: 162 if ((connect(io->os_handle, (struct sockaddr *)SOCKADDR_REMOTE(socket), 163 sizeof (struct sockaddr_in))) != 0) { 164 switch (errno) { 165 case EINTR: 166 goto AGAIN; 167 case EINPROGRESS: 168 goto AGAIN; 169 case EISCONN: 170 return 0; 171 default: 172 return -1; 308 if (connect(fd, walk->ai_addr, walk->ai_addrlen) != 0) { 309 switch (errno) { 310 case EINTR: 311 goto AGAIN; 312 case EINPROGRESS: 313 goto AGAIN; 314 case EISCONN: 315 break; 316 default: 317 close(fd); 318 fd = -1; 319 continue; 320 } 173 321 } 322 323 PARROT_SOCKET(sock)->remote = Parrot_pmc_new(interp, enum_class_Sockaddr); 324 325 VTABLE_set_pointer(interp, PARROT_SOCKET(sock)->remote, walk); 326 return 0; 174 327 } 175 328 176 return 0; 329 if (fd == -1) 330 return -1; 177 331 } 178 332 179 333 /* 180 334 181 =item C<INTVAL Parrot_io_bind_unix(PARROT_INTERP, PMC *sock et, PMC *sockaddr)>335 =item C<INTVAL Parrot_io_bind_unix(PARROT_INTERP, PMC *sock, PMC *sockaddr)> 182 336 183 Binds C<*io>'s socket to the local address and port specified by C<*l>. 337 Takes the Addrinfo PMC C<*sockaddr> and creates a listening socket. A new 338 socket needs to be created because C<*sockaddr> may contain addresses of 339 multiple families (IPv4 and IPv6). An example is binding to "localhost" 340 which resolves to ::1 and 127.0.0.1. If you are on FreeBSD and have no 341 IPv6 support, the first attempt to create a socket and bind it would fail. 184 342 185 343 =cut 186 344 187 345 */ 188 346 189 347 INTVAL 190 Parrot_io_bind_unix(PARROT_INTERP, ARGMOD(PMC *sock et), ARGMOD(PMC *sockaddr))348 Parrot_io_bind_unix(PARROT_INTERP, ARGMOD(PMC *sock), ARGMOD(PMC *sockaddr)) 191 349 { 192 350 ASSERT_ARGS(Parrot_io_bind_unix) 193 const Parrot_Socket_attributes * const io = PARROT_SOCKET(socket); 194 struct sockaddr_in * saddr; 351 const Parrot_Socket_attributes * const io = PARROT_SOCKET(sock); 352 struct addrinfo *res = VTABLE_get_pointer(interp, sockaddr); 353 struct addrinfo *walk; 354 int fd = -1; 355 int i = 1; 195 356 196 357 if (!sockaddr) 197 358 return -1; 198 359 199 PARROT_SOCKET(socket)->local = sockaddr; 360 for (walk = res; walk != NULL; walk = walk->ai_next) { 361 fd = socket(walk->ai_family, walk->ai_socktype, walk->ai_protocol); 362 if (fd < 0) { 363 /* Cannot create socket. Not necessarily an error, for example not 364 * on FreeBSD, where getaddrinfo() returns IPv6 addresses even 365 * when the libc does not offer IPv6 support and thus fails in 366 * socket(). */ 367 continue; 368 } 200 369 201 saddr = SOCKADDR_LOCAL(socket); 370 if (walk->ai_family == AF_INET6) { 371 if (setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &i, sizeof(i)) == -1) { 372 perror("Error setting IPV6_V6ONLY:"); 373 continue; 374 } 375 } 202 376 203 if ((bind(io->os_handle, (struct sockaddr *) saddr, 204 sizeof (struct sockaddr_in))) == -1) { 205 return -1; 377 /* XXX: this effectively overwrites any previously set sockets. is that alright? */ 378 Parrot_io_set_os_handle(interp, sock, fd); 379 380 if (bind(fd, walk->ai_addr, walk->ai_addrlen) != 0) { 381 close(fd); 382 fd = -1; 383 continue; 384 } 385 386 PARROT_SOCKET(sock)->local = Parrot_pmc_new(interp, enum_class_Sockaddr); 387 388 VTABLE_set_pointer(interp, PARROT_SOCKET(sock)->local, walk); 389 return 0; 206 390 } 207 391 208 return 0; 392 if (fd == -1) 393 return -1; 209 394 } 210 395 211 396 /* … … 249 434 Parrot_Socket_attributes * io = PARROT_SOCKET(socket); 250 435 PMC * newio = Parrot_io_new_socket_pmc(interp, 251 436 PIO_F_SOCKET | PIO_F_READ|PIO_F_WRITE); 252 Parrot_Socklen_t addrlen = sizeof (struct sockaddr_in); 253 struct sockaddr_in *saddr; 437 Parrot_Socklen_t addrlen = sizeof (struct sockaddr_storage); 438 Parrot_Sockaddr_attributes *remotedata; 439 struct sockaddr_storage *saddr; 254 440 int newsock; 255 441 256 442 PARROT_SOCKET(newio)->local = PARROT_SOCKET(socket)->local; … … 263 449 return PMCNULL; 264 450 } 265 451 266 PARROT_SOCKET(newio)->os_handle = newsock; 452 /* Set the length for the remote sockaddr PMC so that it can distinguish 453 * between sockaddr_in and sockaddr_in6 */ 454 remotedata = PARROT_SOCKADDR(PARROT_SOCKET(newio)->remote); 455 remotedata->len = addrlen; 267 456 268 /* XXX FIXME: Need to do a getsockname and getpeername here to 269 * fill in the sockaddr_in structs for local and peer */ 457 PARROT_SOCKET(newio)->os_handle = newsock; 270 458 271 /* Optionally do a gethostyaddr() to resolve remote IP address. 272 * This should be based on an option set in the master socket */ 459 /* Optionally do a getaddrinfo() to resolve remote IP address. 460 * This should be based on an option set in the master socket. 461 * 462 * XXX: instead of resolving here, we should use the flags for 463 * getnameinfo() in the VTABLE get_string of the Sockaddr PMC. 464 * At the moment, it uses NI_NUMERICHOST, but when called 465 * differently, it will resolve the address. The advantage is 466 * that we only resolve when someone actually accesses the 467 * name. -- Michael Stapelberg */ 273 468 274 469 return newio; 275 470 } … … 480 675 sa->sin_port = htons(port); 481 676 } 482 677 678 static void 679 get_addrinfo(PARROT_INTERP, ARGIN(PMC * addrinfo), ARGIN(const char *host), int port, int protocol, int family, int passive) 680 { 681 ASSERT_ARGS(get_addrinfo) 682 683 struct addrinfo hints; 684 struct addrinfo *res; 685 /* We need to pass the port as a string (because you could also use a 686 * service specification from /etc/services). The highest port is 65535, 687 * so we need 5 characters + trailing null-byte. */ 688 char portstr[6]; 689 int ret; 690 691 memset(&hints, 0, sizeof(struct addrinfo)); 692 hints.ai_protocol = protocol; 693 if (passive) 694 hints.ai_flags = AI_PASSIVE; 695 hints.ai_family = family; 696 snprintf(portstr, sizeof(portstr), "%u", port); 697 698 if ((ret = getaddrinfo(host, portstr, &hints, &res)) != 0) { 699 fprintf(stderr, "getaddrinfo failure: %s\n", gai_strerror(ret)); 700 return; 701 } 702 703 VTABLE_set_pointer(interp, addrinfo, res); 704 } 483 705 484 706 #endif /* PIO_OS_UNIX */ 485 707 -
(a) /dev/null vs. (b) b/src/pmc/addrinfo.pmc
diff --git a/src/pmc/addrinfo.pmc b/src/pmc/addrinfo.pmc new file mode 100644 index 0000000..4618fc0
a b 1 /* 2 Copyright (C) 2008-2009, Parrot Foundation. 3 $Id$ 4 5 =head1 NAME 6 7 src/pmc/addrinfo.pmc - addrinfo holder 8 9 =head1 DESCRIPTION 10 11 The Addrinfo PMC holds a C pointer to a C<struct addrinfo>. 12 13 14 =head2 Vtable Functions 15 16 These are the vtable functions for the Addrinfo class. 17 18 =over 4 19 20 =cut 21 22 */ 23 24 #ifdef __cplusplus 25 extern "C" { 26 #endif 27 struct addrinfo; 28 #ifdef __cplusplus 29 } 30 #endif 31 32 /* HEADERIZER HFILE: none */ 33 /* HEADERIZER BEGIN: static */ 34 /* HEADERIZER END: static */ 35 36 pmclass Addrinfo auto_attrs { 37 ATTR void *pointer; /* The stored pointer. */ 38 39 /* 40 41 =item C<void init()> 42 43 Initializes the pointer object. 44 45 =cut 46 47 */ 48 49 VTABLE void init() { 50 Parrot_Addrinfo_attributes * const pdata_struct = 51 (Parrot_Addrinfo_attributes *) PMC_data(SELF); 52 53 pdata_struct->pointer = NULL; 54 PObj_custom_destroy_SET(SELF); 55 } 56 57 /* 58 59 =item C<void destroy()> 60 61 Destroys the PMC and frees all allocated memory. 62 63 =cut 64 65 */ 66 67 VTABLE void destroy() { 68 Parrot_Addrinfo_attributes * const data = PARROT_ADDRINFO(SELF); 69 70 if (data) { 71 if (data->pointer) 72 freeaddrinfo(data->pointer); 73 data->pointer = NULL; 74 } 75 } 76 77 /* 78 79 =item C<PMC *clone()> 80 81 Creates and returns a clone of the pointer. 82 83 =cut 84 85 */ 86 87 VTABLE PMC *clone() { 88 PMC * const dest = Parrot_pmc_new(INTERP, SELF->vtable->base_type); 89 memcpy(PARROT_ADDRINFO(dest)->pointer, PARROT_ADDRINFO(SELF)->pointer, 90 sizeof (struct sockaddr_storage)); 91 return dest; 92 } 93 94 /* 95 96 =item C<void *get_pointer()> 97 98 Returns the pointer. 99 100 =cut 101 102 */ 103 104 VTABLE void *get_pointer() { 105 Parrot_Addrinfo_attributes * const data = PARROT_ADDRINFO(SELF); 106 return data->pointer; 107 } 108 109 /* 110 111 =item C<void set_pointer(void *)> 112 113 Sets the pointer. 114 115 =cut 116 117 */ 118 119 VTABLE void set_pointer(void *value) { 120 Parrot_Addrinfo_attributes * const data = PARROT_ADDRINFO(SELF); 121 data->pointer = value; 122 } 123 124 } 125 126 /* 127 128 =back 129 130 =cut 131 132 */ 133 134 /* 135 * Local variables: 136 * c-file-style: "parrot" 137 * End: 138 * vim: expandtab shiftwidth=4: 139 */ 140 -
src/pmc/sockaddr.pmc
diff --git a/src/pmc/sockaddr.pmc b/src/pmc/sockaddr.pmc index 6161557..dc1117d 100644
a b 4 4 5 5 =head1 NAME 6 6 7 src/pmc/sockaddr.pmc - sockaddr_in holder7 src/pmc/sockaddr.pmc - sockaddr_in/sockaddr_in6 holder 8 8 9 9 =head1 DESCRIPTION 10 10 11 The Sockaddr PMC holds raw c-pointer to sockaddr_in 11 The Sockaddr PMC holds a C<sockaddr_in> (IPv4) or C<sockaddr_in6> (IPv6) and 12 saves its length (to distinguish C<sockaddr_in> and C<sockaddr_in6>). 12 13 13 14 14 15 =head2 Vtable Functions … … 24 25 #ifdef __cplusplus 25 26 extern "C" { 26 27 #endif 27 struct sockaddr_ in;28 struct sockaddr_storage; 28 29 #ifdef __cplusplus 29 30 } 30 31 #endif … … 35 36 36 37 pmclass Sockaddr auto_attrs { 37 38 ATTR void *pointer; /* The stored pointer. */ 39 ATTR INTVAL len; /* Length of the contents of the sockaddr_storage */ 38 40 39 41 /* 40 42 41 43 =item C<void init()> 42 44 43 Initializes the pointer object.45 Initializes the PMC by allocating a C<sockaddr_storage>. 44 46 45 47 =cut 46 48 … … 51 53 (Parrot_Sockaddr_attributes *) PMC_data(SELF); 52 54 53 55 pdata_struct->pointer = mem_gc_allocate_zeroed_typed(INTERP, 54 struct sockaddr_ in);56 struct sockaddr_storage); 55 57 PObj_custom_destroy_SET(SELF); 56 58 } 57 59 … … 78 80 79 81 =item C<PMC *clone()> 80 82 81 Creates and returns a clone of the pointer. 83 Creates a new Sockaddr PMC with the same contents and length as the current 84 one. 82 85 83 86 =cut 84 87 … … 86 89 87 90 VTABLE PMC *clone() { 88 91 PMC * const dest = Parrot_pmc_new(INTERP, SELF->vtable->base_type); 92 89 93 memcpy(PARROT_SOCKADDR(dest)->pointer, PARROT_SOCKADDR(SELF)->pointer, 90 sizeof (struct sockaddr_in)); 94 sizeof (struct sockaddr_storage)); 95 PARROT_SOCKADDR(dest)->len = PARROT_SOCKADDR(SELF)->len; 91 96 return dest; 92 97 } 93 98 … … 95 100 96 101 =item C<void *get_pointer()> 97 102 98 Returns the pointer.103 Returns a pointer to the C<sockaddr_in> or C<sockaddr_in6>. 99 104 100 105 =cut 101 106 … … 108 113 109 114 /* 110 115 111 =item C< void set_pointer(void *)>116 =item C<STRING *get_string()> 112 117 113 Sets the pointer.118 Returns the string representation of this sockaddr by calling C<getnameinfo(3)>. 114 119 115 120 =cut 116 121 117 122 */ 123 VTABLE STRING *get_string() { 124 Parrot_Sockaddr_attributes * const data = PARROT_SOCKADDR(SELF); 125 if (!data->pointer) 126 return Parrot_sprintf_c(interp, "(?)"); 127 128 struct sockaddr_storage *addr = data->pointer; 129 /* TODO: get hostname, not only numeric */ 130 char buf[INET6_ADDRSTRLEN+1]; 131 getnameinfo((struct sockaddr_storage*)data->pointer, data->len, buf, 132 sizeof(buf), NULL, 0, NI_NUMERICHOST); 133 return Parrot_str_new(interp, buf, 0); 134 } 135 118 136 119 137 /* 138 139 =item C<void set_pointer(void *)> 140 141 Copies a C<sockaddr_in> or C<sockaddr_in6> from the given C<addrinfo> pointer 142 (by accessing its C<ai_addr> and C<ai_addrlen> members). 143 144 =cut 145 146 */ 147 120 148 VTABLE void set_pointer(void *value) { 121 149 Parrot_Sockaddr_attributes * const data = PARROT_SOCKADDR(SELF); 122 return data->pointer; 150 151 struct addrinfo *walk = value; 152 memcpy(data->pointer, walk->ai_addr, walk->ai_addrlen); 153 data->len = walk->ai_addrlen; 123 154 } 124 */125 155 126 156 } 127 157 -
src/pmc/socket.pmc
diff --git a/src/pmc/socket.pmc b/src/pmc/socket.pmc index 1c8971a..cd3a61e 100644
a b 177 177 178 178 /* 179 179 180 =item C<getaddrinfo(STRING * address, INTVAL port, INTVAL protocol, INTVAL family, INTVAL passive)> 181 182 C<getaddrinfo> returns an object representing the result of the 183 C<getaddrinfo(3)> function which consists of multiple socket addresses, 184 including family and protocol. It can be passed to C<bind()> or C<connect()>. 185 186 =cut 187 188 */ 189 METHOD getaddrinfo(STRING * address, INTVAL port, INTVAL protocol, INTVAL family, INTVAL passive) { 190 PMC * res = Parrot_io_getaddrinfo(INTERP, address, port, protocol, family, passive); 191 RETURN(PMC * res); 192 } 193 194 /* 195 196 =item C<remote_address()> 197 198 C<remote_address> returns the remote address of this socket PMC. 199 200 =cut 201 202 */ 203 METHOD remote_address() { 204 PMC * res = Parrot_io_remote_address(INTERP, SELF); 205 RETURN(PMC * res); 206 } 207 208 /* 209 210 =item C<local_address()> 211 212 C<local_address> returns the local address of this socket PMC. 213 214 =cut 215 216 */ 217 METHOD local_address() { 218 PMC * res = Parrot_io_local_address(INTERP, SELF); 219 RETURN(PMC * res); 220 } 221 222 /* 223 180 224 =item C<connect(PMC * address)> 181 225 182 226 Connects a socket object to an address. … … 265 309 =item C<bind(PMC *host)> 266 310 267 311 C<bind> binds a socket object to the port and address specified by an 268 address object (the packed result of C<sockaddr>).312 address object (the result of C<getaddrinfo>). 269 313 270 314 The asynchronous version takes an additional final PMC callback 271 315 argument, and only returns a status object. When the bind operation is
