rktio: dup and socket addresses
This commit is contained in:
parent
9461c0e72a
commit
e9d5260295
|
@ -557,6 +557,39 @@ int main()
|
||||||
check_valid(fd2);
|
check_valid(fd2);
|
||||||
check_valid(!rktio_poll_accept_ready(rktio, lnr));
|
check_valid(!rktio_poll_accept_ready(rktio, lnr));
|
||||||
|
|
||||||
|
{
|
||||||
|
/* Dup'ing and closing old should work as well as using directly */
|
||||||
|
rktio_fd_t *fdx;
|
||||||
|
|
||||||
|
fdx = rktio_dup(rktio, fd);
|
||||||
|
check_valid(fdx);
|
||||||
|
check_valid(rktio_close(rktio, fd));
|
||||||
|
fd = fdx;
|
||||||
|
|
||||||
|
fdx = rktio_dup(rktio, fd2);
|
||||||
|
check_valid(fdx);
|
||||||
|
check_valid(rktio_close(rktio, fd2));
|
||||||
|
fd2 = fdx;
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
char **strs;
|
||||||
|
|
||||||
|
strs = rktio_socket_address(rktio, fd2);
|
||||||
|
check_valid(strs);
|
||||||
|
printf("client: %s %s\n", strs[0], strs[1]);
|
||||||
|
free(strs[0]);
|
||||||
|
free(strs[1]);
|
||||||
|
free(strs);
|
||||||
|
|
||||||
|
strs = rktio_socket_peer_address(rktio, fd2);
|
||||||
|
check_valid(strs);
|
||||||
|
printf("server: %s %s\n", strs[0], strs[1]);
|
||||||
|
free(strs[0]);
|
||||||
|
free(strs[1]);
|
||||||
|
free(strs);
|
||||||
|
}
|
||||||
|
|
||||||
check_read_write_pair(rktio, fd, fd2);
|
check_read_write_pair(rktio, fd, fd2);
|
||||||
|
|
||||||
rktio_listen_stop(rktio, lnr);
|
rktio_listen_stop(rktio, lnr);
|
||||||
|
|
|
@ -38,6 +38,9 @@ int rktio_fd_is_socket(rktio_t *rktio, rktio_fd_t *rfd);
|
||||||
rktio_fd_t *rktio_open(rktio_t *rktio, char *src, int modes);
|
rktio_fd_t *rktio_open(rktio_t *rktio, char *src, int modes);
|
||||||
int rktio_close(rktio_t *rktio, rktio_fd_t *fd);
|
int rktio_close(rktio_t *rktio, rktio_fd_t *fd);
|
||||||
|
|
||||||
|
rktio_fd_t *rktio_dup(rktio_t *rktio, rktio_fd_t *rfd);
|
||||||
|
void rktio_forget(rktio_t *rktio, rktio_fd_t *fd);
|
||||||
|
|
||||||
#define RKTIO_READ_EOF (-1)
|
#define RKTIO_READ_EOF (-1)
|
||||||
#define RKTIO_READ_ERROR (-2)
|
#define RKTIO_READ_ERROR (-2)
|
||||||
#define RKTIO_WRITE_ERROR (-2)
|
#define RKTIO_WRITE_ERROR (-2)
|
||||||
|
@ -89,9 +92,15 @@ int rktio_poll_connect_ready(rktio_t *rktio, rktio_connect_t *conn);
|
||||||
|
|
||||||
int rktio_socket_shutdown(rktio_t *rktio, rktio_fd_t *rfd, int mode);
|
int rktio_socket_shutdown(rktio_t *rktio, rktio_fd_t *rfd, int mode);
|
||||||
|
|
||||||
|
char **rktio_socket_address(rktio_t *rktio, rktio_fd_t *rfd);
|
||||||
|
char **rktio_socket_peer_address(rktio_t *rktio, rktio_fd_t *rfd);
|
||||||
|
|
||||||
/*************************************************/
|
/*************************************************/
|
||||||
/* File-descriptor sets for polling */
|
/* File-descriptor sets for polling */
|
||||||
|
|
||||||
|
/* A poll set is intended for a single use or few uses, as opposed to
|
||||||
|
"long-term" poll sets. */
|
||||||
|
|
||||||
typedef struct rktio_poll_set_t rktio_poll_set_t;
|
typedef struct rktio_poll_set_t rktio_poll_set_t;
|
||||||
|
|
||||||
#define RKTIO_POLL_READ RKTIO_OPEN_READ
|
#define RKTIO_POLL_READ RKTIO_OPEN_READ
|
||||||
|
|
|
@ -884,11 +884,23 @@ int rktio_socket_close(rktio_t *rktio, rktio_fd_t *rfd)
|
||||||
#ifdef RKTIO_SYSTEM_WINDOWS
|
#ifdef RKTIO_SYSTEM_WINDOWS
|
||||||
UNREGISTER_SOCKET(rfd->sock);
|
UNREGISTER_SOCKET(rfd->sock);
|
||||||
closesocket(rfd->sock);
|
closesocket(rfd->sock);
|
||||||
|
free(rfd);
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void rktio_socket_forget(rktio_t *rktio, rktio_fd_t *rfd)
|
||||||
|
{
|
||||||
|
#ifdef RKTIO_SYSTEM_UNIX
|
||||||
|
rktio_forget(rktio, rfd);
|
||||||
|
#endif
|
||||||
|
#ifdef RKTIO_SYSTEM_WINDOWS
|
||||||
|
UNREGISTER_SOCKET(rfd->sock);
|
||||||
|
closesocket(rfd->sock);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
int rktio_socket_poll_write_ready(rktio_t *rktio, rktio_fd_t *rfd)
|
int rktio_socket_poll_write_ready(rktio_t *rktio, rktio_fd_t *rfd)
|
||||||
{
|
{
|
||||||
#ifdef RKTIO_SYSTEM_UNIX
|
#ifdef RKTIO_SYSTEM_UNIX
|
||||||
|
@ -970,6 +982,30 @@ static void init_socket(rktio_socket_t s)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rktio_fd_t *rktio_socket_dup(rktio_t *rktio, rktio_fd_t *rfd)
|
||||||
|
{
|
||||||
|
#ifdef RKTIO_SYSTEM_UNIX
|
||||||
|
return rktio_dup(rktio, rfd);
|
||||||
|
#endif
|
||||||
|
#ifdef RKTIO_SYSTEM_WINDOWS
|
||||||
|
intptr_t nsocket;
|
||||||
|
intptr_t rc;
|
||||||
|
WSAPROTOCOL_INFO protocolInfo;
|
||||||
|
rc = WSADuplicateSocket(rfd->sock, GetCurrentProcessId(), &protocolInfo);
|
||||||
|
if (rc) {
|
||||||
|
get_socket_error();
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
nsocket = WSASocket(FROM_PROTOCOL_INFO, FROM_PROTOCOL_INFO, FROM_PROTOCOL_INFO, &protocolInfo, 0, WSA_FLAG_OVERLAPPED);
|
||||||
|
if (nsocket == INVALID_SOCKET) {
|
||||||
|
get_socket_error();
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
REGISTER_SOCKET(nsocket);
|
||||||
|
return rktio_system_fd(nsocket, rfd->modes);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
intptr_t rktio_socket_read(rktio_t *rktio, rktio_fd_t *rfd, char *buffer, intptr_t len)
|
intptr_t rktio_socket_read(rktio_t *rktio, rktio_fd_t *rfd, char *buffer, intptr_t len)
|
||||||
{
|
{
|
||||||
rktio_socket_t s = rktio_fd_system_fd(rktio, rfd);
|
rktio_socket_t s = rktio_fd_system_fd(rktio, rfd);
|
||||||
|
@ -1530,179 +1566,70 @@ rktio_fd_t *rktio_accept(rktio_t *rktio, rktio_listener_t *listener)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
static char **get_numeric_strings(rktio_t *rktio, void *sa, unsigned int salen)
|
||||||
|
|
||||||
static void mz_getnameinfo(void *sa, int salen,
|
|
||||||
char *host, int hostlen,
|
|
||||||
char *serv, int servlen)
|
|
||||||
{
|
{
|
||||||
|
char **r;
|
||||||
#ifdef HAVE_GETADDRINFO
|
#ifdef HAVE_GETADDRINFO
|
||||||
getnameinfo(sa, salen, host, hostlen, serv, servlen,
|
char host[NI_MAXHOST], serv[NI_MAXSERV];
|
||||||
|
int err;
|
||||||
|
|
||||||
|
err = getnameinfo(sa, salen, host, sizeof(host), serv, sizeof(serv),
|
||||||
NI_NUMERICHOST | NI_NUMERICSERV);
|
NI_NUMERICHOST | NI_NUMERICSERV);
|
||||||
#else
|
#else
|
||||||
if (host) {
|
char host[128], serv[32];
|
||||||
|
{
|
||||||
unsigned char *b;
|
unsigned char *b;
|
||||||
b = (unsigned char *)&((struct sockaddr_in *)sa)->sin_addr;
|
b = (unsigned char *)&((struct sockaddr_in *)sa)->sin_addr;
|
||||||
sprintf(host, "%d.%d.%d.%d", b[0], b[1], b[2], b[3]);
|
sprintf(host, "%d.%d.%d.%d", b[0], b[1], b[2], b[3]);
|
||||||
}
|
}
|
||||||
if (serv) {
|
{
|
||||||
int id;
|
int id;
|
||||||
id = ntohs(((struct sockaddr_in *)sa)->sin_port);
|
id = ntohs(((struct sockaddr_in *)sa)->sin_port);
|
||||||
sprintf(serv, "%d", id);
|
sprintf(serv, "%d", id);
|
||||||
}
|
}
|
||||||
|
err = 0;
|
||||||
#endif
|
#endif
|
||||||
}
|
|
||||||
|
|
||||||
char **rktio_get_addresses()
|
if (!err) {
|
||||||
{
|
r = malloc(sizeof(char*) * 2);
|
||||||
}
|
r[0] = strdup(host);
|
||||||
|
r[1] = strdup(serv);
|
||||||
static int extract_svc_value(char *svc_buf)
|
return r;
|
||||||
{
|
|
||||||
int id = 0, j;
|
|
||||||
for (j = 0; svc_buf[j]; j++) {
|
|
||||||
id = (id * 10) + (svc_buf[j] - '0');
|
|
||||||
}
|
|
||||||
return id;
|
|
||||||
}
|
|
||||||
|
|
||||||
#define SCHEME_LISTEN_PORTP(p) SAME_TYPE(SCHEME_TYPE(p), scheme_listener_type)
|
|
||||||
#define SCHEME_UDP_PORTP(p) SAME_TYPE(SCHEME_TYPE(p), scheme_udp_type)
|
|
||||||
|
|
||||||
static Scheme_Object *tcp_addresses(int argc, Scheme_Object *argv[])
|
|
||||||
{
|
|
||||||
#ifdef USE_TCP
|
|
||||||
rktio_socket_t socket = 0;
|
|
||||||
Scheme_Tcp *tcp = NULL;
|
|
||||||
int closed = 0;
|
|
||||||
Scheme_Object *result[4];
|
|
||||||
int with_ports = 0;
|
|
||||||
int listener = 0;
|
|
||||||
int udp = 0;
|
|
||||||
|
|
||||||
if (SCHEME_OUTPUT_PORTP(argv[0])) {
|
|
||||||
Scheme_Output_Port *op;
|
|
||||||
op = scheme_output_port_record(argv[0]);
|
|
||||||
if (op->sub_type == scheme_tcp_output_port_type)
|
|
||||||
tcp = op->port_data;
|
|
||||||
closed = op->closed;
|
|
||||||
} else if (SCHEME_INPUT_PORTP(argv[0])) {
|
|
||||||
Scheme_Input_Port *ip;
|
|
||||||
ip = scheme_input_port_record(argv[0]);
|
|
||||||
if (ip->sub_type == scheme_tcp_input_port_type)
|
|
||||||
tcp = ip->port_data;
|
|
||||||
closed = ip->closed;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (argc > 1)
|
|
||||||
with_ports = SCHEME_TRUEP(argv[1]);
|
|
||||||
|
|
||||||
if (tcp) {
|
|
||||||
socket = tcp->tcp;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if (SCHEME_LISTEN_PORTP(argv[0])) {
|
|
||||||
listener = 1;
|
|
||||||
socket = ((listener_t *)argv[0])->s[0];
|
|
||||||
} else if (SCHEME_UDP_PORTP(argv[0])) {
|
|
||||||
udp = 1;
|
|
||||||
socket = ((Scheme_UDP *)argv[0])->s;
|
|
||||||
} else {
|
} else {
|
||||||
scheme_wrong_contract("tcp-addresses", "tcp-port?", 0, argc, argv);
|
set_gai_error(err);
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (closed)
|
char **rktio_socket_address(rktio_t *rktio, rktio_fd_t *rfd)
|
||||||
scheme_raise_exn(MZEXN_FAIL_NETWORK,
|
|
||||||
"tcp-addresses: port is closed");
|
|
||||||
|
|
||||||
{
|
{
|
||||||
unsigned int l;
|
char name[RKTIO_SOCK_NAME_MAX_LEN];
|
||||||
char here[RKTIO_SOCK_NAME_MAX_LEN], there[RKTIO_SOCK_NAME_MAX_LEN];
|
unsigned int name_len;
|
||||||
char host_buf[RKTIO_SOCK_HOST_NAME_MAX_LEN];
|
|
||||||
char svc_buf[RKTIO_SOCK_SVC_NAME_MAX_LEN];
|
|
||||||
unsigned int here_len;
|
|
||||||
unsigned int there_len = 0;
|
|
||||||
int peerrc = 0;
|
|
||||||
|
|
||||||
l = sizeof(here);
|
name_len = sizeof(name);
|
||||||
if (getsockname(socket, (struct sockaddr *)here, &l)) {
|
if (getsockname(rktio_fd_system_fd(rktio, rfd), (struct sockaddr *)name, &name_len)) {
|
||||||
scheme_raise_exn(MZEXN_FAIL_NETWORK,
|
get_socket_error();
|
||||||
"tcp-addresses: could not get local address\n"
|
return NULL;
|
||||||
" system error: %E",
|
|
||||||
SOCK_ERRNO());
|
|
||||||
}
|
|
||||||
here_len = l;
|
|
||||||
|
|
||||||
if (!listener) {
|
|
||||||
l = sizeof(there);
|
|
||||||
peerrc = getpeername(socket, (struct sockaddr *)there, &l);
|
|
||||||
if (peerrc && !udp) {
|
|
||||||
scheme_raise_exn(MZEXN_FAIL_NETWORK,
|
|
||||||
"tcp-addresses: could not get peer address\n"
|
|
||||||
" system error: %E",
|
|
||||||
SOCK_ERRNO());
|
|
||||||
}
|
|
||||||
there_len = l;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
scheme_getnameinfo((struct sockaddr *)here, here_len,
|
return get_numeric_strings(rktio, name, name_len);
|
||||||
host_buf, sizeof(host_buf),
|
|
||||||
(with_ports ? svc_buf : NULL),
|
|
||||||
(with_ports ? sizeof(svc_buf) : 0));
|
|
||||||
result[0] = scheme_make_utf8_string(host_buf);
|
|
||||||
if (with_ports) {
|
|
||||||
l = extract_svc_value(svc_buf);
|
|
||||||
result[1] = scheme_make_integer(l);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (listener || (udp && peerrc)) {
|
char **rktio_socket_peer_address(rktio_t *rktio, rktio_fd_t *rfd)
|
||||||
result[with_ports ? 2 : 1] = scheme_make_utf8_string("0.0.0.0");
|
{
|
||||||
result[3] = scheme_make_integer(0);
|
char name[RKTIO_SOCK_NAME_MAX_LEN];
|
||||||
}
|
unsigned int name_len;
|
||||||
else {
|
|
||||||
scheme_getnameinfo((struct sockaddr *)there, there_len,
|
name_len = sizeof(name);
|
||||||
host_buf, sizeof(host_buf),
|
if (getpeername(rktio_fd_system_fd(rktio, rfd), (struct sockaddr *)name, &name_len)) {
|
||||||
(with_ports ? svc_buf : NULL),
|
get_socket_error();
|
||||||
(with_ports ? sizeof(svc_buf) : 0));
|
return NULL;
|
||||||
result[with_ports ? 2 : 1] = scheme_make_utf8_string(host_buf);
|
|
||||||
if (with_ports) {
|
|
||||||
l = extract_svc_value(svc_buf);
|
|
||||||
result[3] = scheme_make_integer(l);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return scheme_values(with_ports ? 4 : 2, result);
|
return get_numeric_strings(rktio, name, name_len);
|
||||||
#else
|
|
||||||
/* First arg can't possibly be right! */
|
|
||||||
scheme_wrong_contract("tcp-addresses", "tcp-port?", 0, argc, argv);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
intptr_t scheme_dup_socket(intptr_t fd) {
|
#if 0
|
||||||
#ifdef USE_TCP
|
|
||||||
# ifdef RKTIO_SYSTEM_WINDOWS
|
|
||||||
intptr_t nsocket;
|
|
||||||
intptr_t rc;
|
|
||||||
WSAPROTOCOL_INFO protocolInfo;
|
|
||||||
rc = WSADuplicateSocket(fd, GetCurrentProcessId(), &protocolInfo);
|
|
||||||
if (rc)
|
|
||||||
return rc;
|
|
||||||
nsocket = WSASocket(FROM_PROTOCOL_INFO, FROM_PROTOCOL_INFO, FROM_PROTOCOL_INFO, &protocolInfo, 0, WSA_FLAG_OVERLAPPED);
|
|
||||||
REGISTER_SOCKET(nsocket);
|
|
||||||
return nsocket;
|
|
||||||
# else
|
|
||||||
intptr_t nfd;
|
|
||||||
do {
|
|
||||||
nfd = dup(fd);
|
|
||||||
} while (nfd == -1 && errno == EINTR);
|
|
||||||
return nfd;
|
|
||||||
# endif
|
|
||||||
#else
|
|
||||||
return -1;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
/*========================================================================*/
|
/*========================================================================*/
|
||||||
/* UDP */
|
/* UDP */
|
||||||
|
|
|
@ -153,6 +153,8 @@ struct pollfd *rktio_get_poll_fd_array(rktio_poll_set_t *fds);
|
||||||
/*========================================================================*/
|
/*========================================================================*/
|
||||||
|
|
||||||
int rktio_socket_close(rktio_t *rktio, rktio_fd_t *rfd);
|
int rktio_socket_close(rktio_t *rktio, rktio_fd_t *rfd);
|
||||||
|
void rktio_socket_forget(rktio_t *rktio, rktio_fd_t *rfd);
|
||||||
|
rktio_fd_t *rktio_socket_dup(rktio_t *rktio, rktio_fd_t *rfd);
|
||||||
|
|
||||||
int rktio_socket_poll_write_ready(rktio_t *rktio, rktio_fd_t *rfd);
|
int rktio_socket_poll_write_ready(rktio_t *rktio, rktio_fd_t *rfd);
|
||||||
int rktio_socket_poll_read_ready(rktio_t *rktio, rktio_fd_t *rfd);
|
int rktio_socket_poll_read_ready(rktio_t *rktio, rktio_fd_t *rfd);
|
||||||
|
|
|
@ -83,7 +83,7 @@ static void init_read_fd(rktio_fd_t *rfd)
|
||||||
th->checking = 0;
|
th->checking = 0;
|
||||||
|
|
||||||
sm = CreateSemaphore(NULL, 0, 1, NULL);
|
sm = CreateSemaphore(NULL, 0, 1, NULL);
|
||||||
th->checking_sema = sm;
|
v th->checking_sema = sm;
|
||||||
sm = CreateSemaphore(NULL, 0, 1, NULL);
|
sm = CreateSemaphore(NULL, 0, 1, NULL);
|
||||||
th->ready_sema = sm;
|
th->ready_sema = sm;
|
||||||
sm = CreateSemaphore(NULL, 1, 1, NULL);
|
sm = CreateSemaphore(NULL, 1, 1, NULL);
|
||||||
|
@ -153,6 +153,41 @@ int rktio_fd_is_socket(rktio_t *rktio, rktio_fd_t *rfd)
|
||||||
return (rfd->modes & RKTIO_OPEN_SOCKET);
|
return (rfd->modes & RKTIO_OPEN_SOCKET);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rktio_fd_t *rktio_dup(rktio_t *rktio, rktio_fd_t *rfd) {
|
||||||
|
#ifdef RKTIO_SYSTEM_UNIX
|
||||||
|
intptr_t nfd;
|
||||||
|
|
||||||
|
do {
|
||||||
|
nfd = dup(rfd->fd);
|
||||||
|
} while (nfd == -1 && errno == EINTR);
|
||||||
|
|
||||||
|
if (nfd == -1) {
|
||||||
|
get_posix_error();
|
||||||
|
return NULL;
|
||||||
|
} else
|
||||||
|
return rktio_system_fd(rktio, nfd, rfd->modes);
|
||||||
|
#endif
|
||||||
|
#ifdef WINDOWS_FILE_HANDLES
|
||||||
|
if (rfd->modes & RKTIO_OPEN_SOCKET) {
|
||||||
|
return rktio_socket_dup(rktio_t *rktio, rktio_fd_t *rfd)
|
||||||
|
} else {
|
||||||
|
HANDLE newhandle;
|
||||||
|
BOOL rc;
|
||||||
|
|
||||||
|
rc = DuplicateHandle(GetCurrentProcess(), rfd->fd,
|
||||||
|
GetCurrentProcess(), &newhandle,
|
||||||
|
0, FALSE, DUPLICATE_SAME_ACCESS);
|
||||||
|
|
||||||
|
if (rc == FALSE) {
|
||||||
|
get_windows_error();
|
||||||
|
return NULL;
|
||||||
|
} else {
|
||||||
|
return rktio_system_fd(rktio, (intptr_t)newhandle, rfd->modes);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
/*************************************************************/
|
/*************************************************************/
|
||||||
/* opening a file fd */
|
/* opening a file fd */
|
||||||
/*************************************************************/
|
/*************************************************************/
|
||||||
|
@ -475,6 +510,17 @@ int rktio_close(rktio_t *rktio, rktio_fd_t *rfd)
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void rktio_forget(rktio_t *rktio, rktio_fd_t *rfd)
|
||||||
|
{
|
||||||
|
#ifdef RKTIO_SYSTEM_WINDOWS
|
||||||
|
if (rfd->modes & RKTIO_OPEN_SOCKET) {
|
||||||
|
rktio_socket_forget(rktio, rfd);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
free(rfd);
|
||||||
|
}
|
||||||
|
|
||||||
/*************************************************************/
|
/*************************************************************/
|
||||||
/* polling */
|
/* polling */
|
||||||
/*************************************************************/
|
/*************************************************************/
|
||||||
|
|
Loading…
Reference in New Issue
Block a user