fix issue with threaded ivrd, forking is back by default but threaded can be chosen with -t; in both modes the fd number is not passed as the first arg to the program but in threaded mode the stdin will no longer be mapped to the socket you will have to get the first command line arg instead of fileno stdin

This commit is contained in:
Anthony Minessale 2012-05-03 13:13:48 -05:00
parent 086cbf1bfc
commit 163fffb3e8
4 changed files with 141 additions and 21 deletions

View File

@ -36,11 +36,56 @@
#include <esl.h>
#include <errno.h>
static void my_forking_callback(esl_socket_t server_sock, esl_socket_t client_sock, struct sockaddr_in *addr)
{
esl_handle_t handle = {{0}};
char path_buffer[1024] = { 0 };
const char *path;
char arg[64] = { 0 };
if (fork()) {
close(client_sock);
return;
}
if (esl_attach_handle(&handle, client_sock, addr) != ESL_SUCCESS || !handle.info_event) {
esl_log(ESL_LOG_ERROR, "Socket Error\n");
exit(0);
}
if (!(path = esl_event_get_header(handle.info_event, "variable_ivr_path"))) {
esl_disconnect(&handle);
esl_log(ESL_LOG_ERROR, "Missing ivr_path param!\n");
exit(0);
}
snprintf(arg, sizeof(arg), "%d", client_sock);
strncpy(path_buffer, path, sizeof(path_buffer) - 1);
/* hotwire the socket to STDIN/STDOUT */
/* hotwire the socket to STDIN/STDOUT */
if (!(dup2(client_sock, STDIN_FILENO)) && !(dup2(client_sock, STDOUT_FILENO))){
esl_disconnect(&handle);
esl_log(ESL_LOG_ERROR, "Socket Error hotwiring socket to STDIN/STDOUT!\n");
return;
}
/* close the handle but leak the socket on purpose cos the child will need it open */
handle.sock = -1;
esl_disconnect(&handle);
execl(path_buffer, path_buffer, arg, (char *)NULL);
close(client_sock);
exit(0);
}
static void mycallback(esl_socket_t server_sock, esl_socket_t client_sock, struct sockaddr_in *addr)
{
esl_handle_t handle = {{0}};
const char *path;
char path_buffer[1024] = { 0 };
if (esl_attach_handle(&handle, client_sock, addr) != ESL_SUCCESS || !handle.info_event) {
close(client_sock);
esl_log(ESL_LOG_ERROR, "Socket Error\n");
@ -53,16 +98,13 @@ static void mycallback(esl_socket_t server_sock, esl_socket_t client_sock, struc
return;
}
/* hotwire the socket to STDIN/STDOUT */
if (!(dup2(client_sock, STDIN_FILENO)) && !(dup2(client_sock, STDOUT_FILENO))){
esl_disconnect(&handle);
esl_log(ESL_LOG_ERROR, "Socket Error hotwiring socket to STDIN/STDOUT!\n");
return;
}
snprintf(path_buffer, sizeof(path_buffer), "%s %d", path, client_sock);
if(system(path)) {
if (system(path_buffer)) {
esl_log(ESL_LOG_ERROR, "System Call Failed! [%s]\n", strerror(errno));
}
esl_disconnect(&handle);
}
@ -71,24 +113,43 @@ int main(int argc, char *argv[])
{
int i;
char *ip = NULL;
int port = 0;
int port = 0, thread = 0;
for (i = 1; i + 1 < argc; ) {
if (!strcasecmp(argv[i], "-h")) {
ip = argv[++i];
} else if (!strcasecmp(argv[i], "-p")) {
port = atoi(argv[++i]);
} else {
i++;
for (i = 1; i < argc; ) {
int cont = 0;
if (i + 1 < argc) {
if (!strcasecmp(argv[i], "-h")) {
ip = argv[++i]; cont++;
} else if (!strcasecmp(argv[i], "-p")) {
port = atoi(argv[++i]); cont++;
}
}
if (cont) {
i++;
continue;
}
if (!strcasecmp(argv[i], "-t")) {
thread++;
}
i++;
}
if (!(ip && port)) {
fprintf(stderr, "Usage %s -h <host> -p <port>\n", argv[0]);
fprintf(stderr, "Usage %s [-t] -h <host> -p <port>\n", argv[0]);
return -1;
}
esl_listen(ip, port, mycallback, 100000);
if (thread) {
printf("Starting threaded listener.\n");
esl_listen_threaded(ip, port, mycallback, 100000);
} else {
printf("Starting forking listener.\n");
esl_listen(ip, port, my_forking_callback);
}
return 0;
}

View File

@ -649,7 +649,64 @@ static void *client_thread(esl_thread_t *me, void *obj)
}
ESL_DECLARE(esl_status_t) esl_listen(const char *host, esl_port_t port, esl_listen_callback_t callback, int max)
ESL_DECLARE(esl_status_t) esl_listen(const char *host, esl_port_t port, esl_listen_callback_t callback)
{
esl_socket_t server_sock = ESL_SOCK_INVALID;
struct sockaddr_in addr;
esl_status_t status = ESL_SUCCESS;
if ((server_sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) {
return ESL_FAIL;
}
esl_socket_reuseaddr(server_sock);
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = htonl(INADDR_ANY);
addr.sin_port = htons(port);
if (bind(server_sock, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
status = ESL_FAIL;
goto end;
}
if (listen(server_sock, 10000) < 0) {
status = ESL_FAIL;
goto end;
}
for (;;) {
int client_sock;
struct sockaddr_in echoClntAddr;
#ifdef WIN32
int clntLen;
#else
unsigned int clntLen;
#endif
clntLen = sizeof(echoClntAddr);
if ((client_sock = accept(server_sock, (struct sockaddr *) &echoClntAddr, &clntLen)) == ESL_SOCK_INVALID) {
status = ESL_FAIL;
goto end;
}
callback(server_sock, client_sock, &echoClntAddr);
}
end:
if (server_sock != ESL_SOCK_INVALID) {
closesocket(server_sock);
server_sock = ESL_SOCK_INVALID;
}
return status;
}
ESL_DECLARE(esl_status_t) esl_listen_threaded(const char *host, esl_port_t port, esl_listen_callback_t callback, int max)
{
esl_socket_t server_sock = ESL_SOCK_INVALID;
struct sockaddr_in addr;

View File

@ -391,7 +391,9 @@ ESL_DECLARE(esl_status_t) esl_attach_handle(esl_handle_t *handle, esl_socket_t s
\param port Port to bind to
\param callback Callback that will be called upon data received
*/
ESL_DECLARE(esl_status_t) esl_listen(const char *host, esl_port_t port, esl_listen_callback_t callback, int max);
ESL_DECLARE(esl_status_t) esl_listen(const char *host, esl_port_t port, esl_listen_callback_t callback);
ESL_DECLARE(esl_status_t) esl_listen_threaded(const char *host, esl_port_t port, esl_listen_callback_t callback, int max);
/*!
\brief Executes application with sendmsg to a specific UUID. Used for outbound socket.
\param handle Handle that the msg will be sent

View File

@ -48,7 +48,7 @@ static void mycallback(esl_socket_t server_sock, esl_socket_t client_sock, struc
int main(void)
{
esl_global_set_default_logger(7);
esl_listen("localhost", 8084, mycallback, 100000);
esl_listen_threaded("localhost", 8084, mycallback, 100000);
return 0;
}