Skip to content

Commit

Permalink
Merge branch 'mstap-master'
Browse files Browse the repository at this point in the history
  • Loading branch information
leto committed Jan 25, 2011
2 parents 4fe94e4 + 5365f8c commit ff43647
Show file tree
Hide file tree
Showing 11 changed files with 649 additions and 36 deletions.
2 changes: 2 additions & 0 deletions MANIFEST
Expand Up @@ -1907,6 +1907,7 @@ t/pmc/schedulermessage.t [test]
t/pmc/signal.t [test]
t/pmc/sockaddr.t [test]
t/pmc/socket.t [test]
t/pmc/socket_ipv6.t [test]
t/pmc/string.t [test]
t/pmc/stringbuilder.t [test]
t/pmc/stringhandle.t [test]
Expand All @@ -1919,6 +1920,7 @@ t/pmc/testlib/annotations.pir [test]
t/pmc/testlib/number.pasm [test]
t/pmc/testlib/packfile_common.pir [test]
t/pmc/testlib/test_server.pir [test]
t/pmc/testlib/test_server_ipv6.pir [test]
t/pmc/threads.t [test]
t/pmc/timer.t [test]
t/pmc/undef.t [test]
Expand Down
2 changes: 1 addition & 1 deletion config/gen/makefiles/root.in
Expand Up @@ -1621,7 +1621,7 @@ src/platform/generic/math$(O) : src/platform/generic/math.c $(PARROT_H_HEADERS)
src/platform/generic/misc$(O) : src/platform/generic/misc.c $(PARROT_H_HEADERS)

src/platform/generic/socket$(O) : $(PARROT_H_HEADERS) include/pmc/pmc_socket.h \
src/io/io_private.h src/platform/generic/socket.c
src/io/io_private.h include/pmc/pmc_sockaddr.h src/platform/generic/socket.c

src/platform/generic/stat$(O) : src/platform/generic/stat.c $(PARROT_H_HEADERS)

Expand Down
6 changes: 4 additions & 2 deletions include/parrot/platform_interface.h
Expand Up @@ -79,12 +79,14 @@ INTVAL Parrot_io_pipe(PARROT_INTERP, ARGMOD(PIOHANDLE *reader), ARGMOD(PIOHANDLE
* Socket
*/

void Parrot_io_sockaddr_in(PARROT_INTERP, ARGOUT(void *addr), ARGIN(STRING *host), int port);
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);
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_listen(PARROT_INTERP, PIOHANDLE handle, INTVAL sec);
PIOHANDLE Parrot_io_accept(PARROT_INTERP, PIOHANDLE handle, ARGOUT(void *addr));
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);
Expand Down
99 changes: 97 additions & 2 deletions src/io/socket_api.c
Expand Up @@ -294,8 +294,60 @@ 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);

/* 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 = 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 (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &i, sizeof(i)) == -1) {
perror("Error setting SO_REUSEADDR:");
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);
return 0;
}

if (fd == -1)
return -1;
fprintf(stderr, "huh?!\n");
}

if (Parrot_io_socket_is_closed(interp, pmc))
return -1;
if (PMC_IS_NULL(address))
Expand Down Expand Up @@ -323,8 +375,52 @@ 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);

/* Bind to an IPv6 address (UnManagedStruct with an struct addrinfo inside */
if (!PMC_IS_NULL(address) && address->vtable->base_type == enum_class_UnManagedStruct) {
res = 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 (walk->ai_family == AF_INET6) {
if (setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &i, sizeof(i)) == -1) {
perror("Error setting IPV6_V6ONLY:");
continue;
}
}

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

if (bind(fd, walk->ai_addr, walk->ai_addrlen) != 0) {
close(fd);
fd = -1;
continue;
}

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

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

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

}

if (Parrot_io_socket_is_closed(interp, pmc))
return -1;
if (PMC_IS_NULL(address))
Expand Down Expand Up @@ -393,8 +489,7 @@ Parrot_io_accept_handle(PARROT_INTERP, ARGMOD(PMC *pmc))
new_io->local = io->local;
new_io->remote = Parrot_pmc_new(interp, enum_class_Sockaddr);

os_handle = Parrot_io_accept(interp, io->os_handle,
VTABLE_get_pointer(interp, new_io->remote));
os_handle = Parrot_io_accept(interp, io->os_handle, new_io->remote);
/* TODO: error check */
new_io->os_handle = os_handle;

Expand Down

0 comments on commit ff43647

Please sign in to comment.