📄 scprot.c
字号:
/* voifax scripting protocol interface library * Copyright (C) 2004 Simone Freddio & Andrea Emanuelli * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */#include <stdio.h>#include <stdlib.h>#include <string.h>#include <unistd.h>#include <signal.h>#include <sys/types.h>#include "scriptcntl.h"#include "common.h"#include "scprot.h"#include "libevent.h"#include "util.h"/* Local function prototypes */static int search_device(char *dev);void sigpipe_handler(int par);static int handler_device (int argc, char **argv);static int handler_goodbye (int argc, char **argv);static int handler_hello (int argc, char **argv);static int handler_beep (int argc, char **argv);static int handler_enable_events (int argc, char **argv);static int handler_disable_events (int argc, char **argv);static int handler_dial (int argc, char **argv);static int handler_play (int argc, char **argv);static int handler_get_tty (int argc, char **argv);static int handler_get_modem (int argc, char **argv);static int handler_autostop (int argc, char **argv);static int handler_record (int argc, char **argv);static int handler_wait (int argc, char **argv);static int handler_stop (int argc, char **argv);static int handler_dtmf (int argc, char **argv);static int handler_quote (int argc, char **argv);static int handler_getfax (int argc, char **argv);static int handler_sendfax (int argc, char **argv);static t_sp sp;static int events_enabled = false;/* Local data */static t_sp_devdesc sp_devices[SP_DEVICES] = { { SD_NODEVICE, "NO_DEVICE" }, { SD_DIALUPLINE, "DIALUP_LINE" }, { SD_INTERNAL_MICROPHONE, "INTERNAL_MICROPHONE" }, { EXTERNAL_MICROPHONE, "EXTERNAL_MICROPHONE" }, { INTERNAL_SPEAKER, "INTERNAL_SPEAKER" }, { LOCAL_HANDSET, "LOCAL_HANDSET" }, { EXTERNAL_SPEAKER, "EXTERNAL_SPEAKER" }, { DIALUP_WITH_INT_SPEAKER, "DIALUP_WITH_INT_SPEAKER" }, { DIALUP_WITH_EXT_SPEAKER, "DIALUP_WITH_EXT_SPEAKER" }, { DIALUP_WITH_INTERNAL_MIC_AND_SPEAKER, "DIALUP_WITH_INTERNAL_MIC_AND_SPEAKER" }, { DIALUP_WITH_EXTERNAL_MIC_AND_SPEAKER, "DIALUP_WITH_EXTERNAL_MIC_AND_SPEAKER" }, { DIALUP_WITH_LOCAL_HANDSET, "DIALUP_WITH_LOCAL_HANDSET" } };/* Local functions *//***********************//*** SCRIPT HANDLERS ***/static int handler_device(int argc, char **argv){ char module[] = "handler_device"; char trc[200]; int dev; if (argc != 2) { TRC(TRC_ERR, module, "Handler device: Wrong number of parameters"); return false; } sprintf(trc, "Device = '%s'", argv[1]); TRC(TRC_INFO, module, trc); dev = search_device(argv[1]); if (dev == -1) { TRC(TRC_WARN, module, argv[1]); TRC(TRC_WARN, module, "Unkown device"); return sc_send(&sp.sc, "DEVICE_NOT_AVAILABLE"); } sprintf(trc, "Setting device = '%s', '%d'", argv[1], dev); TRC(TRC_INFO, module, trc); strcpy(argv[0], SP_EVENT_DEVICE); sprintf(argv[1], "%d", dev); return libevent_call_handler(argc, argv);}static int handler_goodbye(int argc, char **argv){ char module[] = "handler_goodbye"; argv = argv; if (argc != 1) { TRC(TRC_ERR, module, "Wrong number of arguments"); return false; } TRC(TRC_INFO, module, "Received goodbye, closing connection"); sp.handshake = HANDSHAKE_CLOSED; return sc_send(&sp.sc, "GOODBYE SHELL");}static int handler_hello(int argc, char **argv){ char module[] = "handler_hello"; argv = argv; if (argc != 3) { TRC(TRC_ERR, module, "Wrong number of arguments"); return false; } TRC(TRC_INFO, module, "Initial handshake from script"); sp.handshake = HANDSHAKE_DONE; return sp_send_ready();}static int handler_beep(int argc, char **argv){ char module[] = "handler_beep"; if (argc > 3) { TRC(TRC_ERR, module, "Wrong number of arguments"); return false; } TRC(TRC_INFO, module, "Got beep"); strcpy(argv[0], SP_EVENT_BEEP); return libevent_call_handler(argc, argv);}static int handler_enable_events(int argc, char **argv){ char module[] = "handler_enable_events"; argc = argc; argv = argv; TRC(TRC_INFO, module, "Enabling events..."); events_enabled = true; return sp_send_ready();}static int handler_disable_events(int argc, char **argv){ char module[] = "handler_disable_events"; argc = argc; argv = argv; TRC(TRC_INFO, module, "Disabling events..."); events_enabled = true; return sp_send_ready();}static int handler_dial(int argc, char **argv){ char module[] = "handler_dial"; char trc[200]; if (argc != 2) { TRC(TRC_ERR, module, "Wrong number of arguments"); return false; } sprintf(trc, "Dialing '%s'...", argv[1]); TRC(TRC_INFO, module, trc); strcpy(argv[0], SP_EVENT_DIAL); return libevent_call_handler(argc, argv);}static int handler_play(int argc, char **argv){ char module[] = "handler_play"; char trc[200]; switch (argc) { case 2: sprintf(trc, "Playing '%s'...", argv[1]); TRC(TRC_INFO, module, trc); break; case 3: sprintf(trc, "Playing '%s' '%s'...", argv[1], argv[2]); TRC(TRC_INFO, module, trc); break; default: TRC(TRC_ERR, module, "Wrong number of arguments"); return false; } strcpy(argv[0], SP_EVENT_PLAY); return libevent_call_handler(argc, argv);}static int handler_get_tty(int argc, char **argv){ char module[] = "handler_get_tty"; TRC(TRC_INFO, module, "Returning dev..."); strcpy(argv[0], SP_EVENT_GET_TTY); return libevent_call_handler(argc, argv);}static int handler_get_modem(int argc, char **argv){ char module[] = "handler_get_modem"; TRC(TRC_INFO, module, "Returning modem..."); strcpy(argv[0], SP_EVENT_GET_MODEM); return libevent_call_handler(argc, argv);}static int handler_autostop(int argc, char **argv){ char module[] = "handler_autostop"; char trc[200]; int val = false; if (argc != 2) { TRC(TRC_ERR, module, "Wrong number of arguments"); return false; } sprintf(trc, "Received '%s' '%s'.", argv[0], argv[1]); TRC(TRC_INFO, module, trc); if (strcmp(argv[1], "ON") == 0) { val = true; } else if (strcmp(argv[1], "OFF") == 0) { val = false; } else { TRC(TRC_WARN, module, "Bad parameter"); return false; } strcpy(argv[0], SP_EVENT_AUTOSTOP); sprintf(argv[1], "%d", val); return libevent_call_handler(argc, argv);}static int handler_record(int argc, char **argv){ char module[] = "handler_record"; char trc[200]; if (argc != 2) { TRC(TRC_ERR, module, "Wrong number of arguments"); return false; } sprintf(trc, "Recording '%s'...", argv[1]); TRC(TRC_INFO, module, trc); strcpy(argv[0], SP_EVENT_RECORD); return libevent_call_handler(argc, argv);}static int handler_wait(int argc, char **argv){ char module[] = "handler_wait"; char trc[200]; if (argc != 2) { TRC(TRC_ERR, module, "Wrong number of arguments"); return false; } sprintf(trc, "Waiting for '%d'", atoi(argv[1])); TRC(TRC_INFO, module, trc); strcpy(argv[0], SP_EVENT_WAIT); return libevent_call_handler(argc, argv);}static int handler_stop(int argc, char **argv){ char module[] = "handler_stop"; if (argc != 1) { TRC(TRC_ERR, module, "Wrong number of arguments"); return false; } TRC(TRC_INFO, module, "Stop received"); strcpy(argv[0], SP_EVENT_STOP); return libevent_call_handler(argc, argv);}static int handler_dtmf(int argc, char **argv){ char module[] = "handler_dtmf"; char trc[200]; if (argc != 2) { TRC(TRC_ERR, module, "Wrong number of arguments"); return false; } sprintf(trc, "Sending dtmf for '%d'", atoi(argv[1])); TRC(TRC_INFO, module, trc); strcpy(argv[0], SP_EVENT_DTMF); return libevent_call_handler(argc, argv);}static int handler_quote(int argc, char **argv){ char module[] = "handler_quote"; char trc[200]; if (argc != 2) { TRC(TRC_ERR, module, "Wrong number of arguments"); return false; } sprintf(trc, "Sending raw command '%s'", argv[1]); TRC(TRC_INFO, module, trc); strcpy(argv[0], SP_EVENT_QUOTE); return libevent_call_handler(argc, argv);}static int handler_getfax(int argc, char **argv){ char module[] = "handler_getfax"; char trc[200]; if (argc != 1) { TRC(TRC_ERR, module, "Wrong number of arguments"); return false; } sprintf(trc, "Receiving fax..."); TRC(TRC_INFO, module, trc); strcpy(argv[0], SP_EVENT_GETFAX); return libevent_call_handler(argc, argv);}static int handler_sendfax(int argc, char **argv){ char module[] = "handler_sendfax"; char trc[200]; sprintf(trc, "Sending fax..."); TRC(TRC_INFO, module, trc); strcpy(argv[0], SP_EVENT_SENDFAX); return libevent_call_handler(argc, argv);}/*************************/static int search_device(char *dev){ char module[] = "search_device"; int a = 0; char trc[200]; for (a = 0; a < SP_DEVICES; a++) { if (strcmp(dev, sp_devices[a].devname) == 0) { return sp_devices[a].devno; } } sprintf(trc, "Device not found: '%s'", dev); TRC(TRC_WARN, module, trc); return -1;}/* Exported functions */int sp_init(char *cmd){ char module[] = "sp_init"; int r = true; if (!sc_launch(&sp.sc, cmd)) { TRC(TRC_ERR, module, "Unable to launch script"); return false; } sp.handshake = HANDSHAKE_CONNECTING; if (!sc_send(&sp.sc, "HELLO SHELL")) { TRC(TRC_ERR, module, "Unable to send data to script"); return false; } r = r && libevent_add_handler(handler_hello, "SC_HELLO VOICE PROGRAM"); r = r && libevent_add_handler(handler_beep, "SC_BEEP"); r = r && libevent_add_handler(handler_device, "SC_DEVICE"); r = r && libevent_add_handler(handler_goodbye, "SC_GOODBYE" ); r = r && libevent_add_handler(handler_enable_events, "SC_ENABLE EVENTS"); r = r && libevent_add_handler(handler_disable_events, "SC_DISABLE EVENTS"); r = r && libevent_add_handler(handler_dial, "SC_DIAL"); r = r && libevent_add_handler(handler_play, "SC_PLAY"); r = r && libevent_add_handler(handler_get_tty, "SC_GET TTY"); r = r && libevent_add_handler(handler_get_modem, "SC_GET MODEM"); r = r && libevent_add_handler(handler_autostop, "SC_AUTOSTOP"); r = r && libevent_add_handler(handler_record, "SC_RECORD"); r = r && libevent_add_handler(handler_wait, "SC_WAIT"); r = r && libevent_add_handler(handler_stop, "SC_STOP"); r = r && libevent_add_handler(handler_dtmf, "SC_DTMF"); r = r && libevent_add_handler(handler_quote, "SC_QUOTE"); r = r && libevent_add_handler(handler_getfax, "SC_GETFAX"); r = r && libevent_add_handler(handler_sendfax, "SC_SENDFAX"); if (!r) { TRC(TRC_ERR, module, "Error initializing script handlers"); } /* Solo per compatiblita' con vgetty che necessitava di una kill -PIPE $PID da parte del processo figlio per capirequando erano disponibili i dati sulla pipe. */ signal(SIGPIPE, sigpipe_handler); return r;}void sigpipe_handler(int par){ par = par; TRC(TRC_INFO, "sigpipe_handler","lettura messaggi dall script"); sp_handle_messages();}int sp_getstatus(){ switch (sp.handshake) { case HANDSHAKE_CLOSED: return SP_HM_CLOSED; break; case HANDSHAKE_WAITING: return SP_HM_OK; break; default: return SP_HM_NONE; } return SP_HM_NONE;}int sp_handle_messages(){ char module[] = "sp_handle_messages"; char buf[200]; char evt[200]; char trc[300]; if (sp.handshake == HANDSHAKE_CLOSED) return SP_HM_CLOSED; if (sp.handshake != HANDSHAKE_WAITING && sc_receiveready(&sp.sc)) { sc_receive(&sp.sc, buf, sizeof(buf)); remove_special_chars(buf); sprintf(trc, "Received from script: %s", buf); TRC(TRC_INFO, module, trc); sprintf(evt, "SC_%s", buf); if (!libevent_process_event(evt)) { TRC(TRC_ERR, module, "Handler error"); kill(sp.sc.script_pid, SIGTERM); return SP_HM_ERROR; } if (sp.handshake == HANDSHAKE_WAITING) { sp.handshake = HANDSHAKE_CLOSED; return SP_HM_CLOSED; } return SP_HM_OK; } return SP_HM_NONE;}/* Node abstraction functions (to avoid direct access to scripting protocol) */#define DEFINE_ABS_FUN(name, evt) int sp_send_##name (void) \ { \ return sc_send(&sp.sc, evt); \ }#define DEFINE_ABS_EVENT_FUN(name, evt) int sp_send_##name (void) \ { \ if (events_enabled) \ return sc_send(&sp.sc, evt); \ else \ return true;\ }DEFINE_ABS_FUN(ready, "READY")DEFINE_ABS_FUN(device_not_available, "DEVICE_NOT_AVAILABLE")DEFINE_ABS_FUN(error, "ERROR")DEFINE_ABS_FUN(beeping, "BEEPING")DEFINE_ABS_FUN(dialing, "DIALING")DEFINE_ABS_FUN(playing, "PLAYING")DEFINE_ABS_FUN(recording, "RECORDING")DEFINE_ABS_FUN(waiting, "WAITING")DEFINE_ABS_FUN(dtmfing, "DTMFING")DEFINE_ABS_FUN(receiving, "RECEIVING")int sp_send_tty(char *dev){ return sc_send(&sp.sc, dev) && sp_send_ready();}int sp_send_modem(char *modem){ return sc_send(&sp.sc, modem) && sp_send_ready();}int sp_send_dtmf(char dtmf){ char msg[5]; sprintf(msg, "%c", dtmf); return sc_send(&sp.sc, "RECEIVE_DTMF") && sc_send(&sp.sc, msg);}DEFINE_ABS_EVENT_FUN(bong_tone, "BONG_TONE")DEFINE_ABS_EVENT_FUN(busy_tone, "BUSY_TONE")DEFINE_ABS_EVENT_FUN(loop_break, "LOOP_BREAK")DEFINE_ABS_EVENT_FUN(call_waiting, "CALL_WAITING")DEFINE_ABS_EVENT_FUN(dial_tone, "DIAL_TONE")DEFINE_ABS_EVENT_FUN(data_calling_tone, "DATA_CALLING_TONE")DEFINE_ABS_EVENT_FUN(data_or_fax_detected, "DATA_OR_FAX_DETECTED")DEFINE_ABS_EVENT_FUN(fax_calling_tone, "FAX_CALLING_TONE")DEFINE_ABS_EVENT_FUN(handset_on_hook, "HANDSET_ON_HOOK")DEFINE_ABS_EVENT_FUN(handset_off_hook, "HANDSET_OFF_HOOK")DEFINE_ABS_EVENT_FUN(loop_polarity_change, "LOOP_POLARITY_CHANGE")DEFINE_ABS_EVENT_FUN(no_answer, "NO_ANSWER")DEFINE_ABS_EVENT_FUN(no_carrier, "NO_CARRIER")DEFINE_ABS_EVENT_FUN(no_dial_tone, "NO_DIAL_TONE")DEFINE_ABS_EVENT_FUN(no_voice_energy, "NO_VOICE_ENERGY")DEFINE_ABS_EVENT_FUN(ring_detected, "RING_DETECTED")DEFINE_ABS_EVENT_FUN(ringback_detected, "RINGBACK_DETECTED")DEFINE_ABS_EVENT_FUN(silence_detected, "SILENCE_DETECTED")DEFINE_ABS_EVENT_FUN(sit_tone, "SIT_TONE")DEFINE_ABS_EVENT_FUN(tdd_detected, "TDD_DETECTED")DEFINE_ABS_EVENT_FUN(voice_detected, "VOICE_DETECTED")DEFINE_ABS_EVENT_FUN(unknown_event, "UNKNOWN_EVENT")
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -