123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502 |
- /*
- * Copyright (C) 2009 Mamadou Diop.
- *
- * Contact: Mamadou Diop <diopmamadou(at)doubango.org>
- *
- * This file is part of Open Source Doubango Framework.
- *
- * DOUBANGO 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 3 of the License, or
- * (at your option) any later version.
- *
- * DOUBANGO 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 DOUBANGO.
- *
- */
- #include "main.h"
- #include "common.h"
- #include "invite.h"
- #include "message.h"
- #include "options.h"
- #include "publish.h"
- #include "register.h"
- #include "subscribe.h"
- #include "tinydav.h" /* Doubango Audio/Video Framework */
- #include <stdio.h>
- #include <string.h>
- #include <ctype.h>
- #define LINE_DELIM "\n \r\n"
- /* === global variables === */
- ctx_t* ctx = tsk_null;
- const char* trim(const char*);
- int insert(char* dest, tsk_size_t index, tsk_size_t dest_size, char* src, tsk_size_t src_size);
- int update_param(const char* , const char* );
- int execute(const cmd_t* );
- /* === entry point === */
- int main(int argc, char** argv)
- {
- char cmdbuf[4096];
- tsk_buffer_t* buffer = tsk_null;
- cmd_t* cmd = tsk_null;
- tsk_bool_t comment = tsk_false;
- int ret;
- int i, index;
- const char* start = tsk_null, *end = tsk_null;
- int a = 32 | 1 | 2;
- /* Copyright */
- printf("Doubango Project (tinyDEMO)\nCopyright (C) 2009 - 2013 Mamadou Diop \n\n");
- /* Initialize Network Layer ==> Mandatory */
- tnet_startup();
- /* Initialize Doubango Audio/Video Framework ==> will register all plugins(codecs and sessions)
- * Not mandatory if you have your own plugins*/
- tdav_init();
- /* Print Usage */
- //cmd_print_help();
- /* create user's ctx */
- if(!(ctx = ctx_create()) || !ctx->stack) {
- TSK_DEBUG_ERROR("Failed to create user's ctx.");
- goto bail;
- }
- /* create new buffer */
- if(!(buffer = tsk_buffer_create_null())) {
- TSK_DEBUG_ERROR("Failed to create new buffer.");
- goto bail;
- }
- /* initial args */
- for(i=1 /* index zero contains the exe path */, index=0; i<argc && argv[i]; i++) {
- if(index) {
- tsk_buffer_append(buffer, " ", 1);
- }
- tsk_buffer_append(buffer, argv[i], tsk_strlen(argv[i]));
- }
- /* If initial args ==> parse it now */
- if(buffer->size) {
- TSK_DEBUG_INFO("Initial command-line: %s", buffer->data);
- goto init_buffer;
- }
- /* always use fgets() instead of gets. gets() is considered to be unsafe.(Android and Mac OS X will warn) */
- while(fgets(cmdbuf, sizeof(cmdbuf), stdin)) {
- TSK_DEBUG_INFO("Command-Line: %s", cmdbuf);
- tsk_buffer_cleanup(buffer); /* cannot read from console while executing scenario */
- tsk_buffer_append(buffer, cmdbuf, tsk_strlen(cmdbuf));
- init_buffer:
- start = buffer->data;
- //start = trim(start);
- end = start + buffer->size;
- if(start >= end) {
- TSK_DEBUG_INFO("Empty buffer");
- continue;
- }
- parse_buffer:
- TSK_OBJECT_SAFE_FREE(cmd); /* Free old value */
- cmd = cmd_parse(start, (end-start), &comment, ctx->params);
- if(cmd) {
- if(comment || cmd->type == cmd_none) {
- goto nex_line;
- }
- }
- else {
- continue;
- }
- /* Load from scenario file? */
- if(cmd->type == cmd_scenario) {
- FILE* file;
- const opt_t* opt;
- tsk_size_t read = 0;
- tsk_bool_t rm_lf = tsk_false;
- if((opt = opt_get_by_type(cmd->opts, opt_path)) && !tsk_strnullORempty(opt->value)) { /* --path option */
- if((file = fopen(opt->value, "r"))) {
- memset(cmdbuf, '\0', sizeof(cmdbuf)), cmdbuf[0] = '\n';
- read = fread(cmdbuf+1, sizeof(uint8_t), sizeof(cmdbuf)-1, file);
- fclose(file), file = tsk_null;
- if(read == 0) {
- TSK_DEBUG_ERROR("[%s] is empty.", opt->value);
- goto nex_line;
- }
- else if(read == sizeof(cmdbuf)-1) {
- TSK_DEBUG_ERROR("Buffer too short.");
- goto nex_line;
- }
- read++; /* \n */
- /* repplace all '\' with spaces (easier than handling that in the ragel file) */
- for(i=0; ((tsk_size_t)i)<read; i++) {
- if(cmdbuf[i] == '\\') {
- cmdbuf[i] = ' ';
- rm_lf = tsk_true;
- }
- else if(rm_lf && cmdbuf[i] == '\n') {
- cmdbuf[i] = ' ';
- rm_lf = tsk_false;
- }
- }
- cmdbuf[read] = '\n';
- /* insert embedded scenario */
- if((index = tsk_strindexOf(start, (end-start), "\n")) == -1) { /* ++sn line */
- index = buffer->size;
- }
- else {
- index += (start - ((const char*)buffer->data));
- }
- if(tsk_buffer_insert(buffer, index, cmdbuf, read)) {
- continue;
- }
- else {
- start = ((const char*)buffer->data) + index; // because insert use realloc()
- end = (((const char*)buffer->data) + buffer->size);
- goto nex_line;
- }
- }
- else {
- TSK_DEBUG_ERROR("Failed to open scenario-file [%s].", opt->value);
- goto nex_line;
- }
- continue;
- }
- else {
- TSK_DEBUG_ERROR("++scenario command must have --path option.");
- continue;
- }
- }
- /* execute current command */
- switch(cmd->type) {
- case cmd_exit:
- TSK_DEBUG_INFO("Exit/Quit");
- goto bail;
- default:
- ret = execute(cmd);
- break;
- }
- /* next line */
- nex_line:
- if((index = tsk_strindexOf(start, (end - start), "\n")) !=-1) {
- start += index;
- while((start < end) && isspace(*start)) {
- start ++;
- }
- if((start + 2/*++*/) < end) {
- goto parse_buffer; /* next line */
- }
- else {
- continue; /* wait for new commands */
- }
- }
- } /* while(buffer) */
- bail:
- /* Free current command */
- TSK_OBJECT_SAFE_FREE(cmd);
- /* Free buffer */
- TSK_OBJECT_SAFE_FREE(buffer);
- /* Destroy the user's ctx */
- TSK_OBJECT_SAFE_FREE(ctx);
- /* Deinitialize Doubango Audio/Video Framework ==> will unregister all plugins(codecs and sessions)
- * Not mandatory */
- tdav_init();
- /* Uninitilize Network Layer */
- tnet_cleanup();
- #if ANDROID
- exit(0);
- #endif
- return 0;
- }
- const char* trim(const char* str)
- {
- while(isspace(*str)) {
- str++;
- }
- return str;
- }
- int update_param(const char* pname, const char* pvalue)
- {
- if(ctx->params && pname) {
- const tsk_param_t* param;
- if((param = tsk_params_get_param_by_name(ctx->params, pname))) {
- tsk_strupdate(&TSK_PARAM(param)->value, pvalue);
- return 0;
- }
- else {
- TSK_DEBUG_INFO("[%s] parameter does not exist", pname);
- }
- }
- else {
- TSK_DEBUG_ERROR("Invalid parameter");
- }
- return -1;
- }
- int execute(const cmd_t* cmd)
- {
- int ret = 0;
- tsip_ssession_id_t sid;
- tsk_istr_t istr;
- if(!cmd) {
- TSK_DEBUG_ERROR("Invalid parameter");
- return -1;
- }
- tsk_safeobj_lock(ctx);
- switch(cmd->type) {
- case cmd_audio:
- case cmd_audiovideo: {
- TSK_DEBUG_INFO("command=audio/video");
- if((sid = invite_handle_cmd(cmd->type, cmd->opts)) != TSIP_SSESSION_INVALID_ID) {
- if(cmd->sidparam) {
- tsk_itoa(sid, &istr);
- update_param(cmd->sidparam, istr);
- }
- }
- break;
- }
- case cmd_config_session: {
- TSK_DEBUG_INFO("command=config-session");
- break;
- }
- case cmd_config_stack: {
- TSK_DEBUG_INFO("command=config-satck");
- ret = stack_config(cmd->opts);
- break;
- }
- case cmd_dtmf: {
- const opt_t* opt;
- TSK_DEBUG_INFO("command=dtmf");
- if(!(opt = opt_get_by_type(cmd->opts, opt_sid)) || tsk_strnullORempty(opt->value)) { /* --sid option */
- TSK_DEBUG_ERROR("++dtmf command need --sid option");
- break;
- }
- if(!(opt = opt_get_by_type(cmd->opts, opt_event)) || tsk_strnullORempty(opt->value)) { /* --event option */
- TSK_DEBUG_ERROR("++dtmf command need --event option");
- break;
- }
- invite_handle_cmd(cmd->type, cmd->opts);
- break;
- }
- case cmd_dump: {
- TSK_DEBUG_INFO("command=dump");
- ret = stack_dump();
- break;
- }
- case cmd_ect: {
- const opt_t* opt;
- TSK_DEBUG_INFO("command=ect");
- if((opt = opt_get_by_type(cmd->opts, opt_sid)) && !tsk_strnullORempty(opt->value)) {
- TSK_DEBUG_ERROR("++ect command need --sid option");
- ret = -1;
- break;
- }
- if((opt = opt_get_by_type(cmd->opts, opt_to)) && !tsk_strnullORempty(opt->value)) {
- TSK_DEBUG_ERROR("++ect command need --to option");
- ret = -1;
- break;
- }
- invite_handle_cmd(cmd->type, cmd->opts);
- break;
- }
- case cmd_exit: {
- TSK_DEBUG_INFO("command=exit");
- goto bail;
- break;
- }
- case cmd_file: {
- const opt_t* opt;
- TSK_DEBUG_INFO("command=file");
- if(!(opt = opt_get_by_type(cmd->opts, opt_path)) || tsk_strnullORempty(opt->value)) {
- TSK_DEBUG_ERROR("++file command need --path option");
- break;
- }
- if((sid = invite_handle_cmd(cmd->type, cmd->opts)) != TSIP_SSESSION_INVALID_ID) {
- if(cmd->sidparam) {
- tsk_itoa(sid, &istr);
- update_param(cmd->sidparam, istr);
- }
- }
- break;
- }
- case cmd_hangup: {
- const opt_t* opt;
- TSK_DEBUG_INFO("command=hangup");
- if((opt = opt_get_by_type(cmd->opts, opt_sid)) && !tsk_strnullORempty(opt->value)) { /* --sid option */
- ret = session_hangup(tsk_atoll(opt->value));
- }
- else {
- TSK_DEBUG_ERROR("++hangup command need --sid option");
- ret = -1;
- }
- break;
- }
- case cmd_help: {
- TSK_DEBUG_INFO("command=help");
- cmd_print_help();
- break;
- }
- case cmd_hold: {
- const opt_t* opt;
- TSK_DEBUG_INFO("command=hold");
- if((opt = opt_get_by_type(cmd->opts, opt_sid)) && !tsk_strnullORempty(opt->value)) { /* --sid option */
- invite_handle_cmd(cmd->type, cmd->opts);
- }
- else {
- TSK_DEBUG_ERROR("++hold command need --sid option");
- ret = -1;
- }
- break;
- }
- case cmd_message: {
- TSK_DEBUG_INFO("command=message");
- if((sid = message_handle_cmd(cmd->type, cmd->opts)) != TSIP_SSESSION_INVALID_ID) {
- if(cmd->sidparam) {
- tsk_itoa(sid, &istr);
- update_param(cmd->sidparam, istr);
- }
- }
- break;
- }
- case cmd_options: {
- TSK_DEBUG_INFO("command=options");
- if((sid = options_handle_cmd(cmd->type, cmd->opts)) != TSIP_SSESSION_INVALID_ID) {
- if(cmd->sidparam) {
- tsk_itoa(sid, &istr);
- update_param(cmd->sidparam, istr);
- }
- }
- break;
- }
- case cmd_publish: {
- TSK_DEBUG_INFO("command=publish");
- if((sid = publish_handle_cmd(cmd->type, cmd->opts)) != TSIP_SSESSION_INVALID_ID) {
- if(cmd->sidparam) {
- tsk_itoa(sid, &istr);
- update_param(cmd->sidparam, istr);
- }
- }
- break;
- }
- case cmd_register: {
- TSK_DEBUG_INFO("command=register");
- if((sid = register_handle_cmd(cmd->type, cmd->opts)) != TSIP_SSESSION_INVALID_ID) {
- if(cmd->sidparam) {
- tsk_itoa(sid, &istr);
- update_param(cmd->sidparam, istr);
- }
- }
- break;
- }
- case cmd_resume: {
- const opt_t* opt;
- TSK_DEBUG_INFO("command=resume");
- if((opt = opt_get_by_type(cmd->opts, opt_sid)) && !tsk_strnullORempty(opt->value)) { /* --sid option */
- invite_handle_cmd(cmd->type, cmd->opts);
- }
- else {
- TSK_DEBUG_ERROR("++resume command need --sid option");
- ret = -1;
- }
- break;
- }
- case cmd_run: {
- TSK_DEBUG_INFO("command=run");
- ret = stack_run(cmd->opts);
- break;
- }
- case cmd_scenario: {
- TSK_DEBUG_INFO("command=scenario");
- break;
- }
- case cmd_sleep: {
- const opt_t* opt;
- double seconds;
- tsk_safeobj_unlock(ctx); /* beacuse of callback function */
- if((opt = opt_get_by_type(cmd->opts, opt_sec)) && !tsk_strnullORempty(opt->value)) { /* --sec option */
- seconds = strtod(opt->value, tsk_null); /* strtod() is better than atof() */
- if(seconds<=0) {
- printf("\n==== Press ENTER to continue...\n");
- getchar();
- }
- else {
- TSK_DEBUG_INFO("Sleeping %f seconds", seconds);
- tsk_thread_sleep((uint64_t)(seconds * 1000));
- }
- }
- else {
- TSK_DEBUG_WARN("++sleep need --sec option.");
- }
- return 0; /* bail: will unlock again */
- }
- case cmd_sms: {
- TSK_DEBUG_INFO("command=sms");
- if((sid = message_handle_cmd(cmd->type, cmd->opts)) != TSIP_SSESSION_INVALID_ID) {
- if(cmd->sidparam) {
- tsk_itoa(sid, &istr);
- update_param(cmd->sidparam, istr);
- }
- }
- break;
- }
- case cmd_stop: {
- TSK_DEBUG_INFO("command=stop");
- tsip_stack_stop(ctx->stack);
- break;
- }
- case cmd_subscribe: {
- TSK_DEBUG_INFO("command=subscribe");
- if((sid = subscribe_handle_cmd(cmd->type, cmd->opts)) != TSIP_SSESSION_INVALID_ID) {
- if(cmd->sidparam) {
- tsk_itoa(sid, &istr);
- update_param(cmd->sidparam, istr);
- }
- }
- break;
- }
- case cmd_video: {
- TSK_DEBUG_INFO("command=video");
- break;
- }
- default: {
- TSK_DEBUG_ERROR("%d not a valid command.", cmd);
- break;
- }
- }
- bail:
- tsk_safeobj_unlock(ctx);
- return ret;
- }
|