#include <esl.h>
#include <errno.h>
-static void mycallback(esl_socket_t server_sock, esl_socket_t client_sock, struct sockaddr_in *addr)
+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) {
- close(client_sock);
esl_log(ESL_LOG_ERROR, "Socket Error\n");
- return;
+ 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");
- return;
+ 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);
return;
}
- if(system(path)) {
+ /* 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");
+ return;
+ }
+
+ 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");
+ return;
+ }
+
+ snprintf(path_buffer, sizeof(path_buffer), "%s %d", path, client_sock);
+
+
+ if (system(path_buffer)) {
esl_log(ESL_LOG_ERROR, "System Call Failed! [%s]\n", strerror(errno));
}
+
esl_disconnect(&handle);
}
{
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 {
+ 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;
}
}
-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;