Skip to content

Commit

Permalink
Merge branch 'nwellnhof/ipv6'
Browse files Browse the repository at this point in the history
  • Loading branch information
nwellnhof committed Jan 26, 2011
2 parents b0e86cd + 3caaa85 commit 958c51a
Show file tree
Hide file tree
Showing 9 changed files with 271 additions and 348 deletions.
9 changes: 7 additions & 2 deletions config/gen/makefiles/root.in
Original file line number Diff line number Diff line change
Expand Up @@ -962,8 +962,13 @@ src/scheduler$(O) : \

src/io/core$(O) : $(PARROT_H_HEADERS) src/io/io_private.h src/io/core.c

src/io/socket_api$(O) : $(PARROT_H_HEADERS) src/io/io_private.h \
src/io/api.str include/pmc/pmc_socket.h src/io/socket_api.c
src/io/socket_api$(O) : \
$(PARROT_H_HEADERS) \
src/io/io_private.h \
src/io/api.str \
include/pmc/pmc_socket.h \
include/pmc/pmc_sockaddr.h \
src/io/socket_api.c

O_FILES = \
$(INTERP_O_FILES) \
Expand Down
11 changes: 4 additions & 7 deletions include/parrot/platform_interface.h
Original file line number Diff line number Diff line change
Expand Up @@ -79,20 +79,17 @@ INTVAL Parrot_io_pipe(PARROT_INTERP, ARGMOD(PIOHANDLE *reader), ARGMOD(PIOHANDLE
* Socket
*/

PMC *
Parrot_io_getaddrinfo(PARROT_INTERP, ARGIN(STRING *addr), INTVAL port, INTVAL protocol, INTVAL family, INTVAL passive);
void Parrot_io_sockaddr_in(PARROT_INTERP, ARGOUT(void *addr), ARGIN(STRING *host), int port, int family);
PMC *Parrot_io_getaddrinfo(PARROT_INTERP, ARGIN(STRING *addr), INTVAL port, INTVAL protocol, INTVAL family, INTVAL passive);
STRING *Parrot_io_getnameinfo(PARROT_INTERP, ARGIN(const void *addr), INTVAL addr_len);
PIOHANDLE Parrot_io_socket(PARROT_INTERP, int fam, int type, int proto);
INTVAL Parrot_io_connect(PARROT_INTERP, PIOHANDLE handle, ARGIN(void *addr));
INTVAL Parrot_io_bind(PARROT_INTERP, PIOHANDLE handle, ARGIN(void *addr));
INTVAL Parrot_io_connect(PARROT_INTERP, PIOHANDLE handle, ARGIN(void *addr), INTVAL addr_len);
INTVAL Parrot_io_bind(PARROT_INTERP, PIOHANDLE handle, ARGIN(void *addr), INTVAL addr_len);
INTVAL Parrot_io_listen(PARROT_INTERP, PIOHANDLE handle, INTVAL sec);
PIOHANDLE Parrot_io_accept(PARROT_INTERP, PIOHANDLE handle, ARGOUT(PMC * remote_addr));
INTVAL Parrot_io_send(PARROT_INTERP, PIOHANDLE handle, ARGIN(const char *buf), size_t len);
INTVAL Parrot_io_recv(PARROT_INTERP, PIOHANDLE handle, ARGOUT(char *buf), size_t len);
INTVAL Parrot_io_poll(PARROT_INTERP, PIOHANDLE handle, int which, int sec, int usec);
INTVAL Parrot_io_close_socket(PARROT_INTERP, PIOHANDLE handle);
PMC *Parrot_io_remote_address(PARROT_INTERP, ARGIN(PMC *sock));
PMC *Parrot_io_local_address(PARROT_INTERP, ARGIN(PMC *sock));

/*
** Math:
Expand Down
18 changes: 0 additions & 18 deletions src/io/io_private.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,17 +29,6 @@ Some ideas from AT&T SFIO.

#include <parrot/io.h>

/* XXX: Parrot config is currently not probing for all headers so
* I'm sticking here rather than parrot.h
*/
#ifdef UNIX
# include <sys/socket.h>
#endif

#ifdef WIN32
# include <ws2tcpip.h>
#endif

/* Buffer flags */
#define PIO_BF_MALLOC 00000001 /* Buffer malloced */
#define PIO_BF_READBUF 00000002 /* Buffer is read-buffer */
Expand All @@ -60,13 +49,6 @@ struct _ParrotIOData {
#define _PIO_STDOUT(i) (((ParrotIOData*)(i)->piodata)->table[PIO_STDOUT_FILENO])
#define _PIO_STDERR(i) (((ParrotIOData*)(i)->piodata)->table[PIO_STDERR_FILENO])

/* Parrot_Socklen_t is used in POSIX accept call */
#if PARROT_HAS_SOCKLEN_T
typedef socklen_t Parrot_Socklen_t;
#else
typedef int Parrot_Socklen_t;
#endif

#endif /* PARROT_IO_PRIVATE_H_GUARD */

/*
Expand Down
148 changes: 58 additions & 90 deletions src/io/socket_api.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ These are the primary interface functions for working with socket objects.
#include "io_private.h"
#include "api.str"
#include "pmc/pmc_socket.h"
#include "pmc/pmc_sockaddr.h"

#include <stdarg.h>

Expand Down Expand Up @@ -211,6 +212,9 @@ Parrot_io_socket_handle(PARROT_INTERP, ARGMOD_NULLOK(PMC *socket), INTVAL fam,
return -1;

SETATTR_Socket_os_handle(interp, new_socket, os_handle);
SETATTR_Socket_family(interp, new_socket, fam);
SETATTR_Socket_type(interp, new_socket, type);
SETATTR_Socket_protocol(interp, new_socket, proto);

return 0;
}
Expand Down Expand Up @@ -294,69 +298,47 @@ INTVAL
Parrot_io_connect_handle(PARROT_INTERP, ARGMOD(PMC *pmc), ARGMOD(PMC *address))
{
ASSERT_ARGS(Parrot_io_connect_handle)
struct addrinfo *res, *walk;
int fd = -1;
int i = 1;
Parrot_Socket_attributes * const io = PARROT_SOCKET(pmc);
int i;

/* Connect to an IPv6 addrinfo if an UnManagedStruct was provided as address */
if (!PMC_IS_NULL(address) && address->vtable->base_type == enum_class_UnManagedStruct) {
res = (struct addrinfo *)VTABLE_get_pointer(interp, address);

for (walk = res; walk != NULL; walk = walk->ai_next) {
fd = socket(walk->ai_family, walk->ai_socktype, walk->ai_protocol);
if (fd < 0) {
/* Cannot create socket. Not necessarily an error, for example not
* on FreeBSD, where getaddrinfo() returns IPv6 addresses even
* when the libc does not offer IPv6 support and thus fails in
* socket(). */
continue;
}
if (Parrot_io_socket_is_closed(interp, pmc))
return -1;
if (PMC_IS_NULL(address))
return -1;

/* Iterate over all addresses if an array is passed */
if (address->vtable->base_type != enum_class_Sockaddr) {
INTVAL len = VTABLE_elements(interp, address);

for (i = 0; i < len; ++i) {
PMC *sa = VTABLE_get_pmc_keyed_int(interp, address, i);
Parrot_Sockaddr_attributes * const sa_data = PARROT_SOCKADDR(sa);
struct sockaddr_storage *ss =
(struct sockaddr_storage *)sa_data->pointer;

if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &i, sizeof (i)) == -1) {
perror("Error setting SO_REUSEADDR:");
if (ss->ss_family != io->family
|| (sa_data->type != io->type
&& sa_data->type != 0)
|| sa_data->protocol != io->protocol)
continue;
}

/* XXX: this effectively overwrites any previously set sockets. is that alright? */
SETATTR_Socket_os_handle(interp, pmc, fd);

AGAIN:
if (connect(fd, walk->ai_addr, walk->ai_addrlen) != 0) {
switch (errno) {
case EINTR:
goto AGAIN;
case EINPROGRESS:
goto AGAIN;
case EISCONN:
break;
default:
close(fd);
fd = -1;
continue;
}
}

PARROT_SOCKET(pmc)->remote = Parrot_pmc_new(interp, enum_class_Sockaddr);

VTABLE_set_pointer(interp, PARROT_SOCKET(pmc)->remote, walk);

io->remote = sa;

Parrot_io_connect(interp, io->os_handle, ss, sa_data->len);

return 0;
}

if (fd == -1)
return -1;
fprintf(stderr, "huh?!\n");
Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_PIO_ERROR,
"No address found for family %d, type %d, proto %d",
io->family, io->type, io->protocol);
}

if (Parrot_io_socket_is_closed(interp, pmc))
return -1;
if (PMC_IS_NULL(address))
return -1;

io->remote = address;

return Parrot_io_connect(interp, io->os_handle,
VTABLE_get_pointer(interp, address));
VTABLE_get_pointer(interp, address),
VTABLE_get_integer(interp, address));
}

/*
Expand All @@ -375,61 +357,47 @@ INTVAL
Parrot_io_bind_handle(PARROT_INTERP, ARGMOD(PMC *pmc), ARGMOD(PMC *address))
{
ASSERT_ARGS(Parrot_io_bind_handle)
struct addrinfo *res, *walk;
int fd = -1;
int i = 1;
Parrot_Socket_attributes * const io = PARROT_SOCKET(pmc);
int i;

/* Bind to an IPv6 address (UnManagedStruct with an struct addrinfo inside */
if (!PMC_IS_NULL(address) && address->vtable->base_type == enum_class_UnManagedStruct) {
res = (struct addrinfo *)VTABLE_get_pointer(interp, address);

for (walk = res; walk != NULL; walk = walk->ai_next) {
fd = socket(walk->ai_family, walk->ai_socktype, walk->ai_protocol);
if (fd < 0) {
/* Cannot create socket. Not necessarily an error, for example not
* on FreeBSD, where getaddrinfo() returns IPv6 addresses even
* when the libc does not offer IPv6 support and thus fails in
* socket(). */
continue;
}
if (Parrot_io_socket_is_closed(interp, pmc))
return -1;
if (PMC_IS_NULL(address))
return -1;

if (walk->ai_family == AF_INET6) {
if (setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &i, sizeof (i)) == -1) {
perror("Error setting IPV6_V6ONLY:");
continue;
}
}
/* Iterate over all addresses if an array is passed */
if (address->vtable->base_type != enum_class_Sockaddr) {
INTVAL len = VTABLE_elements(interp, address);

/* XXX: this effectively overwrites any previously set sockets. is that alright? */
SETATTR_Socket_os_handle(interp, pmc, fd);
for (i = 0; i < len; ++i) {
PMC *sa = VTABLE_get_pmc_keyed_int(interp, address, i);
Parrot_Sockaddr_attributes * const sa_data = PARROT_SOCKADDR(sa);
struct sockaddr_storage *ss =
(struct sockaddr_storage *)sa_data->pointer;

if (bind(fd, walk->ai_addr, walk->ai_addrlen) != 0) {
close(fd);
fd = -1;
if (ss->ss_family != io->family
|| (sa_data->type != io->type
&& sa_data->type != 0)
|| sa_data->protocol != io->protocol)
continue;
}

PARROT_SOCKET(pmc)->local = Parrot_pmc_new(interp, enum_class_Sockaddr);
io->local = sa;

Parrot_io_bind(interp, io->os_handle, ss, sa_data->len);

VTABLE_set_pointer(interp, PARROT_SOCKET(pmc)->local, walk);
return 0;
}

if (fd == -1)
return -1;

Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_PIO_ERROR,
"No address found for family %d, type %d, proto %d",
io->family, io->type, io->protocol);
}

if (Parrot_io_socket_is_closed(interp, pmc))
return -1;
if (PMC_IS_NULL(address))
return -1;

io->local = address;

return Parrot_io_bind(interp, io->os_handle,
VTABLE_get_pointer(interp, address));
VTABLE_get_pointer(interp, address),
VTABLE_get_integer(interp, address));
}

/*
Expand Down
Loading

0 comments on commit 958c51a

Please sign in to comment.