mirror of
https://github.com/yrutschle/sslh.git
synced 2025-06-05 09:53:36 +03:00
sslh-select: reduce CPU and memory usage in forked processes
This commit is contained in:
parent
2544f20bdf
commit
2a70470f13
110
sslh-select.c
110
sslh-select.c
@ -182,6 +182,93 @@ void shovel(struct connection *cnx, int active_fd,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* shovels data from one fd to the other and vice-versa
|
||||||
|
returns after one socket closed
|
||||||
|
*/
|
||||||
|
void shovel_single(struct connection *cnx)
|
||||||
|
{
|
||||||
|
fd_set fds_r, fds_w;
|
||||||
|
int res, i;
|
||||||
|
int max_fd = MAX(cnx->q[0].fd, cnx->q[1].fd) + 1;
|
||||||
|
|
||||||
|
FD_ZERO(&fds_r);
|
||||||
|
FD_ZERO(&fds_w);
|
||||||
|
while (1) {
|
||||||
|
for (i = 0; i < 2; i++) {
|
||||||
|
if (cnx->q[i].deferred_data_size) {
|
||||||
|
FD_SET(cnx->q[i].fd, &fds_w);
|
||||||
|
FD_CLR(cnx->q[1-i].fd, &fds_r);
|
||||||
|
} else {
|
||||||
|
FD_CLR(cnx->q[i].fd, &fds_w);
|
||||||
|
FD_SET(cnx->q[1-i].fd, &fds_r);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
res = select(
|
||||||
|
max_fd,
|
||||||
|
&fds_r,
|
||||||
|
&fds_w,
|
||||||
|
NULL,
|
||||||
|
NULL
|
||||||
|
);
|
||||||
|
CHECK_RES_DIE(res, "select");
|
||||||
|
|
||||||
|
for (i = 0; i < 2; i++) {
|
||||||
|
if (FD_ISSET(cnx->q[i].fd, &fds_w)) {
|
||||||
|
res = flush_deferred(&cnx->q[i]);
|
||||||
|
if ((res == -1) && ((errno == EPIPE) || (errno == ECONNRESET))) {
|
||||||
|
if (verbose)
|
||||||
|
fprintf(stderr, "%s socket closed\n", i ? "server" : "client");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (FD_ISSET(cnx->q[i].fd, &fds_r)) {
|
||||||
|
res = fd2fd(&cnx->q[1-i], &cnx->q[i]);
|
||||||
|
if (!res) {
|
||||||
|
if (verbose)
|
||||||
|
fprintf(stderr, "socket closed\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Child process that makes internal connection and proxies
|
||||||
|
*/
|
||||||
|
void connect_proxy(struct connection *cnx)
|
||||||
|
{
|
||||||
|
int in_socket;
|
||||||
|
int out_socket;
|
||||||
|
|
||||||
|
/* Minimize the file descriptor value to help select() */
|
||||||
|
in_socket = dup(cnx->q[0].fd);
|
||||||
|
if (in_socket == -1) {
|
||||||
|
in_socket = cnx->q[0].fd;
|
||||||
|
} else {
|
||||||
|
close(cnx->q[0].fd);
|
||||||
|
cnx->q[0].fd = in_socket;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Connect the target socket */
|
||||||
|
out_socket = connect_addr(cnx, in_socket);
|
||||||
|
CHECK_RES_DIE(out_socket, "connect");
|
||||||
|
|
||||||
|
cnx->q[1].fd = out_socket;
|
||||||
|
|
||||||
|
log_connection(cnx);
|
||||||
|
|
||||||
|
shovel_single(cnx);
|
||||||
|
|
||||||
|
close(in_socket);
|
||||||
|
close(out_socket);
|
||||||
|
|
||||||
|
if (verbose)
|
||||||
|
fprintf(stderr, "connection closed down\n");
|
||||||
|
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
/* returns true if specified fd is initialised and present in fd_set */
|
/* returns true if specified fd is initialised and present in fd_set */
|
||||||
int is_fd_active(int fd, fd_set* set)
|
int is_fd_active(int fd, fd_set* set)
|
||||||
{
|
{
|
||||||
@ -323,22 +410,21 @@ void main_loop(int listen_sockets[], int num_addr_listen)
|
|||||||
res = -1;
|
res = -1;
|
||||||
} else if (cnx[i].proto->fork) {
|
} else if (cnx[i].proto->fork) {
|
||||||
if (!fork()) {
|
if (!fork()) {
|
||||||
struct connection *cnx_i = &cnx[i];
|
struct connection *pcnx_i = &cnx[i];
|
||||||
for (i = 0; i < num_addr_listen; i++) {
|
struct connection cnx_i = *pcnx_i;
|
||||||
FD_CLR(listen_sockets[i], &fds_r);
|
for (i = 0; i < num_addr_listen; i++)
|
||||||
close(listen_sockets[i]);
|
close(listen_sockets[i]);
|
||||||
}
|
|
||||||
num_addr_listen = 0;
|
|
||||||
for (i = 0; i < num_cnx; i++)
|
for (i = 0; i < num_cnx; i++)
|
||||||
if (&cnx[i] != cnx_i)
|
if (&cnx[i] != pcnx_i)
|
||||||
tidy_connection(&cnx[i], &fds_r, &fds_w);
|
for (j = 0; j < 2; j++)
|
||||||
num_probing = 0;
|
if (cnx[i].q[j].fd != -1)
|
||||||
res = connect_queue(cnx_i, &fds_r, &fds_w);
|
close(cnx[i].q[j].fd);
|
||||||
max_fd = MAX(cnx_i->q[0].fd, cnx_i->q[1].fd) + 1;
|
free(cnx);
|
||||||
} else {
|
connect_proxy(&cnx_i);
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
tidy_connection(&cnx[i], &fds_r, &fds_w);
|
tidy_connection(&cnx[i], &fds_r, &fds_w);
|
||||||
res = -1;
|
res = -1;
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
res = connect_queue(&cnx[i], &fds_r, &fds_w);
|
res = connect_queue(&cnx[i], &fds_r, &fds_w);
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user