version 1.5, 2013/11/22 13:49:14
|
version 1.16, 2016/08/18 09:06:31
|
Line 12 terms:
|
Line 12 terms:
|
All of the documentation and software included in the ELWIX and AITNET |
All of the documentation and software included in the ELWIX and AITNET |
Releases is copyrighted by ELWIX - Sofia/Bulgaria <info@elwix.org> |
Releases is copyrighted by ELWIX - Sofia/Bulgaria <info@elwix.org> |
|
|
Copyright 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013 | Copyright 2004 - 2016 |
by Michael Pounov <misho@elwix.org>. All rights reserved. |
by Michael Pounov <misho@elwix.org>. All rights reserved. |
|
|
Redistribution and use in source and binary forms, with or without |
Redistribution and use in source and binary forms, with or without |
Line 51 io_closeClient(sched_task_t *task)
|
Line 51 io_closeClient(sched_task_t *task)
|
{ |
{ |
sock_cli_t *cli = (sock_cli_t*) TASK_ARG(task); |
sock_cli_t *cli = (sock_cli_t*) TASK_ARG(task); |
sock_t *s = (sock_t*) cli->cli_parent; |
sock_t *s = (sock_t*) cli->cli_parent; |
int stat, sock = (int) TASK_DATLEN(task); | int stat; |
|
|
|
schedCancelby(s->sock_root, taskMAX, CRITERIA_ARG, cli, NULL); |
|
|
pthread_mutex_lock(&s->sock_mtx); |
pthread_mutex_lock(&s->sock_mtx); |
TAILQ_REMOVE(&s->sock_cli, cli, cli_node); |
TAILQ_REMOVE(&s->sock_cli, cli, cli_node); |
pthread_mutex_unlock(&s->sock_mtx); |
pthread_mutex_unlock(&s->sock_mtx); |
|
|
schedCancelby(s->sock_root, taskMAX, CRITERIA_ARG, cli, NULL); | if (*cli->cli_name) |
| ioFreePTY(cli->cli_pty, cli->cli_name); |
| if (s->sock_prog) { |
| io_progDetach(s->sock_prog, cli->cli_pty); |
| #if 0 |
| io_progCloseAt(s->sock_prog, cli->cli_pty); |
| #endif |
| cli->cli_pty ^= cli->cli_pty; |
| io_progCheck(s->sock_prog, 42); |
| } |
|
|
if (s->sock_type == SOCK_STREAM) { |
if (s->sock_type == SOCK_STREAM) { |
shutdown(sock, SHUT_RDWR); | shutdown(cli->cli_fd, SHUT_RDWR); |
close(sock); | close(cli->cli_fd); |
} |
} |
AIT_FREE_VAL(&cli->cli_buf[1]); |
AIT_FREE_VAL(&cli->cli_buf[1]); |
AIT_FREE_VAL(&cli->cli_buf[0]); |
AIT_FREE_VAL(&cli->cli_buf[0]); |
|
|
if (cli->cli_pid > 0) { |
if (cli->cli_pid > 0) { |
kill(cli->cli_pid, SIGTERM); | kill(cli->cli_pid, SIGKILL); |
while (waitpid(cli->cli_pid, &stat, WNOHANG) > 0) { |
while (waitpid(cli->cli_pid, &stat, WNOHANG) > 0) { |
usleep(1000); |
usleep(1000); |
kill(cli->cli_pid, SIGTERM); | kill(cli->cli_pid, SIGKILL); |
} |
} |
} |
} |
|
|
Line 123 io_acceptClient(sched_task_t *task)
|
Line 134 io_acceptClient(sched_task_t *task)
|
AIT_SET_BUFSIZ(&cli->cli_buf[1], 0, AIT_LEN(&s->sock_buf)); |
AIT_SET_BUFSIZ(&cli->cli_buf[1], 0, AIT_LEN(&s->sock_buf)); |
|
|
schedRead(TASK_ROOT(task), cli->cli_func, cli, cli->cli_fd, TASK_ARG(task), 0); |
schedRead(TASK_ROOT(task), cli->cli_func, cli, cli->cli_fd, TASK_ARG(task), 0); |
ioUpdTimerSocket(cli, NULL); | ioUpdTimerSocket(cli); |
end: |
end: |
schedReadSelf(task); |
schedReadSelf(task); |
taskExit(task, NULL); |
taskExit(task, NULL); |
Line 132 end:
|
Line 143 end:
|
static void * |
static void * |
io_txNet(sched_task_t *task) |
io_txNet(sched_task_t *task) |
{ |
{ |
int wlen; | int wlen, ret, len = TASK_DATLEN(task); |
sock_cli_t *cli = TASK_ARG(task); |
sock_cli_t *cli = TASK_ARG(task); |
sock_t *s = (sock_t*) cli->cli_parent; |
sock_t *s = (sock_t*) cli->cli_parent; |
|
u_char *buf = TASK_DATA(task); |
|
struct pollfd pfd[1]; |
|
|
ioUpdTimerSocket(cli, NULL); | pfd->fd = TASK_FD(task); |
| pfd->events = POLLOUT; |
| pfd->revents = 0; |
| for(; len > 0; len -= wlen, buf += wlen) { |
| ioUpdTimerSocket(cli); |
|
|
if (s->sock_type == SOCK_STREAM) | if ((ret = poll(pfd, 1, s->sock_timeout.tv_sec * 1000)) < 1 || |
wlen = send(TASK_FD(task), TASK_DATA(task), TASK_DATLEN(task), 0); | pfd->revents & (POLLNVAL | POLLERR | POLLHUP)) { |
else | #if 0 |
wlen = sendto(TASK_FD(task), TASK_DATA(task), TASK_DATLEN(task), 0, | if (!ret) |
&cli->cli_addr.sa, cli->cli_addr.sa.sa_len); | continue; |
if (wlen < 1) | #endif |
schedEvent(TASK_ROOT(task), io_closeClient, cli, 0, | schedEvent(TASK_ROOT(task), io_closeClient, cli, 0, NULL, 0); |
(void*) cli->cli_func, cli->cli_fd); | break; |
| } |
|
|
|
if (s->sock_type == SOCK_STREAM) |
|
wlen = send(TASK_FD(task), buf, len, 0); |
|
else |
|
#ifndef __linux__ |
|
wlen = sendto(TASK_FD(task), buf, len, 0, &cli->cli_addr.sa, cli->cli_addr.sa.sa_len); |
|
#else |
|
wlen = sendto(TASK_FD(task), buf, len, 0, &cli->cli_addr.sa, |
|
cli->cli_addr.sa.sa_family == AF_INET ? |
|
sizeof cli->cli_addr.sin : sizeof cli->cli_addr.sin6); |
|
#endif |
|
if (wlen < 1) { |
|
schedEvent(TASK_ROOT(task), io_closeClient, cli, 0, NULL, 0); |
|
break; |
|
} |
|
} |
|
|
taskExit(task, NULL); |
taskExit(task, NULL); |
} |
} |
|
|
Line 156 io_txPty(sched_task_t *task)
|
Line 190 io_txPty(sched_task_t *task)
|
int wlen; |
int wlen; |
sock_cli_t *cli = TASK_ARG(task); |
sock_cli_t *cli = TASK_ARG(task); |
|
|
ioUpdTimerSocket(cli, NULL); | ioUpdTimerSocket(cli); |
|
|
wlen = write(TASK_FD(task), TASK_DATA(task), TASK_DATLEN(task)); |
wlen = write(TASK_FD(task), TASK_DATA(task), TASK_DATLEN(task)); |
if (wlen < 1) |
if (wlen < 1) |
schedEvent(TASK_ROOT(task), io_closeClient, cli, 0, | schedEvent(TASK_ROOT(task), io_closeClient, cli, 0, NULL, 0); |
(void*) cli->cli_func, cli->cli_fd); | |
|
|
taskExit(task, NULL); |
taskExit(task, NULL); |
} |
} |
Line 175 io_rxNet(sched_task_t *task)
|
Line 208 io_rxNet(sched_task_t *task)
|
sockaddr_t sa; |
sockaddr_t sa; |
socklen_t salen = sizeof sa.ss; |
socklen_t salen = sizeof sa.ss; |
|
|
ioUpdTimerSocket(cli, NULL); | ioUpdTimerSocket(cli); |
|
|
if (s->sock_type == SOCK_STREAM) |
if (s->sock_type == SOCK_STREAM) |
rlen = recv(TASK_FD(task), AIT_GET_BUF(&cli->cli_buf[0]), |
rlen = recv(TASK_FD(task), AIT_GET_BUF(&cli->cli_buf[0]), |
Line 183 io_rxNet(sched_task_t *task)
|
Line 216 io_rxNet(sched_task_t *task)
|
else { |
else { |
rlen = recvfrom(TASK_FD(task), AIT_GET_BUF(&cli->cli_buf[0]), |
rlen = recvfrom(TASK_FD(task), AIT_GET_BUF(&cli->cli_buf[0]), |
AIT_LEN(&cli->cli_buf[0]), 0, &sa.sa, &salen); |
AIT_LEN(&cli->cli_buf[0]), 0, &sa.sa, &salen); |
if (e_addrcmp(&cli->cli_addr, &sa, 42)) | if (e_addrcmp(&cli->cli_addr, &sa, 42)) { |
goto end; | schedReadSelf(task); |
| taskExit(task, NULL); |
| } |
} |
} |
if (rlen < 1) |
if (rlen < 1) |
schedEvent(TASK_ROOT(task), io_closeClient, cli, 0, | schedEvent(TASK_ROOT(task), io_closeClient, cli, 0, NULL, 0); |
(void*) cli->cli_func, cli->cli_fd); | else { |
else | |
schedEvent(TASK_ROOT(task), io_txPty, cli, cli->cli_pty, |
schedEvent(TASK_ROOT(task), io_txPty, cli, cli->cli_pty, |
AIT_GET_BUF(&cli->cli_buf[0]), rlen); |
AIT_GET_BUF(&cli->cli_buf[0]), rlen); |
end: | schedReadSelf(task); |
schedReadSelf(task); | } |
| |
taskExit(task, NULL); |
taskExit(task, NULL); |
} |
} |
|
|
Line 203 io_rxPty(sched_task_t *task)
|
Line 238 io_rxPty(sched_task_t *task)
|
int rlen; |
int rlen; |
sock_cli_t *cli = TASK_ARG(task); |
sock_cli_t *cli = TASK_ARG(task); |
|
|
ioUpdTimerSocket(cli, NULL); | ioUpdTimerSocket(cli); |
|
|
rlen = read(TASK_FD(task), AIT_GET_BUF(&cli->cli_buf[1]), AIT_LEN(&cli->cli_buf[1])); |
rlen = read(TASK_FD(task), AIT_GET_BUF(&cli->cli_buf[1]), AIT_LEN(&cli->cli_buf[1])); |
if (rlen < 1) |
if (rlen < 1) |
schedEvent(TASK_ROOT(task), io_closeClient, cli, 0, | schedEvent(TASK_ROOT(task), io_closeClient, cli, 0, NULL, 0); |
(void*) cli->cli_func, cli->cli_fd); | else { |
else | |
schedEvent(TASK_ROOT(task), io_txNet, cli, cli->cli_fd, |
schedEvent(TASK_ROOT(task), io_txNet, cli, cli->cli_fd, |
AIT_GET_BUF(&cli->cli_buf[1]), rlen); |
AIT_GET_BUF(&cli->cli_buf[1]), rlen); |
|
schedReadSelf(task); |
|
} |
|
|
schedReadSelf(task); |
|
taskExit(task, NULL); |
taskExit(task, NULL); |
} |
} |
|
|
static void * |
static void * |
io_bridgeClient(sched_task_t *task) |
io_bridgeClient(sched_task_t *task) |
{ |
{ |
int c, rlen; | int c, rlen, pty; |
pid_t pid; |
pid_t pid; |
sockaddr_t sa; |
sockaddr_t sa; |
socklen_t salen = sizeof sa.ss; |
socklen_t salen = sizeof sa.ss; |
Line 264 io_bridgeClient(sched_task_t *task)
|
Line 299 io_bridgeClient(sched_task_t *task)
|
AIT_SET_BUFSIZ(&cli->cli_buf[0], 0, AIT_LEN(&s->sock_buf)); |
AIT_SET_BUFSIZ(&cli->cli_buf[0], 0, AIT_LEN(&s->sock_buf)); |
AIT_SET_BUFSIZ(&cli->cli_buf[1], 0, AIT_LEN(&s->sock_buf)); |
AIT_SET_BUFSIZ(&cli->cli_buf[1], 0, AIT_LEN(&s->sock_buf)); |
|
|
switch ((pid = ioForkPTY(&cli->cli_pty, cli->cli_name, sizeof cli->cli_name, | switch ((pid = ioForkPTY(&pty, cli->cli_name, sizeof cli->cli_name, |
NULL, NULL, NULL))) { |
NULL, NULL, NULL))) { |
case -1: |
case -1: |
ELIBERR(io); |
ELIBERR(io); |
break; |
break; |
case 0: |
case 0: |
|
cli->cli_pty = pty; |
|
ioSetRAWMode(STDIN_FILENO, NULL); |
|
|
array_Args(cli->cli_cmdline, 0, " \t", &args); |
array_Args(cli->cli_cmdline, 0, " \t", &args); |
argv = array_To(args); |
argv = array_To(args); |
array_Destroy(&args); |
array_Destroy(&args); |
|
|
|
#if 0 |
printf("Console %s\n", cli->cli_name); |
printf("Console %s\n", cli->cli_name); |
execv(*argv, argv); | #endif |
| rlen = execv(*argv, argv); |
| _exit(rlen); |
break; |
break; |
default: |
default: |
|
cli->cli_pty = pty; |
cli->cli_pid = pid; |
cli->cli_pid = pid; |
|
|
schedRead(TASK_ROOT(task), io_rxPty, cli, cli->cli_pty, |
schedRead(TASK_ROOT(task), io_rxPty, cli, cli->cli_pty, |
TASK_ARG(task), 0); |
TASK_ARG(task), 0); |
schedRead(TASK_ROOT(task), io_rxNet, cli, cli->cli_fd, |
schedRead(TASK_ROOT(task), io_rxNet, cli, cli->cli_fd, |
TASK_ARG(task), 0); |
TASK_ARG(task), 0); |
ioUpdTimerSocket(cli, NULL); | ioUpdTimerSocket(cli); |
break; |
break; |
} |
} |
end: |
end: |
Line 292 end:
|
Line 334 end:
|
taskExit(task, NULL); |
taskExit(task, NULL); |
} |
} |
|
|
|
static void * |
|
io_bridgeClient2Pool(sched_task_t *task) |
|
{ |
|
int c, rlen; |
|
sockaddr_t sa; |
|
socklen_t salen = sizeof sa.ss; |
|
sock_cli_t *cli = NULL; |
|
sock_t *s = (sock_t*) TASK_ARG(task); |
|
|
|
if (s->sock_type == SOCK_STREAM) { |
|
if ((c = accept(TASK_FD(task), &sa.sa, &salen)) == -1) { |
|
LOGERR; |
|
goto end; |
|
} |
|
} else { |
|
if ((rlen = recvfrom(TASK_FD(task), |
|
AIT_GET_BUF(&s->sock_buf), AIT_LEN(&s->sock_buf), |
|
MSG_PEEK, &sa.sa, &salen)) == -1) { |
|
LOGERR; |
|
goto end; |
|
} else |
|
c = TASK_FD(task); |
|
} |
|
|
|
cli = e_malloc(sizeof(sock_cli_t)); |
|
if (!cli) { |
|
io_SetErr(elwix_GetErrno(), "%s", elwix_GetError()); |
|
if (s->sock_type == SOCK_STREAM) |
|
close(c); |
|
goto end; |
|
} else { |
|
memset(cli, 0, sizeof(sock_cli_t)); |
|
pthread_mutex_lock(&s->sock_mtx); |
|
TAILQ_INSERT_TAIL(&s->sock_cli, cli, cli_node); |
|
pthread_mutex_unlock(&s->sock_mtx); |
|
} |
|
|
|
io_progCheck(s->sock_prog, 42); |
|
|
|
cli->cli_parent = TASK_ARG(task); |
|
cli->cli_fd = c; |
|
cli->cli_pty = io_progAttach(s->sock_prog, 42); |
|
strlcpy(cli->cli_cmdline, TASK_DATA(task), sizeof cli->cli_cmdline); |
|
memcpy(&cli->cli_addr, &sa, sizeof cli->cli_addr); |
|
AIT_SET_BUFSIZ(&cli->cli_buf[0], 0, AIT_LEN(&s->sock_buf)); |
|
AIT_SET_BUFSIZ(&cli->cli_buf[1], 0, AIT_LEN(&s->sock_buf)); |
|
|
|
schedRead(TASK_ROOT(task), io_rxPty, cli, cli->cli_pty, TASK_ARG(task), 0); |
|
schedRead(TASK_ROOT(task), io_rxNet, cli, cli->cli_fd, TASK_ARG(task), 0); |
|
ioUpdTimerSocket(cli); |
|
end: |
|
schedReadSelf(task); |
|
taskExit(task, NULL); |
|
} |
|
|
|
|
/* |
/* |
* ioInitSocket() - Init socket and allocate resources |
* ioInitSocket() - Init socket and allocate resources |
* |
* |
Line 360 ioInitSocket(int role, int type, int proto, const char
|
Line 457 ioInitSocket(int role, int type, int proto, const char
|
e_free(s); |
e_free(s); |
return NULL; |
return NULL; |
} |
} |
|
#ifndef __linux__ |
if (bind(s->sock_fd, &s->sock_addr.sa, s->sock_addr.sa.sa_len) == -1) { |
if (bind(s->sock_fd, &s->sock_addr.sa, s->sock_addr.sa.sa_len) == -1) { |
|
#else |
|
if (bind(s->sock_fd, &s->sock_addr.sa, s->sock_addr.sa.sa_family == AF_INET ? |
|
sizeof s->sock_addr.sin : sizeof s->sock_addr.sin6) == -1) { |
|
#endif |
LOGERR; |
LOGERR; |
AIT_FREE_VAL(&s->sock_buf); |
AIT_FREE_VAL(&s->sock_buf); |
e_free(s); |
e_free(s); |
Line 406 ioCloseSocket(sock_t ** __restrict s)
|
Line 508 ioCloseSocket(sock_t ** __restrict s)
|
AIT_FREE_VAL(&cli->cli_buf[0]); |
AIT_FREE_VAL(&cli->cli_buf[0]); |
|
|
if (cli->cli_pid > 0) { |
if (cli->cli_pid > 0) { |
kill(cli->cli_pid, SIGTERM); | kill(cli->cli_pid, SIGKILL); |
while (waitpid(cli->cli_pid, &stat, WNOHANG) > 0) { |
while (waitpid(cli->cli_pid, &stat, WNOHANG) > 0) { |
usleep(1000); |
usleep(1000); |
kill(cli->cli_pid, SIGTERM); | kill(cli->cli_pid, SIGKILL); |
} |
} |
} |
} |
|
|
Line 457 ioUpSocket(sock_t * __restrict s, void *arg, int timeo
|
Line 559 ioUpSocket(sock_t * __restrict s, void *arg, int timeo
|
case IO_SOCK_ROLE_CLIENT: |
case IO_SOCK_ROLE_CLIENT: |
memcpy(&s->sock_peer, peer, sizeof s->sock_peer); |
memcpy(&s->sock_peer, peer, sizeof s->sock_peer); |
|
|
if (connect(s->sock_fd, &s->sock_peer.sa, | #ifndef __linux__ |
s->sock_peer.sa.sa_len) == -1) { | if (connect(s->sock_fd, &s->sock_peer.sa, s->sock_peer.sa.sa_len) == -1) { |
| #else |
| if (connect(s->sock_fd, &s->sock_peer.sa, s->sock_addr.sa.sa_family == AF_INET ? |
| sizeof s->sock_peer.sin : sizeof s->sock_peer.sin6) == -1) { |
| #endif |
LOGERR; |
LOGERR; |
return -1; |
return -1; |
} |
} |
Line 486 ioUpSocket(sock_t * __restrict s, void *arg, int timeo
|
Line 592 ioUpSocket(sock_t * __restrict s, void *arg, int timeo
|
* ioUpdTimerSocket() - Update timeout of socket |
* ioUpdTimerSocket() - Update timeout of socket |
* |
* |
* @c = Client socket |
* @c = Client socket |
* @arg = Optional data argument |
|
* return: none |
* return: none |
*/ |
*/ |
void |
void |
ioUpdTimerSocket(sock_cli_t * __restrict c, void *arg) | ioUpdTimerSocket(sock_cli_t * __restrict c) |
{ |
{ |
sock_t *s; |
sock_t *s; |
|
|
Line 499 ioUpdTimerSocket(sock_cli_t * __restrict c, void *arg)
|
Line 604 ioUpdTimerSocket(sock_cli_t * __restrict c, void *arg)
|
else |
else |
s = c->cli_parent; |
s = c->cli_parent; |
|
|
schedCancelby(s->sock_root, taskTIMER, CRITERIA_DATLEN, (void*) c->cli_fd, NULL); | if (s->sock_prog) |
schedTimer(s->sock_root, io_closeClient, c, s->sock_timeout, arg, c->cli_fd); | io_progCheck(s->sock_prog, 42); |
| |
| schedCancelby(s->sock_root, taskTIMER, CRITERIA_ARG, c, NULL); |
| schedTimer(s->sock_root, io_closeClient, c, s->sock_timeout, NULL, 0); |
} |
} |
|
|
/* |
/* |
Line 519 ioCloseClient(sock_cli_t * __restrict c)
|
Line 627 ioCloseClient(sock_cli_t * __restrict c)
|
else |
else |
s = c->cli_parent; |
s = c->cli_parent; |
|
|
return !schedEvent(s->sock_root, io_closeClient, c, 0, NULL, c->cli_fd); | return !schedEvent(s->sock_root, io_closeClient, c, 0, NULL, 0); |
} |
} |
|
|
/* |
/* |
Line 539 ioLoopSocket(sock_t * __restrict s, sched_task_func_t
|
Line 647 ioLoopSocket(sock_t * __restrict s, sched_task_func_t
|
return schedRun(s->sock_root, &s->sock_kill); |
return schedRun(s->sock_root, &s->sock_kill); |
} |
} |
|
|
|
static void * |
|
io_progPurge(sched_task_t *task) |
|
{ |
|
sock_t *s = (sock_t*) TASK_ARG(task); |
|
|
|
io_progVacuum(s->sock_prog, 0); |
|
|
|
schedTimer(TASK_ROOT(task), TASK_FUNC(task), TASK_ARG(task), |
|
s->sock_timeout, TASK_DATA(task), TASK_DATLEN(task)); |
|
taskExit(task, NULL); |
|
} |
|
|
/* |
/* |
* ioBridgeProg2Socket() - Start socket scheduler and bridge program to socket |
* ioBridgeProg2Socket() - Start socket scheduler and bridge program to socket |
* |
* |
Line 552 ioBridgeProg2Socket(sock_t * __restrict s, const char
|
Line 672 ioBridgeProg2Socket(sock_t * __restrict s, const char
|
if (!s || !prgname || s->sock_kill) |
if (!s || !prgname || s->sock_kill) |
return -1; |
return -1; |
|
|
schedRead(s->sock_root, io_bridgeClient, s, s->sock_fd, (void*) prgname, 0); | if (s->sock_prog) { |
| schedRead(s->sock_root, io_bridgeClient2Pool, |
| s, s->sock_fd, (void*) prgname, 0); |
| schedTimer(s->sock_root, io_progPurge, s, s->sock_timeout, NULL, 0); |
| } else |
| schedRead(s->sock_root, io_bridgeClient, |
| s, s->sock_fd, (void*) prgname, 0); |
return schedRun(s->sock_root, &s->sock_kill); |
return schedRun(s->sock_root, &s->sock_kill); |
|
} |
|
|
|
/* |
|
* ioSetupProg2Socket() - Setup program pool to socket server |
|
* |
|
* @s = Socket |
|
* @p = Program pool |
|
* return: -1 error or 0 ok |
|
*/ |
|
int |
|
ioSetupProg2Socket(sock_t * __restrict s, prog_t * __restrict p) |
|
{ |
|
if (!s) |
|
return -1; |
|
|
|
s->sock_prog = p; |
|
return 0; |
} |
} |