forked from bruno/ami_c
Rodgger
2 years ago
commit
227dffd6f3
17 changed files with 5314 additions and 0 deletions
@ -0,0 +1,46 @@ |
|||||||
|
|
||||||
|
CC=gcc
|
||||||
|
|
||||||
|
NAME_LIBRARY=libami_c.so
|
||||||
|
|
||||||
|
|
||||||
|
DIR_OBJ=obj/
|
||||||
|
DIR_SRC=src/
|
||||||
|
IR_SRC=src/
|
||||||
|
CFLAGS =
|
||||||
|
|
||||||
|
|
||||||
|
OBJ=\
|
||||||
|
$(DIR_OBJ)parse_action.o \ |
||||||
|
$(DIR_OBJ)parse_event.o \ |
||||||
|
$(DIR_OBJ)parse_string.o \ |
||||||
|
$(DIR_OBJ)asterisk.o \ |
||||||
|
$(DIR_OBJ)net.o \ |
||||||
|
$(DIR_OBJ)ami.o |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
$(NAME_LIBRARY):$(OBJ) |
||||||
|
$(CC) -shared -o $@ $^ -lpthread
|
||||||
|
|
||||||
|
|
||||||
|
$(DIR_OBJ)%.o: $(DIR_SRC)%.c |
||||||
|
$(CC) -shared -fPIC -Wall -c -o $@ $< $(CFLAGS) -I$(DIR_SRC)
|
||||||
|
|
||||||
|
|
||||||
|
install:$(NAME_LIBRARY) |
||||||
|
@cp libami_c.so /usr/local/lib/libami_c.so
|
||||||
|
@ln -s /usr/local/lib/libami_c.so /usr/lib/libami_c.so
|
||||||
|
$(info Copiado pra /usr/lib/libami_c.so)
|
||||||
|
|
||||||
|
|
||||||
|
.PHONY: clean |
||||||
|
clean: |
||||||
|
rm obj/*.o
|
||||||
|
|
||||||
|
.PHONY: uninstall |
||||||
|
uninstall: |
||||||
|
rm /usr/local/lib/libami_c.so
|
||||||
|
rm /usr/lib/libami_c.so
|
||||||
|
|
||||||
|
|
@ -0,0 +1,434 @@ |
|||||||
|
|
||||||
|
#include <ami.h> |
||||||
|
#include <string.h> |
||||||
|
#include <sys/socket.h> |
||||||
|
#include <netinet/in.h> |
||||||
|
#include <arpa/inet.h> |
||||||
|
#include <stdio.h> |
||||||
|
#include <sys/time.h> |
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Primeira função que deverá ser chamada. Essa função inicializa a estrutura necessária.\n |
||||||
|
* \warning Não deve ser liberada diretamente esse ponteiro. Use a função close_ami. |
||||||
|
* \return retorna NULL caso tenha erro |
||||||
|
*/ |
||||||
|
AMI *init_ami(){ |
||||||
|
AMI *ami = calloc(1, sizeof(AMI)); |
||||||
|
if(!ami){ |
||||||
|
return NULL;
|
||||||
|
} |
||||||
|
|
||||||
|
return ami; |
||||||
|
} |
||||||
|
|
||||||
|
/*!
|
||||||
|
* Essa função encerrará essa instância com ami. A memória será liberada dessa instância |
||||||
|
* \return sucesso 0, falha -1 |
||||||
|
*/ |
||||||
|
int close_ami(AMI *ami){ |
||||||
|
|
||||||
|
return 0; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* A conexão com a AMI e algumas informações serão refeitas |
||||||
|
* \return sucesso 0, falha -1 |
||||||
|
*/ |
||||||
|
int restart_ami(AMI *ami){ |
||||||
|
|
||||||
|
return 0; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Defini as credenciais necessárias para fazer login com a ami |
||||||
|
* \return sucesso 0, falha -1 |
||||||
|
*/ |
||||||
|
int set_credentials( AMI *ami, const char *username, const char *password ){ |
||||||
|
|
||||||
|
if(!username || !password){ |
||||||
|
return -1; |
||||||
|
} |
||||||
|
|
||||||
|
if(strlen(username) >= MAX_LEN_USERNAME){ |
||||||
|
return -1; |
||||||
|
} |
||||||
|
|
||||||
|
if(strlen(password) >= MAX_LEN_PASSWORD){ |
||||||
|
return -1; |
||||||
|
} |
||||||
|
|
||||||
|
strcpy(ami->credential.username, username); |
||||||
|
strcpy(ami->credential.password, password); |
||||||
|
|
||||||
|
return 0; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* defini o caminho para conectar ao ami |
||||||
|
* \return sucesso 0, falha -1 |
||||||
|
*/ |
||||||
|
int set_net( AMI *ami, const char *address, int port ){ |
||||||
|
|
||||||
|
if(!address) |
||||||
|
return -1; |
||||||
|
|
||||||
|
if(strlen(address) >= MAX_LEN_ADDRESS){ |
||||||
|
return -1; |
||||||
|
} |
||||||
|
|
||||||
|
strcpy(ami->net.str_address, address); |
||||||
|
|
||||||
|
ami->net.address = inet_addr(address); |
||||||
|
ami->net.port = (port == 0 ? 5038 : port); |
||||||
|
|
||||||
|
|
||||||
|
return 0; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Começa o processo de conexão, obter informação e receber dados do ami |
||||||
|
* \return sucesso 0, falha -1 |
||||||
|
*/ |
||||||
|
int ami (AMI *ami ){ |
||||||
|
|
||||||
|
net_start(ami); |
||||||
|
|
||||||
|
|
||||||
|
return 0; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Mostra a versão que essa instância está conectada. Ex: "13.38.1\0" |
||||||
|
* \warning esse ponteiro não deve ser liberar. |
||||||
|
*/ |
||||||
|
const char *show_version(AMI *ami){ |
||||||
|
return ami->asterisk.version.version;
|
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Mostra apenas o major da versão do asterisk. Ex: versão 13.38.1 -> 13 returno da função. |
||||||
|
* |
||||||
|
* \return sucesso major, falha -1 |
||||||
|
*/ |
||||||
|
int show_version_major(AMI *ami){ |
||||||
|
return ami->asterisk.version.major; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Mostra apenas o minor da versão do asterisk. Ex versão 13.38.1 -> -> 38 returno da função. |
||||||
|
* \return sucesso minor, falha -1 |
||||||
|
*/ |
||||||
|
int show_version_minor(AMI *ami){ |
||||||
|
return ami->asterisk.version.minor; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Mostra apenas o minor2 da versão do asterisk. Ex versão 13.38.1 -> -> 1 returno da função. |
||||||
|
* \return sucesso minor2, falha -1 |
||||||
|
*/ |
||||||
|
int show_version_minor2(AMI *ami){ |
||||||
|
return ami->asterisk.version.minor2; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Retorna se o ami está ativado. Essa função retornará true se conseguir conectar ao ami. |
||||||
|
* \return sucesso 0, falha -1 |
||||||
|
*/ |
||||||
|
int is_ami(AMI *ami){ |
||||||
|
return ami->asterisk.settings.subsystem.ami; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Retorna se o ARA está ativado. |
||||||
|
* \return sucesso 0, falha -1 |
||||||
|
*/ |
||||||
|
int is_ara(AMI *ami){ |
||||||
|
return ami->asterisk.settings.subsystem.ara; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Retorna se o CDR está ativado. |
||||||
|
* \return sucesso 0, falha -1 |
||||||
|
* |
||||||
|
*/ |
||||||
|
int is_cdr(AMI *ami){ |
||||||
|
return ami->asterisk.settings.subsystem.cdr; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Retorna quantidade de memória de acordo com o parâmetro.\n |
||||||
|
* TOTAL_RAM = retorna total da memória |
||||||
|
* FREE_RAM = retorna total livre |
||||||
|
* BUFFER_RAM = retorna o total buffer |
||||||
|
* TOTAL_SWAP = retorna total swap |
||||||
|
* FREE_SWAP = retorna total swap livre |
||||||
|
* \return sucesso >=0, falha -1 |
||||||
|
*/ |
||||||
|
int get_memory(AMI *ami, int type){ |
||||||
|
|
||||||
|
switch( type ){ |
||||||
|
case TOTAL_RAM: |
||||||
|
return ami->asterisk.sysinfo.total_ram; |
||||||
|
break; |
||||||
|
case FREE_RAM: |
||||||
|
return ami->asterisk.sysinfo.free_ram; |
||||||
|
break;
|
||||||
|
case BUFFER_RAM: |
||||||
|
return ami->asterisk.sysinfo.buffer_ram; |
||||||
|
break;
|
||||||
|
case TOTAL_SWAP: |
||||||
|
return ami->asterisk.sysinfo.total_swap_space; |
||||||
|
break;
|
||||||
|
case FREE_SWAP: |
||||||
|
return ami->asterisk.sysinfo.free_swap_space; |
||||||
|
break;
|
||||||
|
default: |
||||||
|
return 0; |
||||||
|
break; |
||||||
|
} |
||||||
|
|
||||||
|
return 0; |
||||||
|
} |
||||||
|
|
||||||
|
/*!
|
||||||
|
* Retorna diretórios configurados de acordo com o parâmetro =
|
||||||
|
* CONFIG_FILE = arquivo de configuração |
||||||
|
* CONFIG_DIR = diretório de configuração |
||||||
|
* MODULE_DIR = diretório de módulos |
||||||
|
* SPOOL_DIR = diretório spool |
||||||
|
* LOG_DIR = diretório de logs |
||||||
|
* RUN_SOCK_DIR = diretórios pid, ctl |
||||||
|
* PID_FILE = arquivo pid |
||||||
|
* VARLIB_DIR = diretórios de bibliotecas |
||||||
|
* DATA_DIR = diretórios de dados |
||||||
|
* ASTDB = armazena dados do banco interno do asterisk |
||||||
|
* IAX_DIR = diretórios chaves utilizadas para autenticação |
||||||
|
* AGI_DIR = diretório AGI que o asterisk procura por padrão |
||||||
|
* \warning esse ponteiro não deve liberar. |
||||||
|
* \return string ou NULL (NULL pode por diretório não definido pelo asterisk) |
||||||
|
*/ |
||||||
|
const char *get_dir(AMI *ami, int type){ |
||||||
|
|
||||||
|
switch( type ){ |
||||||
|
case CONFIG_FILE: |
||||||
|
return ami->asterisk.settings.dir.config_file; |
||||||
|
break; |
||||||
|
|
||||||
|
case CONFIG_DIR: |
||||||
|
return ami->asterisk.settings.dir.config_dir; |
||||||
|
break; |
||||||
|
|
||||||
|
case MODULE_DIR: |
||||||
|
return ami->asterisk.settings.dir.module_dir; |
||||||
|
break; |
||||||
|
|
||||||
|
case SPOOL_DIR: |
||||||
|
return ami->asterisk.settings.dir.spool_dir; |
||||||
|
break; |
||||||
|
|
||||||
|
case LOG_DIR: |
||||||
|
return ami->asterisk.settings.dir.log_dir; |
||||||
|
break; |
||||||
|
|
||||||
|
case RUN_SOCK_DIR: |
||||||
|
return ami->asterisk.settings.dir.run_sock_dir; |
||||||
|
break; |
||||||
|
|
||||||
|
case PID_FILE: |
||||||
|
return ami->asterisk.settings.dir.pid_file; |
||||||
|
break; |
||||||
|
|
||||||
|
case VARLIB_DIR: |
||||||
|
return ami->asterisk.settings.dir.varlib_dir; |
||||||
|
break; |
||||||
|
|
||||||
|
case DATA_DIR: |
||||||
|
return ami->asterisk.settings.dir.data_dir; |
||||||
|
break; |
||||||
|
|
||||||
|
case ASTDB: |
||||||
|
return ami->asterisk.settings.dir.astdb; |
||||||
|
break; |
||||||
|
|
||||||
|
case IAX_DIR: |
||||||
|
return ami->asterisk.settings.dir.iax_dir; |
||||||
|
break; |
||||||
|
|
||||||
|
case AGI_DIR: |
||||||
|
return ami->asterisk.settings.dir.agi_dir; |
||||||
|
break; |
||||||
|
|
||||||
|
default: |
||||||
|
return NULL; |
||||||
|
break; |
||||||
|
} |
||||||
|
|
||||||
|
return NULL; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* A linguagem definida pelo asterisk |
||||||
|
* \warning esse ponteiro não deve liberar. |
||||||
|
* \return sucesso string, falha NULL |
||||||
|
*/ |
||||||
|
int get_language(AMI *ami){ |
||||||
|
return ami->asterisk.settings.language; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Qual o usuário do sistema que o asterisk está rodando |
||||||
|
* \warning Esse ponteiro não deve ser liberar. |
||||||
|
* \return nome do usuário |
||||||
|
*/ |
||||||
|
const char *get_user(AMI *ami){ |
||||||
|
return ami->asterisk.settings.user; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Retorna o grupo no qual o asterisk está execução |
||||||
|
* \warning esse ponteiro não deve liberar. |
||||||
|
* \return nome do grupo |
||||||
|
*/ |
||||||
|
const char *get_group(AMI *ami){ |
||||||
|
return ami->asterisk.settings.group; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/ |
||||||
|
int is_exec_includes(AMI *ami){ |
||||||
|
return ami->asterisk.settings.exec_includes; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Retorna o socket dessa instância que está sendo usado |
||||||
|
* \return socket(int) |
||||||
|
*/ |
||||||
|
int get_socket(AMI *ami){ |
||||||
|
return ami->net.sock; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Está connectado ao ami do asterisk.\n |
||||||
|
* Caso não esteja conectado, a biblioteca continuará tentando conectar. A biblioteca só irá parar de tentar conectar com a função close_ami. |
||||||
|
* \return connectado 1, falha -1 |
||||||
|
*/ |
||||||
|
int is_connected(AMI *ami){ |
||||||
|
return ami->net.is_connected; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Verifica se a comunicação está com login sucesso. Retorna 0 a biblioteca tentará fazer o mesmo login. Para parar as tentativas use função close_ami. |
||||||
|
* \return sucesso 0, falha -1 |
||||||
|
*/ |
||||||
|
int is_logged(AMI *ami){ |
||||||
|
return ami->asterisk.is_logged; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Envia a action que está na struct |
||||||
|
* \return sucesso actionid, fail -1 |
||||||
|
*/ |
||||||
|
int send_action(AMI *ami, struct ss_action *action ){ |
||||||
|
int return_send = 0; |
||||||
|
const char *str_action = NULL; |
||||||
|
str_action = build_str_action(action); |
||||||
|
|
||||||
|
actionid_add(&ami->asterisk.list_actionid, action->args[0].value); |
||||||
|
|
||||||
|
return_send = dispatch_action(ami, str_action); |
||||||
|
|
||||||
|
str_action_free((char *)str_action); |
||||||
|
|
||||||
|
if(return_send == -1){ |
||||||
|
actionid_remove(&ami->asterisk.list_actionid, action->args[0].value); |
||||||
|
} |
||||||
|
|
||||||
|
return return_send; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Cria uma nova estrutura e essa estrutura é usado para criar e mandar action. A actionid será criada com o primeiro argumento args[0]. |
||||||
|
* o args será acrescentada mais 1 para argumentos. |
||||||
|
* |
||||||
|
* struct s_args s_args_action {\n |
||||||
|
* char key[MAX_LEN_KEY_ACTION];\n |
||||||
|
* char value[MAX_LEN_VALUE_ACTION];\n |
||||||
|
* };\n |
||||||
|
* \n |
||||||
|
* struct ss_action {\n |
||||||
|
* char name_action[MAX_LEN_NAME_ACTION];\n |
||||||
|
* int count_args;--- a quantidade de argumentos. action->args[0].key - actionid\n |
||||||
|
* struct s_args *args;\n |
||||||
|
* };\n |
||||||
|
* Use destroy_action para liberar esse ponteiro |
||||||
|
*
|
||||||
|
* \warning A actionid é de acordo com microseconds, portanto tome cuidado se for chamar várias vezes direto. |
||||||
|
* \param args número de argumentos dessa action |
||||||
|
* |
||||||
|
* \return poteiro do tipo ss_action. A action será criada automaticamente na primeira posição dos argumentos |
||||||
|
*/ |
||||||
|
struct ss_action *create_new_action(unsigned int args){ |
||||||
|
|
||||||
|
struct ss_action *action = NULL; |
||||||
|
|
||||||
|
action = calloc(1, sizeof(struct ss_action)); |
||||||
|
|
||||||
|
action->args = calloc(args + 1, sizeof(struct ss_args)); |
||||||
|
|
||||||
|
struct timeval tv; |
||||||
|
gettimeofday(&tv, NULL); |
||||||
|
sprintf(action->args[0].key, "ActionID"); |
||||||
|
sprintf(action->args[0].value, "%ld.%ld", tv.tv_sec, tv.tv_usec); |
||||||
|
|
||||||
|
action->count_args = args + 1; |
||||||
|
|
||||||
|
return action; |
||||||
|
} |
||||||
|
|
||||||
|
/*!
|
||||||
|
* Libera ponteiro para para estrutura ss_action |
||||||
|
* \return sucesso 0 sempre |
||||||
|
*/ |
||||||
|
int destroy_action(struct ss_action *action){ |
||||||
|
|
||||||
|
free(action->args); |
||||||
|
free(action); |
||||||
|
|
||||||
|
return 0; |
||||||
|
} |
||||||
|
|
||||||
|
|
@ -0,0 +1,249 @@ |
|||||||
|
|
||||||
|
#ifndef AMI_H |
||||||
|
#define AMI_H 1 |
||||||
|
|
||||||
|
#include <limits.h> |
||||||
|
#include <time.h> |
||||||
|
#include <pthread.h> |
||||||
|
#include <sys/socket.h> |
||||||
|
#include <netinet/in.h> |
||||||
|
#include <stdlib.h> |
||||||
|
|
||||||
|
#include <ami_simplesip.h> |
||||||
|
|
||||||
|
|
||||||
|
#define TYPE_EVENT 0x1 |
||||||
|
|
||||||
|
#define TIME_UPDATE_ASTERISK 60 /*!< tempo que a biblioteca vai atualizar informações do asterisk */ |
||||||
|
|
||||||
|
#define MAX_BUFFER_NET PATH_MAX /*!< O comprimento máximo que poderá obter através do recv */ |
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Estrutura armazena informações sobre sistema entregue pelo asterisk |
||||||
|
* - core show sysinfo - |
||||||
|
* dentro do ASTERISK |
||||||
|
*/ |
||||||
|
struct s_sysinfo { |
||||||
|
int total_ram; /*!< memória ram no sistema no qual asterisk está rodando */ |
||||||
|
int free_ram; /*!< memória ram livre no sistema no qual asterisk está rodando */ |
||||||
|
int buffer_ram; /*!< memória ram utilizada no sistema no qual asterisk está rodando */ |
||||||
|
int total_swap_space; /*!< memória swap no sistema no qual asterisk está rodando */ |
||||||
|
int free_swap_space; /*!< memória swap livre no sistema no qual asterisk está rodando */ |
||||||
|
int numprocs; /*!< número de processos rodando no sistema */ |
||||||
|
}; |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Estrutura armazena informação de versão do asterisk |
||||||
|
* core show version e core show settings |
||||||
|
* dentro do ASTERISK |
||||||
|
*/ |
||||||
|
struct s_version { |
||||||
|
char *version; /*!< versão em string */ |
||||||
|
int major; /*!< versão major. Ex: 13.38.1 -> major = 13 */ |
||||||
|
int minor; /*!< versão minor. Ex: 13.38.1 - > minor = 38 */ |
||||||
|
int minor2; /*!< versão minor. Ex: 13.38.1 -> minor = 1 */ |
||||||
|
}; |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Estrutura subsystem, armazena quais subsistema estão ativado |
||||||
|
* ami = Asterisk Manager Interface |
||||||
|
* cdr = call data record (call details record) |
||||||
|
* ara = realtime architecture |
||||||
|
* dentro da estrutura struct s_settings |
||||||
|
*/ |
||||||
|
struct s_subsystem{ |
||||||
|
int ami:1; /*!< ami ativado. Sempre estará ativado.*/ |
||||||
|
int cdr:1; /*!< ativado ou desativado cdr*/ |
||||||
|
int ara:1; /*!< ativado ou desativado ara*/ |
||||||
|
}; |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Estrutura de diretórios usado pelo asterisk |
||||||
|
* Dentro da estrutura struct s_settings |
||||||
|
*/ |
||||||
|
struct s_dir { |
||||||
|
char config_file[PATH_MAX]; /*!< arquivo de configuração */ |
||||||
|
char config_dir[PATH_MAX]; /*!< diretório de configuração */ |
||||||
|
char module_dir[PATH_MAX]; /*!< diretório de módulos */ |
||||||
|
char spool_dir[PATH_MAX]; /*!< diretório de spool diretório de chamadas*/ |
||||||
|
char log_dir[PATH_MAX]; /*!< diretório de log */ |
||||||
|
char run_sock_dir[PATH_MAX]; /*!< diretórios socket e pid */ |
||||||
|
char pid_file[PATH_MAX]; /*!< arquivo mostra o pid do asterisk */ |
||||||
|
char varlib_dir[PATH_MAX]; /*!< biblioteca contendo dados usados em tempo de execução */ |
||||||
|
char data_dir[PATH_MAX]; /*!< arquivo contendo dados usados em tempo de execução */ |
||||||
|
char astdb[PATH_MAX]; /*!< armazenar arquivo do banco de dados internos do asterisk */ |
||||||
|
char iax_dir[PATH_MAX]; /*!< armazena arquivos das chaves utilizadas para autenticação */ |
||||||
|
char agi_dir[PATH_MAX]; /*!< scripts AGI que o asterisk procura por padrão */ |
||||||
|
}; |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Estrutura de configurações do asterisk |
||||||
|
* - core show settings - |
||||||
|
* Dentro do ASTERISK |
||||||
|
*/ |
||||||
|
struct s_settings { |
||||||
|
int language; |
||||||
|
char *user; |
||||||
|
char *group; |
||||||
|
int exec_includes:1; |
||||||
|
struct s_subsystem subsystem; |
||||||
|
struct s_dir dir; |
||||||
|
}; |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
struct s_actionid { |
||||||
|
char actionid[MAX_LEN_VALUE_ACTION]; |
||||||
|
struct s_actionid *next; |
||||||
|
}; |
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Estrutura asterisk |
||||||
|
* Dentro do AMI |
||||||
|
*/ |
||||||
|
typedef struct s_asterisk { |
||||||
|
struct s_version version; /*!< estrutura obtém versão do asterisk */ |
||||||
|
int calls_processed; /*!< chamadas processadas pelo asterisk */ |
||||||
|
struct tm uptime; /*!< tempo em execução */ |
||||||
|
struct tm last_reload; /*!< último reload */ |
||||||
|
struct s_sysinfo sysinfo; /*!< informação do sistema no qual asterisk está rodando */ |
||||||
|
struct s_settings settings; /*!< algumas configurações do asterisk */ |
||||||
|
int is_logged:1; /*!< */ |
||||||
|
int init_action:1; /*!< */ |
||||||
|
int time_update; /*!< */ |
||||||
|
int init_response:1; /*!< */ |
||||||
|
struct s_actionid *list_actionid; |
||||||
|
struct s_actionid *list_intern_actionid; |
||||||
|
} ASTERISK; |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Estrutura contém as informações de thread dessa instância |
||||||
|
* Dentro AMI |
||||||
|
*/ |
||||||
|
typedef struct s_thread { |
||||||
|
pthread_t id_thread; /*!< identificador da thread */ |
||||||
|
} THREAD; |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Informações sobre comunicação |
||||||
|
* Dentro AMI |
||||||
|
*/ |
||||||
|
typedef struct s_net{ |
||||||
|
int address; /*!< endereço IPV4 da ami em binary */ |
||||||
|
char *str_address; /*!< endereço IPV4 da ami em ascii */ |
||||||
|
int port; /*!< número da porta que a ami está escutando */ |
||||||
|
struct sockaddr_in sock_addr; /*!< estrutura da rede linux */ |
||||||
|
char buffer_net[MAX_BUFFER_NET]; |
||||||
|
int sock; /*!< file descriptor, o socket */ |
||||||
|
int imcomplete_net:1; |
||||||
|
int is_connected:1; |
||||||
|
int timeout; |
||||||
|
int q_ndata; |
||||||
|
} NET; |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Informação sobre credenciais para fazer login no ami. |
||||||
|
* Dentro AMI |
||||||
|
*/ |
||||||
|
typedef struct s_credentials{ |
||||||
|
char *username; /*!< usuário do ami */ |
||||||
|
char *password; /*!< secret (password) do ami */ |
||||||
|
} CREDENTIAL; |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Estrutura dos dados que chegam da ami |
||||||
|
* Ex: |
||||||
|
* |
||||||
|
* Event: event |
||||||
|
* key: value |
||||||
|
* key: value |
||||||
|
*/ |
||||||
|
typedef struct s_args { |
||||||
|
char *key; /*!< chave do argumento */ |
||||||
|
char *value; /*!< value do argumento */ |
||||||
|
struct s_args *next; |
||||||
|
} ARGS; |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Estrutura de dados da resposta da AMI e suas chaves e valores |
||||||
|
*/ |
||||||
|
typedef struct s_response { |
||||||
|
char *response; /*!< valor da chave response no bloco */ |
||||||
|
ARGS *args; /*!< argumentos do bloco response */ |
||||||
|
int count; /*!< quantidade de argumentos */ |
||||||
|
} RESPONSE; |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* informação do evento |
||||||
|
*/ |
||||||
|
typedef struct s_event{ |
||||||
|
char *event; /*!< nome do evento */ |
||||||
|
ARGS *args; /*!< argumentos do evento */ |
||||||
|
int count; /*!< constagem do event. decrescente 1000 - 0 */ |
||||||
|
struct s_event *next; |
||||||
|
} EVENT; |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* informação da action recebida |
||||||
|
* Dentro ami |
||||||
|
*/ |
||||||
|
typedef struct s_action{ |
||||||
|
RESPONSE *response; |
||||||
|
char *actionid; |
||||||
|
EVENT *event; |
||||||
|
struct s_action *next; |
||||||
|
} ACTION; |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Estrutura principal para usar sobre ami.\n |
||||||
|
* Essa estrutura será opaco para o user externo |
||||||
|
*/ |
||||||
|
struct ami { |
||||||
|
int error_code; /*!< erro no ami */ |
||||||
|
NET net; /*!< sobre a transmissão */ |
||||||
|
CREDENTIAL credential; /*!< credenciais do ami */ |
||||||
|
ACTION *actions; /*!< action recebido da ami. Respostas e event */ |
||||||
|
EVENT *events; /*!< event recebido da ami */ |
||||||
|
THREAD thread; /*!< informaçãos da thread em execução */ |
||||||
|
ASTERISK asterisk; /*!< informações relevantes do asterisk. Ex: memória, versão, diretórios . . . */ |
||||||
|
}; |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#include <ami_simplesip.h> |
||||||
|
#include <parse_action.h> |
||||||
|
#include <parse_event.h> |
||||||
|
#include <parse_string.h> |
||||||
|
#include <asterisk.h> |
||||||
|
#include <net.h> |
||||||
|
|
||||||
|
|
||||||
|
#endif |
||||||
|
|
||||||
|
|
@ -0,0 +1,314 @@ |
|||||||
|
|
||||||
|
#ifndef AMI_C_H |
||||||
|
#define AMI_C_H 1 |
||||||
|
|
||||||
|
#define MAX_LEN_KEY_ACTION 50 /*!< maior comprimento permitido pelo chave no argumento */ |
||||||
|
#define MAX_LEN_VALUE_ACTION 256 /*!< maior comprimento permitido pelo valor da chave no argumento */ |
||||||
|
#define MAX_LEN_NAME_ACTION 50 /*!< maior comprimento permitido pelo nome de um action */ |
||||||
|
#define MAX_LEN_USERNAME 32 /*!< tamanho máximo que o username terá */ |
||||||
|
#define MAX_LEN_PASSWORD 64 /*!< tamanho máximo que o secret terá */ |
||||||
|
#define MAX_LEN_ADDRESS 15 /*!< texto ip. Ex: 10.100.100.10 */ |
||||||
|
|
||||||
|
struct ss_args { |
||||||
|
char key[MAX_LEN_KEY_ACTION]; |
||||||
|
char value[MAX_LEN_VALUE_ACTION]; |
||||||
|
}; |
||||||
|
|
||||||
|
struct ss_action { |
||||||
|
char name_action[MAX_LEN_NAME_ACTION]; |
||||||
|
int count_args; |
||||||
|
struct s_args *args; |
||||||
|
}; |
||||||
|
|
||||||
|
|
||||||
|
typedef struct ami AMI; |
||||||
|
|
||||||
|
|
||||||
|
#define TOTAL_RAM 0x1 |
||||||
|
#define FREE_RAM 0x2 |
||||||
|
#define BUFFER_RAM 0x3 |
||||||
|
#define TOTAL_SWAP 0x4 |
||||||
|
#define FREE_SWAP 0x5 |
||||||
|
|
||||||
|
|
||||||
|
#define CONFIG_FILE 0x1 |
||||||
|
#define CONFIG_DIR 0x2 |
||||||
|
#define MODULE_DIR 0x3 |
||||||
|
#define SPOOL_DIR 0x4 |
||||||
|
#define LOG_DIR 0x5 |
||||||
|
#define RUN_SOCK_DIR 0x6 |
||||||
|
#define PID_FILE 0x7 |
||||||
|
#define VARLIB_DIR 0x8 |
||||||
|
#define DATA_DIR 0x9 |
||||||
|
#define ASTDB 0xa |
||||||
|
#define IAX_DIR 0xb |
||||||
|
#define AGI_DIR 0xc |
||||||
|
|
||||||
|
/*!
|
||||||
|
* Primeira função que deverá ser chamada. Essa função inicializa a estrutura necessária.\n |
||||||
|
* \warning Não deve ser liberada diretamente esse ponteiro. Use a função close_ami. |
||||||
|
* \return retorna NULL caso tenha erro |
||||||
|
*/ |
||||||
|
AMI *init_ami(); |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Essa função encerrará essa instância com ami. A memória será liberada dessa instância |
||||||
|
* \return sucesso 0, falha -1 |
||||||
|
*/ |
||||||
|
int close_ami(AMI *ami); |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* A conexão com a AMI e algumas informações serão refeitas |
||||||
|
* \return sucesso 0, falha -1 |
||||||
|
*/ |
||||||
|
int restart_ami(AMI *ami); |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Defini as credenciais necessárias para fazer login com a ami |
||||||
|
* \return sucesso 0, falha -1 |
||||||
|
*/ |
||||||
|
int set_credentials( AMI *ami, const char *username, const char *password ); |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* defini o caminho para conectar ao ami |
||||||
|
* \return sucesso 0, falha -1 |
||||||
|
*/ |
||||||
|
int set_net( AMI *ami, const char *address, int port ); |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Começa o processo de conexão, obter informação e receber dados do ami |
||||||
|
* \return sucesso 0, falha -1 |
||||||
|
*/ |
||||||
|
int ami (AMI *ami ); |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Mostra a versão que essa instância está conectada. Ex: "13.38.1\0" |
||||||
|
* \warning esse ponteiro não deve ser liberar. |
||||||
|
*/ |
||||||
|
const char *show_version(AMI *ami); |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Mostra apenas o major da versão do asterisk. Ex: versão 13.38.1 -> 13 returno da função. |
||||||
|
* |
||||||
|
* \return sucesso major, falha -1 |
||||||
|
*/ |
||||||
|
int show_version_major(AMI *ami); |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Mostra apenas o minor da versão do asterisk. Ex versão 13.38.1 -> -> 38 returno da função. |
||||||
|
* \return sucesso minor, falha -1 |
||||||
|
*/ |
||||||
|
int show_version_minor(AMI *ami); |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Mostra apenas o minor2 da versão do asterisk. Ex versão 13.38.1 -> -> 1 returno da função. |
||||||
|
* \return sucesso minor2, falha -1 |
||||||
|
*/ |
||||||
|
int show_version_minor2(AMI *ami); |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Retorna se o ami está ativado. Essa função retornará true se conseguir conectar ao ami. |
||||||
|
* \return sucesso 0, falha -1 |
||||||
|
*/ |
||||||
|
int is_ami(AMI *ami); |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Retorna se o ARA está ativado. |
||||||
|
* \return sucesso 0, falha -1 |
||||||
|
*/ |
||||||
|
int is_ara(AMI *ami); |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Retorna se o CDR está ativado. |
||||||
|
* \return sucesso 0, falha -1 |
||||||
|
* |
||||||
|
*/ |
||||||
|
int is_cdr(AMI *ami); |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Retorna quantidade de memória de acordo com o parâmetro.\n |
||||||
|
* TOTAL_RAM = retorna total da memória |
||||||
|
* FREE_RAM = retorna total livre |
||||||
|
* BUFFER_RAM = retorna o total buffer |
||||||
|
* TOTAL_SWAP = retorna total swap |
||||||
|
* FREE_SWAP = retorna total swap livre |
||||||
|
* \return sucesso >=0, falha -1 |
||||||
|
*/ |
||||||
|
int get_memory(AMI *ami, int type); |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Retorna diretórios configurados de acordo com o parâmetro =
|
||||||
|
* CONFIG_FILE = arquivo de configuração |
||||||
|
* CONFIG_DIR = diretório de configuração |
||||||
|
* MODULE_DIR = diretório de módulos |
||||||
|
* SPOOL_DIR = diretório spool |
||||||
|
* LOG_DIR = diretório de logs |
||||||
|
* RUN_SOCK_DIR = diretórios pid, ctl |
||||||
|
* PID_FILE = arquivo pid |
||||||
|
* VARLIB_DIR = diretórios de bibliotecas |
||||||
|
* DATA_DIR = diretórios de dados |
||||||
|
* ASTDB = armazena dados do banco interno do asterisk |
||||||
|
* IAX_DIR = diretórios chaves utilizadas para autenticação |
||||||
|
* AGI_DIR = diretório AGI que o asterisk procura por padrão |
||||||
|
* \warning esse ponteiro não deve liberar. |
||||||
|
* \return string ou NULL (NULL pode por diretório não definido pelo asterisk) |
||||||
|
*/ |
||||||
|
const char *get_dir(AMI *ami, int type); |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* A linguagem definida pelo asterisk |
||||||
|
* \warning esse ponteiro não deve liberar. |
||||||
|
* \return sucesso string, falha NULL |
||||||
|
*/ |
||||||
|
int get_language(AMI *ami); |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Qual o usuário do sistema que o asterisk está rodando |
||||||
|
* \warning Esse ponteiro não deve ser liberar. |
||||||
|
* \return nome do usuário |
||||||
|
*/ |
||||||
|
const char *get_user(AMI *ami); |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Retorna o grupo no qual o asterisk está execução |
||||||
|
* \warning esse ponteiro não deve liberar. |
||||||
|
* \return nome do grupo |
||||||
|
*/ |
||||||
|
const char *get_group(AMI *ami); |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/ |
||||||
|
int is_exec_includes(AMI *ami); |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Retorna o socket dessa instância que está sendo usado |
||||||
|
* \return socket(int) |
||||||
|
*/ |
||||||
|
int get_socket(AMI *ami); |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Está connectado ao ami do asterisk.\n |
||||||
|
* Caso não esteja conectado, a biblioteca continuará tentando conectar. A biblioteca só irá parar de tentar conectar com a função close_ami. |
||||||
|
* \return connectado 1, falha -1 |
||||||
|
*/ |
||||||
|
int is_connected(AMI *ami); |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Verifica se a comunicação está com login sucesso. Retorna 0 a biblioteca tentará fazer o mesmo login. Para parar as tentativas use função close_ami. |
||||||
|
* \return sucesso 0, falha -1 |
||||||
|
*/ |
||||||
|
int is_logged(AMI *ami); |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Envia a action que está na struct |
||||||
|
* \return sucesso actionid, fail -1 |
||||||
|
*/ |
||||||
|
int send_action(AMI *ami, struct ss_action *action ); |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Cria uma nova estrutura e essa estrutura é usado para criar e mandar action. A actionid será criada com o primeiro argumento args[0]. |
||||||
|
* o args será acrescentada mais 1 para argumentos. |
||||||
|
* |
||||||
|
* struct s_args s_args_action {\n |
||||||
|
* char key[MAX_LEN_KEY_ACTION];\n |
||||||
|
* char value[MAX_LEN_VALUE_ACTION];\n |
||||||
|
* };\n |
||||||
|
* \n |
||||||
|
* struct ss_action {\n |
||||||
|
* char name_action[MAX_LEN_NAME_ACTION];\n |
||||||
|
* int count_args;--- a quantidade de argumentos. action->args[0].key - actionid\n |
||||||
|
* struct s_args *args;\n |
||||||
|
* };\n |
||||||
|
* Use destroy_action para liberar esse ponteiro |
||||||
|
*
|
||||||
|
* \warning A actionid é de acordo com microseconds, portanto tome cuidado se for chamar várias vezes direto. |
||||||
|
* \param args número de argumentos dessa action |
||||||
|
* |
||||||
|
* \return poteiro do tipo ss_action. A action será criada automaticamente na primeira posição dos argumentos |
||||||
|
*/ |
||||||
|
struct ss_action *create_new_action(unsigned int args); |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Libera ponteiro para para estrutura ss_action |
||||||
|
* \return sucesso 0 sempre |
||||||
|
*/ |
||||||
|
int destroy_action(struct ss_action *action); |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#endif |
||||||
|
|
@ -0,0 +1,374 @@ |
|||||||
|
#include <ami.h> |
||||||
|
#include <string.h> |
||||||
|
|
||||||
|
/*!
|
||||||
|
* A função é usado para inicializar ami com métodos que retornarão informação ami ami |
||||||
|
* \param ami estrutura geral sobre informações da ami (asterisk) |
||||||
|
* \return sucesso 0, falha -1 |
||||||
|
*/ |
||||||
|
int init_methods( AMI *ami ){ |
||||||
|
|
||||||
|
struct ss_action *sysinfo = create_new_action(1); |
||||||
|
strcpy(sysinfo->name_action, "command"); |
||||||
|
strcpy(sysinfo->args[1].key, "command"); |
||||||
|
strcpy(sysinfo->args[1].value, "core show sysinfo"); |
||||||
|
if(send_action(ami, sysinfo) == -1){ |
||||||
|
return -1; |
||||||
|
} |
||||||
|
|
||||||
|
struct ss_action *settings = create_new_action(1); |
||||||
|
strcpy(settings->name_action, "command"); |
||||||
|
strcpy(settings->args[1].key, "command"); |
||||||
|
strcpy(settings->args[1].value, "core show settings"); |
||||||
|
if(send_action(ami, settings) == -1){ |
||||||
|
return -1; |
||||||
|
} |
||||||
|
|
||||||
|
return 0; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Verifica se o evento continua esperando informação da AMI |
||||||
|
* |
||||||
|
* \param list_actions lista das actionid ativas, ou seja, esperando concluir a resposta |
||||||
|
* \param actionid valor da actionid que será verificada |
||||||
|
* \return sucesso 0, falha -1 |
||||||
|
*/ |
||||||
|
int is_actionid(struct s_actionid **list_actions, const char *actionid){ |
||||||
|
|
||||||
|
int bytes = strlen(actionid); |
||||||
|
|
||||||
|
while(*list_actions){ |
||||||
|
if(!strncmp(actionid, (*list_actions)->actionid, (bytes < strlen((*list_actions)->actionid)) ? strlen((*list_actions)->actionid) : bytes)){ |
||||||
|
return 0; |
||||||
|
} |
||||||
|
|
||||||
|
list_actions = &(*list_actions)->next; |
||||||
|
} |
||||||
|
|
||||||
|
return -1; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Adicionar novas actionid. A biblioteca obterá apenas actionid que estão nessa estrutura |
||||||
|
* |
||||||
|
* \param list_actions lista de actionid ativas |
||||||
|
* \param actionid será adicionada na lista |
||||||
|
* |
||||||
|
* \return sucesso 0, falha -1 |
||||||
|
*/ |
||||||
|
int actionid_add(struct s_actionid **list_actions, const char *actionid){ |
||||||
|
|
||||||
|
while( (*list_actions) ){ |
||||||
|
list_actions = &(*list_actions)->next; |
||||||
|
} |
||||||
|
|
||||||
|
*list_actions = calloc(1, sizeof(struct s_actionid)); |
||||||
|
|
||||||
|
|
||||||
|
strcpy((*list_actions)->actionid, actionid); |
||||||
|
|
||||||
|
return 0; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* remove a actionid da lista de actionid ativas. A biblioteca vai ignorar actionid que estão fora dessa estrutura.\n |
||||||
|
* Apenas quando essa actionid for concluída |
||||||
|
* |
||||||
|
* \param list_actions lista de actionid ativas |
||||||
|
* \param actionid actionid que será excluída da lista |
||||||
|
* |
||||||
|
* \return sucesso 0, falha -1 |
||||||
|
*/ |
||||||
|
int actionid_remove( struct s_actionid **list_actions, const char *actionid ){ |
||||||
|
|
||||||
|
struct s_actionid *drop_actionid = NULL; |
||||||
|
|
||||||
|
while( (*list_actions) ){ |
||||||
|
|
||||||
|
if( !strcmp( (*list_actions)->actionid, actionid ) ){ |
||||||
|
drop_actionid = *list_actions; |
||||||
|
actionid_free(drop_actionid); |
||||||
|
*list_actions = (*list_actions)->next; |
||||||
|
return 0; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
return -1; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Libera o actionid |
||||||
|
* \param drop_actionid ponteiro para estrutura |
||||||
|
* \return 0 sempre |
||||||
|
*/ |
||||||
|
int actionid_free( struct s_actionid *drop_actionid ){ |
||||||
|
|
||||||
|
free(drop_actionid); |
||||||
|
return 0; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
////* EVENT *////
|
||||||
|
/*!
|
||||||
|
* Adicionar eventos lista de eventos da ami.
|
||||||
|
* |
||||||
|
* \param event lista de eventos recebido do AMI |
||||||
|
* \param next próximo evento que será incluído na lista de eventos |
||||||
|
*
|
||||||
|
*/ |
||||||
|
void event_add(EVENT **event, EVENT *next){ |
||||||
|
|
||||||
|
while((*event)){ |
||||||
|
event = &(*event)->next; |
||||||
|
} |
||||||
|
|
||||||
|
*event = next; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Cria a estrutura de um novo evento.
|
||||||
|
* |
||||||
|
* \warning Esse ponteiro deve ser liberado através do free_event. |
||||||
|
* |
||||||
|
* \return p_event um novo espaço para alocar eventos da AMI |
||||||
|
*/ |
||||||
|
EVENT *event_create(){ |
||||||
|
EVENT *p_event = calloc(1, sizeof(EVENT)); |
||||||
|
return p_event; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Libera ponteiro do EVENT único e seus argumentos. Não vai liberar os próximos eventos "event->next" |
||||||
|
* |
||||||
|
* \param event estrutura que contém um evento da AMI |
||||||
|
*/ |
||||||
|
void event_free( EVENT *event ){ |
||||||
|
|
||||||
|
free(event->event); |
||||||
|
list_args_free(event->args); |
||||||
|
free(event); |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Libera a lista do eventos da AMI |
||||||
|
* |
||||||
|
* \param event lista de eventos que serão liberadas |
||||||
|
*/ |
||||||
|
void list_event_free(EVENT *event){ |
||||||
|
|
||||||
|
if(event->next){ |
||||||
|
list_event_free(event->next); |
||||||
|
} |
||||||
|
|
||||||
|
event_free(event); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
////* ARGUMENTOS *////
|
||||||
|
/*!
|
||||||
|
* Adiciona o argumento dentro do evento
|
||||||
|
* |
||||||
|
* \param event estrutura de evento que será
|
||||||
|
* \param arg
|
||||||
|
* |
||||||
|
*/ |
||||||
|
void args_event_add(EVENT *event, struct s_args *arg){ |
||||||
|
|
||||||
|
struct s_args **args = &event->args; |
||||||
|
while((*args)) { |
||||||
|
args = &(*args)->next; |
||||||
|
} |
||||||
|
|
||||||
|
*args = arg; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Adiciona argumento para estrutura RESPONSE |
||||||
|
*
|
||||||
|
* \param args lista de argumentos |
||||||
|
* \param arg argumento que será inserido |
||||||
|
*/ |
||||||
|
void args_add( ARGS **args, ARGS *arg ){ |
||||||
|
|
||||||
|
|
||||||
|
while(*args){ |
||||||
|
args = &(*args)->next; |
||||||
|
} |
||||||
|
|
||||||
|
*args = arg; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Cria uma estrutura para um argumento. |
||||||
|
* \return arg estrutura do tipo struct s_args |
||||||
|
*/ |
||||||
|
struct s_args *arg_create(){ |
||||||
|
struct s_args *arg = calloc(1, sizeof(struct s_args)); |
||||||
|
return arg; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* libera o ponteiro para estrutura do argumento.
|
||||||
|
* \param arg liberar ponteiro |
||||||
|
*/ |
||||||
|
void args_free(ARGS *arg){ |
||||||
|
|
||||||
|
free(arg->key); |
||||||
|
free(arg->value); |
||||||
|
|
||||||
|
free(arg); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* libera lista de argumentos. O ponteiro atuais e membros next args->next |
||||||
|
* \param args pointeiro para essa lista |
||||||
|
*
|
||||||
|
*/ |
||||||
|
void list_args_free(ARGS *args){ |
||||||
|
|
||||||
|
if(args->next){ |
||||||
|
list_args_free(args->next); |
||||||
|
} |
||||||
|
|
||||||
|
args_free(args); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
////* RESPONSE *////
|
||||||
|
/*!
|
||||||
|
* Cria estrutura RESPONSE |
||||||
|
* \return response estrutura vazia que será usada para preencher resposta da AMI |
||||||
|
*/ |
||||||
|
RESPONSE *response_create(){ |
||||||
|
RESPONSE *response; |
||||||
|
response = calloc(1, sizeof(RESPONSE)); |
||||||
|
return response; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Adiciona Response na estrutura Action |
||||||
|
* \param action estrutura action |
||||||
|
* \param response será adicionado para o ACtion |
||||||
|
*/ |
||||||
|
void action_response_add(ACTION *action, RESPONSE *response){ |
||||||
|
|
||||||
|
if(!action->response){ |
||||||
|
action->response = response; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Libera espaço do ponteiro da entrutura RESPONSE |
||||||
|
* \param response estrutura response que será liberada |
||||||
|
*/ |
||||||
|
int response_free(RESPONSE *response){ |
||||||
|
|
||||||
|
list_args_free(response->args); |
||||||
|
free(response); |
||||||
|
|
||||||
|
return 0; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
////* ACTION *////
|
||||||
|
/*!
|
||||||
|
* criar estrutura para preenche-la com resposta da action |
||||||
|
* \return ACTION nova estrutura ACTION
|
||||||
|
*/ |
||||||
|
ACTION *action_create(){ |
||||||
|
ACTION * action; |
||||||
|
action = calloc(1, sizeof(ACTION)); |
||||||
|
return action; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* liberar uma action da estrutura |
||||||
|
* \param action lista de actions |
||||||
|
* \param toremove o action que será escluída da lista |
||||||
|
* \return
|
||||||
|
*/ |
||||||
|
int action_remove(ACTION **list_action, ACTION *toremove){ |
||||||
|
|
||||||
|
while(*list_action){ |
||||||
|
if(*list_action == toremove){ |
||||||
|
ACTION *p = (*list_action); |
||||||
|
(*list_action) = (*list_action)->next; |
||||||
|
action_free(p); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
return 0; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* libera toda a lista do action |
||||||
|
* \param list_action lista das action |
||||||
|
* \return 0 |
||||||
|
*/ |
||||||
|
int list_action_free(ACTION *list_action){ |
||||||
|
|
||||||
|
if(list_action){ |
||||||
|
list_action_free(list_action->next); |
||||||
|
} |
||||||
|
|
||||||
|
action_free(list_action); |
||||||
|
|
||||||
|
return 0; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* libera action a estrutura action |
||||||
|
* \param action ponteiro para estrutura action |
||||||
|
* \return sempre sucesso 0 |
||||||
|
*/ |
||||||
|
int action_free(ACTION *action){ |
||||||
|
|
||||||
|
response_free(action->response); |
||||||
|
free(action->actionid); |
||||||
|
list_event_free(action->event); |
||||||
|
free(action); |
||||||
|
|
||||||
|
return 0; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Adicionar action na lista de action |
||||||
|
* \param action lista action |
||||||
|
* \param next estrutura action que será inserida |
||||||
|
* \return sucesso 0, falha -1 |
||||||
|
*/ |
||||||
|
int action_add(ACTION **action, ACTION *next){ |
||||||
|
|
||||||
|
while(*action){ |
||||||
|
action = &(*action)->next; |
||||||
|
} |
||||||
|
|
||||||
|
*action = next; |
||||||
|
|
||||||
|
return 0; |
||||||
|
} |
||||||
|
|
@ -0,0 +1,226 @@ |
|||||||
|
|
||||||
|
#ifndef ASTERISK_H |
||||||
|
#define ASTERISK_H 1 |
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* A função é usado para inicializar ami com métodos que retornarão informação ami ami |
||||||
|
* \param ami estrutura sobre informações da ami (asterisk) |
||||||
|
*/ |
||||||
|
int init_methods( AMI *ami ); |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Verifica se o evento continua esperando informação da AMI |
||||||
|
* |
||||||
|
* \param list_actions lista das actionid ativas, ou seja, esperando concluir a resposta |
||||||
|
* \param actionid valor da actionid que será verificada |
||||||
|
* \return sucesso 0, falha -1 |
||||||
|
*/ |
||||||
|
int is_actionid(struct s_actionid **list_actions, const char *actionid); |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Adicionar novas actionid. A biblioteca obterá apenas actionid que estão nessa estrutura |
||||||
|
* |
||||||
|
* \param list_actions lista de actionid ativas |
||||||
|
* \param actionid será adicionada na lista |
||||||
|
* |
||||||
|
* \return sucesso 0, falha -1 |
||||||
|
*/ |
||||||
|
int actionid_add(struct s_actionid **list_actions, const char *actionid); |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* remove a actionid da lista de actionid ativas. A biblioteca vai ignorar actionid que estão fora dessa estrutura.\n |
||||||
|
* Apenas quando essa actionid for concluída |
||||||
|
* |
||||||
|
* \param list_actions lista de actionid ativas |
||||||
|
* \param actionid actionid que será excluída da lista |
||||||
|
* |
||||||
|
* \return sucesso 0, falha -1 |
||||||
|
*/ |
||||||
|
int actionid_remove( struct s_actionid **list_actions, const char *actionid ); |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Libera o actionid |
||||||
|
* \param drop_actionid ponteiro para estrutura |
||||||
|
* \return 0 sempre |
||||||
|
*/ |
||||||
|
int actionid_free( struct s_actionid *drop_actionid ); |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Adicionar eventos lista de eventos da ami.
|
||||||
|
* |
||||||
|
* \param event lista de eventos recebido do AMI |
||||||
|
* \param next próximo evento que será incluído na lista de eventos |
||||||
|
*
|
||||||
|
*/ |
||||||
|
void event_add(EVENT **event, EVENT *next); |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Cria a estrutura de um novo evento.
|
||||||
|
* |
||||||
|
* \warning Esse ponteiro deve ser liberado através do free_event. |
||||||
|
* |
||||||
|
* \return p_event um novo espaço para alocar eventos da AMI |
||||||
|
*/ |
||||||
|
EVENT *event_create(); |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Libera ponteiro do EVENT único e seus argumentos. Não vai liberar os próximos eventos "event->next" |
||||||
|
* |
||||||
|
* \param event estrutura que contém um evento da AMI |
||||||
|
*/ |
||||||
|
void event_free( EVENT *event ); |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Libera a lista do eventos da AMI |
||||||
|
* |
||||||
|
* \param event lista de eventos que serão liberadas |
||||||
|
*/ |
||||||
|
void list_event_free(EVENT *event); |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Adiciona o argumento dentro do evento
|
||||||
|
* |
||||||
|
* \param event estrutura de evento que será
|
||||||
|
* \param arg
|
||||||
|
* |
||||||
|
*/ |
||||||
|
void args_event_add(EVENT *event, struct s_args *arg); |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Adiciona argumento para estrutura RESPONSE |
||||||
|
* \param args lista de argumentos |
||||||
|
* \param arg argumento que será inserido na lista |
||||||
|
*/ |
||||||
|
void args_add( ARGS **args, ARGS *arg ); |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Cria uma estrutura para um argumento. |
||||||
|
* \return arg estrutura do tipo struct s_args |
||||||
|
*/ |
||||||
|
struct s_args *arg_create(); |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* libera o ponteiro para estrutura do argumento.
|
||||||
|
*
|
||||||
|
* \return void |
||||||
|
*/ |
||||||
|
void args_free(ARGS *arg); |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* libera lista de argumentos. O ponteiro atuais e membros next args->next |
||||||
|
* \param args pointeiro para essa lista |
||||||
|
*
|
||||||
|
*/ |
||||||
|
void list_args_free(ARGS *args); |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Cria estrutura RESPONSE |
||||||
|
* \return response estrutura vazia que será usada para preencher resposta da AMI |
||||||
|
*/ |
||||||
|
RESPONSE *response_create(); |
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Adiciona Response na estrutura Action |
||||||
|
* \param action estrutura action |
||||||
|
* \param response será adicionado para o ACtion |
||||||
|
*/ |
||||||
|
void action_response_add(ACTION *action, RESPONSE *response); |
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Libera espaço do ponteiro da entrutura RESPONSE |
||||||
|
* \param response estrutura response que será liberada |
||||||
|
*/ |
||||||
|
int response_free(RESPONSE *response); |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* criar estrutura para preenche-la com resposta da action |
||||||
|
* \return ACTION nova estrutura ACTION
|
||||||
|
*/ |
||||||
|
ACTION *action_create(); |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* liberar uma action da estrutura |
||||||
|
* \param action lista de actions |
||||||
|
* \param toremove o action que será escluída da lista |
||||||
|
* \return 0 sempre |
||||||
|
*/ |
||||||
|
int action_remove(ACTION **list_action, ACTION *toremove); |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* libera toda a lista do action |
||||||
|
* \param list_action lista das action |
||||||
|
* \return 0 |
||||||
|
*/ |
||||||
|
int list_action_free(ACTION *list_action); |
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* remove a actionid da lista de actionid ativas. A biblioteca vai ignorar actionid que estão fora dessa estrutura.\n |
||||||
|
* Apenas quando essa actionid for concluída |
||||||
|
* |
||||||
|
* \param list_actions lista de actionid ativas |
||||||
|
* \param actionid actionid que será excluída da lista |
||||||
|
* |
||||||
|
* \return sucesso 0, falha -1 |
||||||
|
*/ |
||||||
|
int actionid_remove( struct s_actionid **list_actions, const char *actionid ); |
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* libera action a estrutura action |
||||||
|
* \param action ponteiro para estrutura action |
||||||
|
* \return sempre sucesso 0 |
||||||
|
*/ |
||||||
|
int action_free(ACTION *action); |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Adicionar action na lista de action |
||||||
|
* \param action lista action |
||||||
|
* \param next estrutura action que será inserida |
||||||
|
* \return sucesso 0, falha -1 |
||||||
|
*/ |
||||||
|
int action_add(ACTION **action, ACTION *next); |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#endif |
||||||
|
|
@ -0,0 +1,385 @@ |
|||||||
|
#include <ami.h> |
||||||
|
#include <string.h> |
||||||
|
#include <errno.h> |
||||||
|
#include <poll.h> |
||||||
|
#include <unistd.h> |
||||||
|
#include <fcntl.h> |
||||||
|
#include <pthread.h> |
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Cria um sockect e defini opções desse conexão |
||||||
|
* |
||||||
|
* \return sucesso 0 |
||||||
|
*/ |
||||||
|
static int create_socket(NET *net); |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* O módulo net começa ser usada. Essa função fará thread para começar a conexão. |
||||||
|
* \param ami identifica qual instância da conexão |
||||||
|
* \return sucesso 0 |
||||||
|
*/ |
||||||
|
int net_start(AMI *ami){ |
||||||
|
|
||||||
|
ami->thread.id_thread = pthread_create(&ami->thread.id_thread, NULL, net, (void *)ami); |
||||||
|
|
||||||
|
return 0; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Começará a conexão com a ami de acordo com os parâmetro passado |
||||||
|
* \param void_ami identifica qual instância da conexão em tipo void * |
||||||
|
* \return void * |
||||||
|
*/ |
||||||
|
void *net(void *void_ami){ |
||||||
|
AMI *ami = void_ami; |
||||||
|
|
||||||
|
create_socket(&ami->net); |
||||||
|
|
||||||
|
while(1){ |
||||||
|
|
||||||
|
if(ami->net.is_connected == 0){ |
||||||
|
connect_ami(&ami->net); |
||||||
|
} |
||||||
|
|
||||||
|
if(ami->net.is_connected == 1 && ami->asterisk.is_logged == 0){ |
||||||
|
dispatch_login(ami); |
||||||
|
} |
||||||
|
|
||||||
|
if(ami->net.is_connected == 1 && ami->asterisk.is_logged == 1){ |
||||||
|
communication_ami(ami); |
||||||
|
connect_login_down(&ami->net, &ami->asterisk); |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Retira o login e a conexão definida da estrutura.\n |
||||||
|
* Reset conexão e login |
||||||
|
*/ |
||||||
|
void connect_login_down(NET *net, ASTERISK *asterisk){ |
||||||
|
connect_down(net); |
||||||
|
login_down(asterisk); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Derruba a conexão com o ami |
||||||
|
* \param net estrutura de informações de rede da biblioteca |
||||||
|
*/ |
||||||
|
void connect_down(NET *net){ |
||||||
|
|
||||||
|
net->is_connected = 0; |
||||||
|
net->imcomplete_net = 0; |
||||||
|
sock_close(net->sock); |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Levanta a conexão, isto é, define na estrutura que a conexão está conectada. |
||||||
|
* \param net estrutura responsável por tratar rede |
||||||
|
*/ |
||||||
|
void connect_up(NET *net){ |
||||||
|
net->is_connected = 1; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Define na estrutura que não está logado |
||||||
|
* \param asterisk estrutura sobre o asterisk a ami do outro lado |
||||||
|
* \return void |
||||||
|
*/ |
||||||
|
void login_down(ASTERISK *asterisk){ |
||||||
|
asterisk->is_logged = 0; |
||||||
|
asterisk->init_action = 0; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Define na estrutura que está logado |
||||||
|
* |
||||||
|
*/ |
||||||
|
void login_up(ASTERISK *asterisk){ |
||||||
|
asterisk->is_logged = 1; |
||||||
|
} |
||||||
|
|
||||||
|
/*!
|
||||||
|
* Envia uma action para asterisk. send_action é função externa. dispatch_action é uma função interna |
||||||
|
* \param ami estrutura de instância da biblioteca |
||||||
|
* \param action action que será enviado |
||||||
|
* \return sucesso 1, falha -1 |
||||||
|
*/ |
||||||
|
int dispatch_action(AMI *ami, const char *action){ |
||||||
|
|
||||||
|
if( !ami->net.is_connected || !ami->asterisk.is_logged ){ |
||||||
|
return -1; |
||||||
|
} |
||||||
|
|
||||||
|
ssize_t len, data_sent; |
||||||
|
char *p_action; |
||||||
|
p_action = (char *)action; |
||||||
|
|
||||||
|
/*
|
||||||
|
* Enviar actions pela rede |
||||||
|
*/ |
||||||
|
len = strlen(p_action); |
||||||
|
while((data_sent = send(ami->net.sock, p_action, len, MSG_DONTWAIT|MSG_NOSIGNAL)) > 0){ |
||||||
|
|
||||||
|
/* looop enviar pacote que não foi enviado */ |
||||||
|
p_action += data_sent; |
||||||
|
len -= data_sent; |
||||||
|
} |
||||||
|
|
||||||
|
if(data_sent == -1){ |
||||||
|
return -1; |
||||||
|
} |
||||||
|
|
||||||
|
return 0; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* envia a action para login ami |
||||||
|
* \return sucesso 0, falha -1 |
||||||
|
*/ |
||||||
|
int dispatch_login(AMI *ami){ |
||||||
|
|
||||||
|
if( ami->net.is_connected == 0 || ami->asterisk.is_logged == 0 ){ |
||||||
|
return -1; |
||||||
|
} |
||||||
|
|
||||||
|
const char *str_login = NULL; |
||||||
|
|
||||||
|
str_login = build_str_login(&ami->credential); |
||||||
|
|
||||||
|
if( dispatch_login(ami) == -1 ){ |
||||||
|
return -1; |
||||||
|
} |
||||||
|
|
||||||
|
free_str_login((char *) str_login); |
||||||
|
|
||||||
|
if( done_login( &ami->net ) == -1 ){ |
||||||
|
connect_login_down(&ami->net, &ami->asterisk); |
||||||
|
return -1; |
||||||
|
} |
||||||
|
|
||||||
|
login_up(&ami->asterisk); |
||||||
|
|
||||||
|
return 0; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Fecha o socket que está conectado com a ami |
||||||
|
* |
||||||
|
*/ |
||||||
|
int sock_close(int sock){ |
||||||
|
|
||||||
|
if(close(sock) == -1){ |
||||||
|
if(errno == EINTR){ |
||||||
|
close(sock); |
||||||
|
return 0; |
||||||
|
} |
||||||
|
|
||||||
|
return -1; |
||||||
|
} |
||||||
|
|
||||||
|
return 0; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Verifica a resposta do login, se retornar 0 o usuário está logado |
||||||
|
* |
||||||
|
* \return sucesso 0, falha -1 |
||||||
|
*/ |
||||||
|
int done_login( NET *net ){ |
||||||
|
|
||||||
|
int len_message_login = 512; |
||||||
|
char result_login[len_message_login]; |
||||||
|
char login_success[56] = "Response: Success\r\nMessage: Authentication accepted\r\n"; |
||||||
|
int bytes = 0; |
||||||
|
int attempt_wait_login = 0; |
||||||
|
|
||||||
|
while( 1 ){ |
||||||
|
struct pollfd pfd[1]; |
||||||
|
pfd[0].fd = net->sock; |
||||||
|
pfd[0].events = POLLIN; |
||||||
|
|
||||||
|
if(poll(pfd, 1, 10) == -1){ |
||||||
|
return -1; |
||||||
|
} |
||||||
|
|
||||||
|
if(pfd[0].revents & POLLHUP) { |
||||||
|
return -1; |
||||||
|
} |
||||||
|
|
||||||
|
if(pfd[0].revents & POLLERR) { |
||||||
|
return -1; |
||||||
|
} |
||||||
|
|
||||||
|
else if(pfd[0].revents & POLLIN) { |
||||||
|
|
||||||
|
bytes = recv(net->sock, result_login, len_message_login - 1, 0); |
||||||
|
result_login[bytes] = '\0'; |
||||||
|
|
||||||
|
if(!strstr(result_login, "Response")){ |
||||||
|
continue; |
||||||
|
} |
||||||
|
|
||||||
|
if(strstr(result_login, login_success) != NULL){ |
||||||
|
break; |
||||||
|
} |
||||||
|
else { /* login fail */ |
||||||
|
return -1; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
attempt_wait_login++; |
||||||
|
if(attempt_wait_login == 100){ |
||||||
|
return -1; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
return 0; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Connectar a ami e retorna já está conectado |
||||||
|
* |
||||||
|
* \return sucesso 0, falha -1 |
||||||
|
*/ |
||||||
|
int connect_ami(NET *net){ |
||||||
|
|
||||||
|
while(1){ |
||||||
|
|
||||||
|
if (connect(net->sock, (struct sockaddr *)&net->sock_addr, sizeof(struct sockaddr_in) ) == -1){ |
||||||
|
sleep(1); |
||||||
|
continue; |
||||||
|
} |
||||||
|
|
||||||
|
connect_up(net); |
||||||
|
break; |
||||||
|
} |
||||||
|
|
||||||
|
return 0; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Cria um sockect e defini opções desse conexão |
||||||
|
* \return sucesso 0 |
||||||
|
*/ |
||||||
|
static int create_socket(NET *net){ |
||||||
|
|
||||||
|
bzero(&net->sock_addr, sizeof(net->sock_addr)); |
||||||
|
|
||||||
|
net->sock_addr.sin_family = AF_INET; |
||||||
|
net->sock_addr.sin_port = htons(net->port); |
||||||
|
net->sock_addr.sin_addr.s_addr = net->address; |
||||||
|
|
||||||
|
net->sock = socket(net->sock_addr.sin_family, SOCK_STREAM, 0); |
||||||
|
|
||||||
|
fcntl(net->sock, F_SETFL, O_NONBLOCK); |
||||||
|
|
||||||
|
return 0; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Começa receber dados do ami, essa função é depois que connect_ami e dispatch_login |
||||||
|
* Direciona os dados que chegam da ami para determinados ramos |
||||||
|
* \return void |
||||||
|
*/ |
||||||
|
int communication_ami(AMI *ami){ |
||||||
|
|
||||||
|
int bytes = 0; |
||||||
|
char more_buffer[MAX_BUFFER_NET + MAX_BUFFER_NET]; |
||||||
|
|
||||||
|
while(1){ |
||||||
|
struct pollfd pfd[1]; |
||||||
|
pfd[0].fd = ami->net.sock; |
||||||
|
pfd[0].events = POLLIN; |
||||||
|
|
||||||
|
if(poll(pfd, 1, 10) == -1){ |
||||||
|
if(errno == EINTR){ |
||||||
|
continue; |
||||||
|
} |
||||||
|
return -1; |
||||||
|
} |
||||||
|
|
||||||
|
if(pfd[0].revents & POLLHUP) { |
||||||
|
return -1; |
||||||
|
} |
||||||
|
|
||||||
|
if(pfd[0].revents & POLLERR) { |
||||||
|
return -1; |
||||||
|
} |
||||||
|
|
||||||
|
if(ami->asterisk.init_action == 0){ |
||||||
|
if(init_methods(ami) == -1){ |
||||||
|
connect_login_down(&ami->net, &ami->asterisk); |
||||||
|
break; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
else if(pfd[0].revents & POLLIN) { |
||||||
|
char *buffer = NULL; |
||||||
|
char *block = NULL; |
||||||
|
|
||||||
|
if(ami->net.imcomplete_net == 0){ |
||||||
|
bytes = recv(ami->net.sock, ami->net.buffer_net, MAX_BUFFER_NET - 1, MSG_DONTWAIT); |
||||||
|
ami->net.buffer_net[bytes] = '\0'; |
||||||
|
if(bytes == (MAX_BUFFER_NET - 2)){ |
||||||
|
ami->net.imcomplete_net = 1; |
||||||
|
continue; |
||||||
|
} |
||||||
|
buffer = ami->net.buffer_net; |
||||||
|
} |
||||||
|
else{ |
||||||
|
strcpy(more_buffer, ami->net.buffer_net); |
||||||
|
bytes = recv(ami->net.sock, (more_buffer + (MAX_BUFFER_NET - 1)), MAX_BUFFER_NET - 1, MSG_DONTWAIT); |
||||||
|
more_buffer[bytes] = '\0'; |
||||||
|
ami->net.imcomplete_net = 0; |
||||||
|
buffer = more_buffer; |
||||||
|
} |
||||||
|
|
||||||
|
block = define_block(buffer, &buffer); |
||||||
|
while(block){ |
||||||
|
if(!strncmp(block, "Response: ", 10)){ |
||||||
|
parse_response(ami, block); |
||||||
|
} |
||||||
|
else if(!strncmp(block, "Event: ", 7)){ |
||||||
|
parse_event(ami, block); |
||||||
|
} |
||||||
|
|
||||||
|
block = define_block(NULL, &buffer); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
return 0; |
||||||
|
} |
||||||
|
|
@ -0,0 +1,134 @@ |
|||||||
|
/*!
|
||||||
|
* |
||||||
|
* |
||||||
|
*/ |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* O módulo net começa ser usada. Essa função fará thread para começar a conexão. |
||||||
|
* \param ami identifica qual instância da conexão |
||||||
|
* \return sucesso 0 |
||||||
|
*/ |
||||||
|
int net_start(AMI *ami); |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Começará a conexão com a ami de acordo com os parâmetro passado |
||||||
|
* \param void_ami identifica qual instância da conexão em tipo void * |
||||||
|
* \return void * |
||||||
|
*/ |
||||||
|
void *net(void *void_ami); |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Retira o login e a conexão definida da estrutura.\n |
||||||
|
* Reset conexão e login |
||||||
|
*/ |
||||||
|
void connect_login_down(NET *net, ASTERISK *asterisk); |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Derruba a conexão com o ami |
||||||
|
* \param net estrutura de informações de rede da biblioteca |
||||||
|
*/ |
||||||
|
void connect_down(NET *net); |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Levanta a conexão, isto é, define na estrutura que a conexão está conectada. |
||||||
|
* \param net l |
||||||
|
* \return |
||||||
|
*/ |
||||||
|
void connect_up(NET *net); |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Define na estrutura que não está logado |
||||||
|
* \param asterisk estrutura sobre o asterisk a ami do outro lado |
||||||
|
* \return void |
||||||
|
*/ |
||||||
|
void login_down(ASTERISK *asterisk); |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Define na estrutura que está logado |
||||||
|
* |
||||||
|
*/ |
||||||
|
void login_up(ASTERISK *asterisk); |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Envia uma action para asterisk. send_action é função externa. dispatch_action é uma função interna |
||||||
|
* \param ami estrutura de instância da biblioteca |
||||||
|
* \param action action que será enviado |
||||||
|
* \return sucesso 1, falha -1 |
||||||
|
*/ |
||||||
|
int dispatch_action(AMI *ami, const char *action); |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* envia a action para login ami |
||||||
|
* \return sucesso 0, falha -1 |
||||||
|
*/ |
||||||
|
int dispatch_login(AMI *ami); |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Fecha o socket que está conectado com a ami |
||||||
|
* |
||||||
|
*/ |
||||||
|
int sock_close(int sock); |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Verifica a resposta do login, se retornar 0 o usuário está logado |
||||||
|
* |
||||||
|
* \return sucesso 0, falha -1 |
||||||
|
*/ |
||||||
|
int done_login( NET *net ); |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Connectar a ami e retorna já está conectado |
||||||
|
* |
||||||
|
* \return sucesso 0, falha -1 |
||||||
|
*/ |
||||||
|
int connect_ami(NET *net); |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Começa receber dados do ami, essa função é depois que connect_ami e dispatch_login |
||||||
|
* Direciona os dados que chegam da ami para determinados ramos |
||||||
|
* \return void |
||||||
|
*/ |
||||||
|
int communication_ami(AMI *ami); |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -0,0 +1,84 @@ |
|||||||
|
#include <ami.h> |
||||||
|
#include <string.h> |
||||||
|
|
||||||
|
/*!
|
||||||
|
* Cuida das respostas que chegam da AMi das actions enviadas |
||||||
|
* \param ami estrutura da AMI, a principal estrutura da AMI |
||||||
|
* \param buffer
|
||||||
|
* \return void |
||||||
|
*/ |
||||||
|
void parse_response(AMI *ami, const char *buffer){ |
||||||
|
|
||||||
|
char *end_response = "\r\n\r"; |
||||||
|
char *p_end = NULL; |
||||||
|
RESPONSE *p_response = NULL; |
||||||
|
ACTION *p_action = NULL; |
||||||
|
size_t len_command = 0; |
||||||
|
|
||||||
|
p_end = strstr(buffer, end_response); |
||||||
|
if( !p_end ){ |
||||||
|
return ; |
||||||
|
} |
||||||
|
|
||||||
|
p_action = action_create(); |
||||||
|
p_response = response_create(); |
||||||
|
p_response = p_response + 10; |
||||||
|
|
||||||
|
size_t len = len_action_ami(buffer); |
||||||
|
p_response->response = calloc(1, len + 1); |
||||||
|
strncpy(p_response->response, buffer, len); |
||||||
|
p_response->response[len] = '\0'; |
||||||
|
buffer = buffer + len + 2; |
||||||
|
|
||||||
|
action_response_add(p_action, p_response); |
||||||
|
|
||||||
|
while(buffer < p_end){ |
||||||
|
ARGS *arg = arg_create(); |
||||||
|
|
||||||
|
len = len_key_ami( buffer ); |
||||||
|
arg->key = calloc(1, len + 1); |
||||||
|
strncpy(arg->key, buffer, len); |
||||||
|
buffer = buffer + 2; |
||||||
|
|
||||||
|
//command
|
||||||
|
if(!strcmp(arg->key, "Output")){ |
||||||
|
size_t len = strlen(buffer); |
||||||
|
arg->value = calloc(1, len + 1); |
||||||
|
strcpy(arg->value, buffer); |
||||||
|
arg->value[len] = '\0'; |
||||||
|
break; |
||||||
|
} |
||||||
|
|
||||||
|
len = len_value_ami(buffer, 0); |
||||||
|
arg->value = calloc(1, len); |
||||||
|
strncpy(arg->value, buffer, len); |
||||||
|
buffer = buffer + 2; |
||||||
|
|
||||||
|
args_add(&p_response->args, arg); |
||||||
|
|
||||||
|
len_command = len_command_old_ami(buffer); |
||||||
|
//action comando antigo
|
||||||
|
if( len_command && !strcmp(arg->key, "Privilege") && !strcmp(arg->value, "Command") ){ |
||||||
|
ARGS *arg = arg_create(); |
||||||
|
arg->key = calloc(1, sizeof(7));
|
||||||
|
strcpy(arg->key, "Output"); |
||||||
|
arg->key[6] = '\0'; |
||||||
|
|
||||||
|
arg->value = calloc(1, len_command + 1 ); |
||||||
|
strncpy(arg->value, buffer, len_command); |
||||||
|
arg->value[len_command] = '\0'; |
||||||
|
break; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
return; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
int verify_response(AMI *ami, char *buffer){ |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
return 0; |
||||||
|
} |
||||||
|
|
@ -0,0 +1,15 @@ |
|||||||
|
|
||||||
|
#ifndef PARSE_ACTION_H |
||||||
|
#define PARSE_ACTION_H 1 |
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Tratará das respostas das actions |
||||||
|
* \param substring inicio da resposta |
||||||
|
*
|
||||||
|
*/ |
||||||
|
void parse_response(AMI *ami, const char *buffer); |
||||||
|
|
||||||
|
|
||||||
|
#endif |
||||||
|
|
@ -0,0 +1,52 @@ |
|||||||
|
#include <ami.h> |
||||||
|
#include <string.h> |
||||||
|
|
||||||
|
/*!
|
||||||
|
* Colocar cada evento dentro da estrutura Event. |
||||||
|
* |
||||||
|
* \param substring |
||||||
|
* \param ami |
||||||
|
* \return diferente de NULL significa que o evento será completado na proxima revc |
||||||
|
*/ |
||||||
|
void parse_event(AMI *ami, char *buffer){ |
||||||
|
char *end_event = "\r\n\r"; |
||||||
|
char *p_end = NULL; |
||||||
|
EVENT *p_event = NULL; |
||||||
|
|
||||||
|
p_end = strstr(buffer, end_event); |
||||||
|
if( !p_end ){ |
||||||
|
return; |
||||||
|
} |
||||||
|
|
||||||
|
p_event = event_create(); |
||||||
|
|
||||||
|
buffer = buffer + 8; |
||||||
|
size_t len = len_action_ami(buffer); |
||||||
|
p_event->event = calloc(1, sizeof(len)); |
||||||
|
strncpy(p_event->event, buffer, len); |
||||||
|
p_event->event[len] = '\0'; |
||||||
|
buffer = buffer + len + 2; |
||||||
|
|
||||||
|
while(buffer < p_end){ |
||||||
|
ARGS *arg = arg_create(); |
||||||
|
|
||||||
|
len = len_key_ami( buffer ); |
||||||
|
arg->key = calloc(1, len + 1); |
||||||
|
strncpy(arg->key, buffer, len); |
||||||
|
arg->key[len] = '\0'; |
||||||
|
buffer = buffer + 2; |
||||||
|
|
||||||
|
len = len_value_ami(buffer, TYPE_EVENT); |
||||||
|
arg->value = calloc(1, len); |
||||||
|
strncpy(arg->value, buffer, len); |
||||||
|
buffer = buffer + 2; |
||||||
|
|
||||||
|
args_add(&p_event->args, arg); |
||||||
|
} |
||||||
|
|
||||||
|
event_add(&ami->events, p_event); |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
|
@ -0,0 +1,15 @@ |
|||||||
|
|
||||||
|
#ifndef PARSE_EVENT_H |
||||||
|
#define PARSE_EVENT_H 1 |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Colocar cada evento dentro da estrutura Event. |
||||||
|
* \param substring |
||||||
|
* \param ami |
||||||
|
* \return diferente de NULL significa que o evento será completado na proxima revc |
||||||
|
*/ |
||||||
|
void parse_event(AMI *ami, char *buffer); |
||||||
|
|
||||||
|
#endif |
@ -0,0 +1,200 @@ |
|||||||
|
#include <ami.h> |
||||||
|
|
||||||
|
#include <string.h> |
||||||
|
#include <stdio.h> |
||||||
|
|
||||||
|
#define END_AND_EVENT "\r\n\r\nEvent: " |
||||||
|
#define END_AND_RESPONSE "\r\n\r\nResponse: " |
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Constrói o msg de login de acordo com as credenciais informadas pelo usuários |
||||||
|
* |
||||||
|
* \return action para ser enviado ao login, para dar free use a função free_str_login |
||||||
|
*/ |
||||||
|
const char *build_str_login(CREDENTIAL *credential) { |
||||||
|
|
||||||
|
char *str_login = NULL; |
||||||
|
|
||||||
|
str_login = calloc(1, strlen("action: Login\r\nusername: %s\r\nsecret: %s\r\n\r\n") + strlen(credential->username) + strlen(credential->password) + 2); |
||||||
|
sprintf(str_login, "action: Login\r\nusername: %s\r\nsecret: %s\r\n\r\n", credential->username, credential->password); |
||||||
|
|
||||||
|
return str_login; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* libera ponteiro que está o action do login |
||||||
|
* \param str_login action em texto |
||||||
|
*/ |
||||||
|
void free_str_login(char *str_login){ |
||||||
|
free(str_login); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Constrói texto da action de acordo com parâmetros que foi criado pelo create_new_action e preenchido pelo usuário |
||||||
|
* \param action estrutura criada pelo create_new_action |
||||||
|
* \return string da action, essa action deve ser chamada free_str_action para liberar |
||||||
|
*/ |
||||||
|
const char *build_str_action(struct ss_action *action){ |
||||||
|
|
||||||
|
int len_total = (MAX_LEN_NAME_ACTION + 10) + ( action->count_args * (MAX_LEN_KEY_ACTION + MAX_LEN_VALUE_ACTION + 6)); |
||||||
|
char *str_action = calloc(1, len_total + 1); |
||||||
|
|
||||||
|
snprintf(str_action, len_total, "action:%s\r\n", action->name_action); |
||||||
|
|
||||||
|
int i; |
||||||
|
for( i = 0; i < action->count_args; i++ ) { |
||||||
|
strcat(str_action, action->args[i].key); |
||||||
|
strcat(str_action, action->args[i].value); |
||||||
|
strcat(str_action, "\r\n"); |
||||||
|
} |
||||||
|
|
||||||
|
strcat(str_action, "\r\n"); |
||||||
|
|
||||||
|
return str_action; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Será usado para liberar action criada pelo create_new_action |
||||||
|
* \param str_action liberar ponteiro que está o texto action |
||||||
|
*/ |
||||||
|
void str_action_free(char *str_action){ |
||||||
|
free(str_action); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Comprimento do nome da action que vem da ami |
||||||
|
* \param str texto da AMI |
||||||
|
* \return retorna o comprimento da AMI ou 0 se encontrar byte \0 |
||||||
|
*/ |
||||||
|
size_t len_action_ami(const char *str){ |
||||||
|
|
||||||
|
size_t len_action = 0; |
||||||
|
|
||||||
|
do{ |
||||||
|
len_action++; |
||||||
|
if(*str == '\0'){ |
||||||
|
return 0; |
||||||
|
} |
||||||
|
}while (*(++str) != '\r'); |
||||||
|
|
||||||
|
return len_action; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* tamanho da chave que vem no texto da AMI |
||||||
|
* \param str texto da AMI |
||||||
|
* \return comprimento da ami ou 0 se encontrar byte nulo |
||||||
|
*/ |
||||||
|
size_t len_key_ami(const char *str){ |
||||||
|
|
||||||
|
size_t len_action = 0; |
||||||
|
|
||||||
|
do{ |
||||||
|
len_action++; |
||||||
|
if(*str == '\0'){ |
||||||
|
return 0; |
||||||
|
} |
||||||
|
}while (*(++str) != ':'); |
||||||
|
|
||||||
|
return len_action; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Comprimento do valor da chave
|
||||||
|
* \param str texto do evento da ami |
||||||
|
* \return comprimento do valor ou 0 se encontrar byte nulo \0 |
||||||
|
*/ |
||||||
|
size_t len_value_ami( const char *str, int type ){ |
||||||
|
|
||||||
|
size_t len_action = 0; |
||||||
|
|
||||||
|
do{ |
||||||
|
len_action++; |
||||||
|
if(*str == '\0'){ |
||||||
|
return 0; |
||||||
|
} |
||||||
|
}while (*(++str) != '\r'); |
||||||
|
|
||||||
|
return len_action; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Cada bloco é colocado um \0 no final. O final do bloco tem \\r\\n\\r\\n -> \\r\\n\\r\\0 |
||||||
|
* O parâmetro str será incluído uma data para buscar blocos, os próximos blocos parâmetro deve ser NULL. O parâmetro saveptr |
||||||
|
* deve ser usado para achar os próximos blocos.\n |
||||||
|
* |
||||||
|
* primeiro bloco:\n |
||||||
|
* point = define_block(str, &point_block); |
||||||
|
* outros blocos:\n |
||||||
|
* point = define_block(NULL, &point_block); |
||||||
|
* |
||||||
|
* \param str
|
||||||
|
* \param saveptr |
||||||
|
* \return sucesso bloco de dados ou NULL não tem mais blocos definidos |
||||||
|
*/ |
||||||
|
char *define_block(char *str, char **saveptr){ |
||||||
|
|
||||||
|
char *point_response, *point_event; |
||||||
|
|
||||||
|
if(!(*saveptr)){ |
||||||
|
return NULL; |
||||||
|
} |
||||||
|
|
||||||
|
if(str == NULL){ |
||||||
|
str = *saveptr; |
||||||
|
} |
||||||
|
|
||||||
|
point_event = strstr(str, END_AND_EVENT); |
||||||
|
point_response = strstr(str, END_AND_RESPONSE); |
||||||
|
|
||||||
|
if( (point_response < point_event && point_response) || (point_response && !point_event) ){ |
||||||
|
point_response = point_response + 3; |
||||||
|
*point_response = '\0'; |
||||||
|
point_response++; |
||||||
|
*saveptr = point_response; |
||||||
|
}
|
||||||
|
else if( (point_event < point_response && point_event) || (!point_response && point_event) ){ |
||||||
|
point_event = point_event + 3; |
||||||
|
*point_event = '\0'; |
||||||
|
point_event++; |
||||||
|
*saveptr = point_event; |
||||||
|
} |
||||||
|
else{ |
||||||
|
*saveptr = NULL; |
||||||
|
} |
||||||
|
|
||||||
|
return str; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/* Verifica se existe a string "--END COMMAND--\r\n\r" esse trecho é usado no asterisk 13 e anterior
|
||||||
|
* Caso estiver esse texto, retornará quando caracteres até ele |
||||||
|
* \param command cadeia que verificará se existe a frase |
||||||
|
* \return len quantidade de carcteres até a frase, falha 0 significa que a string não existe |
||||||
|
*/ |
||||||
|
size_t len_command_old_ami(const char *command){ |
||||||
|
|
||||||
|
char *end_command = NULL; |
||||||
|
size_t len = 0; |
||||||
|
char *str_end_command = "--END COMMAND--\r\n\r"; |
||||||
|
|
||||||
|
end_command = strstr(command, str_end_command); |
||||||
|
if(!end_command){ |
||||||
|
return 0; |
||||||
|
} |
||||||
|
|
||||||
|
while(command != end_command){ |
||||||
|
len++; |
||||||
|
} |
||||||
|
|
||||||
|
return len; |
||||||
|
} |
||||||
|
|
@ -0,0 +1,88 @@ |
|||||||
|
|
||||||
|
#ifndef PARSE_STRING_H |
||||||
|
#define PARSE_STRING_H 1 |
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Constrói o msg de login de acordo com as credenciais informadas pelo usuários |
||||||
|
* |
||||||
|
* \return action para ser enviado ao login, para dar free use a função free_str_login |
||||||
|
*/ |
||||||
|
const char *build_str_login(CREDENTIAL *credential); |
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* libera ponteiro que está o action do login |
||||||
|
* \param str_login action em texto |
||||||
|
*/ |
||||||
|
void free_str_login(char *str_login); |
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Constrói texto da action de acordo com parâmetros que foi criado pelo create_new_action e preenchido pelo usuário |
||||||
|
* \param action estrutura criada pelo create_new_action |
||||||
|
* \return string da action, essa action deve ser chamada free_str_action para liberar |
||||||
|
*/ |
||||||
|
const char *build_str_action(struct ss_action *action); |
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Será usado para liberar action criada pelo create_new_action |
||||||
|
* /param str_action liberar ponteiro que está o texto action |
||||||
|
*/ |
||||||
|
void free_str_action(char *str_action); |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Comprimento do nome da action que vem da ami |
||||||
|
* \param str texto da AMI |
||||||
|
* \return retorna o comprimento da AMI ou 0 se encontrar byte \0 |
||||||
|
*/ |
||||||
|
size_t len_action_ami(const char *str); |
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* tamanho da chave que vem no texto da AMI |
||||||
|
* \param str texto da AMI |
||||||
|
* \return comprimento da ami ou 0 se encontrar byte nulo |
||||||
|
*/ |
||||||
|
size_t len_key_ami(const char *str); |
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Comprimento do valor da chave
|
||||||
|
* \param str texto do evento da ami |
||||||
|
* \param type |
||||||
|
* \return comprimento do valor ou 0 se encontrar byte nulo \0 |
||||||
|
*/ |
||||||
|
size_t len_value_ami( const char *str, int type ); |
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* define o bloco dos dados da AMI colocando um \\0 no último \\n |
||||||
|
* Essa função é similar ao strtok_r |
||||||
|
* \param str começo do dados da AMI |
||||||
|
* \param saveptr esse ponteiro será preenchido para o próxima chamada |
||||||
|
* \return sucesso dados não null, falha NULL não tem blocos definidos |
||||||
|
*/ |
||||||
|
char *define_block(char *str, char **saveptr); |
||||||
|
|
||||||
|
|
||||||
|
/* Verifica se existe a string "--END COMMAND--\r\n\r" esse trecho é usado no asterisk 13 e anterior
|
||||||
|
* Caso estiver esse texto, retornará quando caracteres até ele |
||||||
|
* \param command cadeia que verificará se existe a frase |
||||||
|
* \return len quantidade de carcteres até a frase, falha 0 significa que a string não existe |
||||||
|
*/ |
||||||
|
size_t len_command_old_ami(const char *command); |
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Será usado para liberar action criada pelo create_new_action |
||||||
|
* /param str_action liberar ponteiro que está o texto action |
||||||
|
*/ |
||||||
|
void str_action_free(char *str_action); |
||||||
|
|
||||||
|
|
||||||
|
#endif |
||||||
|
|
Loading…
Reference in new issue