INTVAL Parrot_io_connect_win32(PARROT_INTERP, ARGMOD(PMC *socket), ARGIN(PMC *r)) { ASSERT_ARGS(Parrot_io_connect_win32) const Parrot_Socket_attributes * const io = PARROT_SOCKET(socket); if (!r) return -1; PARROT_SOCKET(socket)->remote = r; AGAIN: if ((connect((int)io->os_handle, (struct sockaddr *)SOCKADDR_REMOTE(socket), sizeof (struct sockaddr_in))) != 0) { switch (errno) { case WSAEINTR: goto AGAIN; case WSAEINPROGRESS: goto AGAIN; case WSAEISCONN: return 0; default: return -1; } } return 0; }
PARROT_WARN_UNUSED_RESULT PARROT_CAN_RETURN_NULL PMC * Parrot_io_accept_win32(PARROT_INTERP, ARGMOD(PMC *socket)) { ASSERT_ARGS(Parrot_io_accept_win32) const Parrot_Socket_attributes * const io = PARROT_SOCKET(socket); PMC * newio = Parrot_io_new_socket_pmc(interp, PIO_F_SOCKET | PIO_F_READ|PIO_F_WRITE); Parrot_Socklen_t addrlen = sizeof (struct sockaddr_in); struct sockaddr_in *saddr; int newsock; PARROT_SOCKET(newio)->local = PARROT_SOCKET(socket)->local; PARROT_SOCKET(newio)->remote = Parrot_pmc_new(interp, enum_class_Sockaddr); saddr = SOCKADDR_REMOTE(newio); newsock = accept((int)io->os_handle, (struct sockaddr *)saddr, &addrlen); if (newsock == -1) { return PMCNULL; } PARROT_SOCKET(newio)->os_handle = (void*)newsock; /* XXX FIXME: Need to do a getsockname and getpeername here to * fill in the sockaddr_in structs for local and peer */ /* Optionally do a gethostyaddr() to resolve remote IP address. * This should be based on an option set in the master socket */ return newio; }
PARROT_EXPORT void Parrot_io_socket_initialize_handle(SHIM_INTERP, ARGMOD(PMC *socket)) { ASSERT_ARGS(Parrot_io_socket_initialize_handle) PARROT_SOCKET(socket)->os_handle = (PIOHANDLE)PIO_INVALID_HANDLE; }
INTVAL Parrot_io_listen_win32(SHIM_INTERP, ARGMOD(PMC *socket), INTVAL sec) { ASSERT_ARGS(Parrot_io_listen_win32) const Parrot_Socket_attributes * const io = PARROT_SOCKET(socket); if ((listen((int)io->os_handle, sec)) == -1) { return -1; } return 0; }
INTVAL Parrot_io_bind_win32(PARROT_INTERP, ARGMOD(PMC *socket), ARGMOD(PMC *sockaddr)) { ASSERT_ARGS(Parrot_io_bind_win32) const Parrot_Socket_attributes * const io = PARROT_SOCKET(socket); struct sockaddr_in * saddr; if (!sockaddr) return -1; PARROT_SOCKET(socket)->local = sockaddr; saddr = SOCKADDR_LOCAL(socket); if ((bind((int)io->os_handle, (struct sockaddr *) saddr, sizeof (struct sockaddr_in))) == -1) { return -1; } return 0; }
PARROT_EXPORT INTVAL Parrot_io_poll_handle(PARROT_INTERP, ARGMOD(PMC *pmc), INTVAL which, INTVAL sec, INTVAL usec) { ASSERT_ARGS(Parrot_io_poll_handle) Parrot_Socket_attributes *io = PARROT_SOCKET(pmc); if (Parrot_io_socket_is_closed(interp, pmc)) Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_PIO_ERROR, "Can't poll closed socket"); return Parrot_io_poll(interp, io->os_handle, which, sec, usec); }
PARROT_EXPORT PARROT_WARN_UNUSED_RESULT INTVAL Parrot_io_send_handle(PARROT_INTERP, ARGMOD(PMC *pmc), ARGMOD(STRING *buf)) { ASSERT_ARGS(Parrot_io_send_handle) Parrot_Socket_attributes *io = PARROT_SOCKET(pmc); if (Parrot_io_socket_is_closed(interp, pmc)) Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_PIO_ERROR, "Can't send to closed socket"); return Parrot_io_send(interp, io->os_handle, buf->strstart, buf->bufused); }
PARROT_EXPORT PARROT_CANNOT_RETURN_NULL STRING * Parrot_io_recv_handle(PARROT_INTERP, ARGMOD(PMC *pmc), size_t len) { ASSERT_ARGS(Parrot_io_recv_handle) Parrot_Socket_attributes *io = PARROT_SOCKET(pmc); STRING *res; INTVAL received; if (Parrot_io_socket_is_closed(interp, pmc)) Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_PIO_ERROR, "Can't recv from closed socket"); /* This must stay ASCII to make Rakudo and UTF-8 work for now */ res = Parrot_str_new_noinit(interp, len); received = Parrot_io_recv(interp, io->os_handle, res->strstart, len); res->bufused = received; res->strlen = received; return res; }
/* =item C<INTVAL Parrot_io_send_win32(PARROT_INTERP, PMC *socket, STRING *s)> Send the message C<*s> to C<*io>'s connected socket. =cut */ INTVAL Parrot_io_send_win32(SHIM_INTERP, ARGMOD(PMC *socket), ARGMOD(STRING *s)) { ASSERT_ARGS(Parrot_io_send_win32) int error, bytes, byteswrote; const Parrot_Socket_attributes * const io = PARROT_SOCKET(socket); bytes = s->bufused; byteswrote = 0; AGAIN: /* * Ignore encoding issues for now. */ if ((error = send((int)io->os_handle, (char *)s->strstart + byteswrote, bytes, 0)) >= 0) { byteswrote += error; bytes -= error; if (!bytes) { return byteswrote; } goto AGAIN;
/* =item C<void Parrot_io_connect_handle(PARROT_INTERP, PMC *pmc, PMC *address)> Connects C<*pmc> to C<*address>. =cut */ PARROT_EXPORT void Parrot_io_connect_handle(PARROT_INTERP, ARGMOD(PMC *pmc), ARGMOD(PMC *address)) { ASSERT_ARGS(Parrot_io_connect_handle) Parrot_Socket_attributes * const io = PARROT_SOCKET(pmc); int i; if (Parrot_io_socket_is_closed(interp, pmc)) Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_PIO_ERROR, "Can't connect closed socket"); if (PMC_IS_NULL(address)) Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_PIO_ERROR, "Address is null"); /* 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);