/** * @brief Hangup action entry point * * Hangup action will Hangup the first channel generated using * CALL action using the manager application Hangup. The hangup * events will still be parsed by @ref call_state function, unregistering * the pending filters * * @param sess Session rnuning this application * @param app The application structure * @param args Hangup action args "ActionID" * @return 0 if the call is found, -1 otherwise */ int hangup_exec(session_t *sess, app_t *app, const char *args) { struct app_call_info *info; char actionid[ACTIONID_LEN]; // This can only be done after authentication if (!session_test_flag(sess, SESS_FLAG_AUTHENTICATED)) { return NOT_AUTHENTICATED; } // Get Hangup parameteres if (sscanf(args, "%s", actionid) != 1) { return INVALID_ARGUMENTS; } // Try to find the action info of the given actionid if ((info = get_call_info_from_id(sess, actionid))) { if (!isaac_strlen_zero(info->ochannel)) { ami_message_t msg; memset(&msg, 0, sizeof(ami_message_t)); message_add_header(&msg, "Action: Hangup"); message_add_header(&msg, "Channel: %s", info->ochannel); manager_write_message(manager, &msg); session_write(sess, "HANGUPOK\r\n"); } else { session_write(sess, "HANGUPFAILED CHANNEL NOT FOUND\r\n"); } } else { session_write(sess, "HANGUPFAILED ID NOT FOUND\r\n"); return -1; } return 0; }
/** * @brief DTMF action entry point * * DTMF action will send a DTMF code to a second channel generated using * CALL action using the custom manager application PlayDTMF. * * @param sess Session rnuning this applicationthe custom manager application PlayDTMF. * @param app The application structure * @param args Dtmf action args "ActionID DTMFDigit" * @return 0 if the call is found, -1 otherwise */ int dtmf_exec(session_t *sess, app_t *app, const char *args) { struct app_call_info *info; char actionid[ACTIONID_LEN]; char digit[20]; // This can only be done after authentication if (!session_test_flag(sess, SESS_FLAG_AUTHENTICATED)) { return NOT_AUTHENTICATED; } // Get Hangup parameteres if (sscanf(args, "%s %s", actionid, digit) != 2) { return INVALID_ARGUMENTS; } // Try to find the action info of the given actionid if ((info = get_call_info_from_id(sess, actionid)) && !isaac_strlen_zero(info->dchannel)) { // Send the digit to remote channel using PlayDTMF manager action ami_message_t msg; memset(&msg, 0, sizeof(ami_message_t)); message_add_header(&msg, "Action: PlayDTMF"); message_add_header(&msg, "Channel: %s", info->dchannel); message_add_header(&msg, "Digit: %s", digit); manager_write_message(manager, &msg); usleep(300 * 1000); // Wait 300 ms before accepting any other command session_write(sess, "DTMFOK\r\n"); } else { session_write(sess, "DTMFFAILED ID NOT FOUND\r\n"); return -1; } return 0; }
void test_session_tcp6(void) { lagopus_result_t ret; char cbuf[256] = {0}; char sbuf[256] = {0}; lagopus_session_t sesc, sess, sesa; struct addrunion dst, src; ret = session_create(SESSION_TCP6|SESSION_PASSIVE, &sess); TEST_ASSERT_EQUAL(LAGOPUS_RESULT_OK, ret); addrunion_ipv6_set(&src, "::0"); ret = session_bind(sess, &src, 10023); TEST_ASSERT_EQUAL(LAGOPUS_RESULT_OK, ret); ret = session_create(SESSION_TCP6|SESSION_ACTIVE, &sesc); TEST_ASSERT_EQUAL(LAGOPUS_RESULT_OK, ret); addrunion_ipv6_set(&dst, "::1"); ret = session_connect(sesc, &dst, 10023, NULL, 0); if (ret == 0 || errno == EINPROGRESS) { TEST_ASSERT(true); } else { TEST_ASSERT(false); } ret = session_accept(sess, &sesa); TEST_ASSERT_EQUAL(LAGOPUS_RESULT_OK, ret); TEST_ASSERT_NOT_NULL(sesa); TEST_ASSERT_TRUE(session_is_alive(sess)); TEST_ASSERT_TRUE(session_is_alive(sesc)); TEST_ASSERT_TRUE(session_is_alive(sesa)); snprintf(cbuf, sizeof(cbuf), "hogehoge\n"); ret = session_write(sesc, cbuf, strlen(cbuf)); TEST_ASSERT_EQUAL(ret, strlen(cbuf)); ret = session_read(sesa, sbuf, sizeof(sbuf)); TEST_ASSERT_EQUAL(ret, strlen(sbuf)); ret = session_write(sesa, sbuf, strlen(sbuf)); TEST_ASSERT_EQUAL(ret, strlen(sbuf)); ret = session_read(sesc, cbuf, sizeof(cbuf)); TEST_ASSERT_EQUAL(ret, strlen(cbuf)); session_destroy(sesc); session_destroy(sesa); session_destroy(sess); }
/** * @brief Record action entry point * * Record action will start MixMonitor on given channel and will * set some variables for record post processing (in h extension). * * @param sess Session rnuning this application * @param app The application structure * @param args Hangup action args "ActionID" and "UniqueID" * @return 0 if the call is found, -1 otherwise */ int recordstop_exec(session_t *sess, app_t *app, const char *args) { struct app_call_info *info; char actionid[ACTIONID_LEN]; // This can only be done after authentication if (!session_test_flag(sess, SESS_FLAG_AUTHENTICATED)) { return NOT_AUTHENTICATED; } // Get Hangup parameteres if (sscanf(args, "%s", actionid) != 1) { return INVALID_ARGUMENTS; } // Try to find the action info of the given actionid if ((info = get_call_info_from_id(sess, actionid)) && !isaac_strlen_zero(info->ochannel)) { // Check if this call is not being recorded if (!info->recording) { session_write(sess, "RECORDSTOPFAILED CALL NOT BEING RECORDED\r\n"); return -1; } ami_message_t msg; memset(&msg, 0, sizeof(ami_message_t)); message_add_header(&msg, "Action: Command"); message_add_header(&msg, "Command: mixmonitor stop %s", info->ochannel); manager_write_message(manager, &msg); // Flag this call as not being recorded info->recording = false; session_write(sess, "RECORDSTOPOK\r\n"); } else { session_write(sess, "RECORDSTOPFAILED ID NOT FOUND\r\n"); return -1; } return 0; }
/** * @brief Hold action entry point * * Hold action will send an event to the first channel generated by * CALL action using the manager application SIPNotifyChan. Not all * terminals support hold event. * * @param sess Session rnuning this application * @param app The application structure * @param args Hangup action args "ActionID" * @return 0 if the call is found, -1 otherwise */ int hold_unhold_exec(session_t *sess, app_t *app, const char *args) { struct app_call_info *info; char actionid[ACTIONID_LEN]; char action[10]; int i; // This can only be done after authentication if (!session_test_flag(sess, SESS_FLAG_AUTHENTICATED)) { return NOT_AUTHENTICATED; } // Get Hangup parameteres if (sscanf(args, "%s", actionid) != 1) { return INVALID_ARGUMENTS; } // Convert action to uppercase isaac_strcpy(action, app->name); for (i=0; action[i]; i++){ action[i] = (char) toupper(action[i]); } // Try to find the action info of the given actionid if ((info = get_call_info_from_id(sess, actionid)) && !isaac_strlen_zero(info->ochannel)) { ami_message_t msg; memset(&msg, 0, sizeof(ami_message_t)); message_add_header(&msg, "Action: SIPNotifyChan"); message_add_header(&msg, "Channel: %s", info->ochannel); message_add_header(&msg, "Event: %s", ((!strcasecmp(app->name, "Hold"))?"hold":"talk")); manager_write_message(manager, &msg); session_write(sess, "%sOK\r\n", action); } else { session_write(sess, "%sFAILED ID NOT FOUND\r\n", action); return -1; } return 0; }
static int http_request(session *s, void *param) { const char *filename = session_get_stash(s, HTTP_RESOURCE); char body[1024]; const size_t len = sprintf(body, "<html>\n<title>404 NOT FOUND</title>\n<body>\n<h1>404 NOT FOUND: '%s'</h1>\n</body>\n</html>\n", filename ); httpserver_response(s, 404, "NOT FOUND", len, "text/html"); if (g_http_debug) printf("HTTP: %s", body); return session_write(s, body, len); }
void test_session_pair_stream(void) { lagopus_result_t ret; char cbuf[256] = {0}; char sbuf[256] = {0}; lagopus_session_t s[2]; ret = session_pair(SESSION_UNIX_STREAM, s); TEST_ASSERT_EQUAL(LAGOPUS_RESULT_OK, ret); snprintf(cbuf, sizeof(cbuf), "hogehoge\n"); ret = session_write(s[0], cbuf, strlen(cbuf)); TEST_ASSERT_EQUAL(ret, strlen(cbuf)); ret = session_read(s[1], sbuf, sizeof(sbuf)); TEST_ASSERT_EQUAL(ret, strlen(sbuf)); ret = session_write(s[1], sbuf, strlen(sbuf)); TEST_ASSERT_EQUAL(ret, strlen(sbuf)); ret = session_read(s[0], cbuf, sizeof(cbuf)); TEST_ASSERT_EQUAL(ret, strlen(cbuf)); session_destroy(s[0]); session_destroy(s[1]); }
static int linda_request(session *s, void *param) { linda *l = (linda*)param; const char *ct = session_get_stash(s, "content-type"); if (!strstr(ct, APPLICATION_JSON)) { httpserver_response(s, 415, "UNSUPPORTED MEDIA TYPE", 0, NULL); return 1; } char *query = (char*)httpserver_get_content(s); if (!query) { httpserver_response(s, 400, "BAD REQUEST", 0, NULL); return 1; } const int dbsync = 0; hlinda *h = linda_begin(l); if (session_get_udata_flag(s, HTTP_GET)) { const char *buf = NULL; if (!linda_rdp(h, query, &buf)) { linda_end(h, dbsync); httpserver_response(s, 404, "NOT FOUND", 0, NULL); free(query); return 1; } size_t len = linda_get_length(h); linda_release(h); // release the buf linda_end(h, dbsync); httpserver_response(s, 200, "OK", len, APPLICATION_JSON); if (g_http_debug) printf("LINDA: %s", buf); free((void*)buf); // now free the buf session_write(s, buf, len); } else if (session_get_udata_flag(s, HTTP_POST)) { const char *buf = NULL; if (!linda_inp(h, query, &buf)) { linda_end(h, dbsync); httpserver_response(s, 404, "NOT FOUND", 0, NULL); free(query); return 1; } size_t len = linda_get_length(h); linda_release(h); // release the buf linda_end(h, dbsync); httpserver_response(s, 200, "OK", len, APPLICATION_JSON); if (g_http_debug) printf("LINDA: %s", buf); free((void*)buf); // now free the buf session_write(s, buf, len); } else if (session_get_udata_flag(s, HTTP_DELETE)) { if (!linda_rm(h, query)) { linda_end(h, dbsync); httpserver_response(s, 404, "NOT FOUND", 0, NULL); free(query); return 1; } linda_end(h, dbsync); httpserver_response(s, 200, "OK", 0, APPLICATION_JSON); } else if (session_get_udata_flag(s, HTTP_PUT)) { if (!linda_out(h, query)) { linda_end(h, dbsync); httpserver_response(s, 404, "NOT FOUND", 0, NULL); free(query); return 1; } linda_end(h, dbsync); httpserver_response(s, 200, "OK", 0, APPLICATION_JSON); } else { linda_end(h, dbsync); httpserver_response(s, 501, "NOT IMPLEMENTED", 0, NULL); free(query); return 1; } free(query); return 1; }
void test_session_tcp(void) { lagopus_result_t ret; char cbuf[256] = {0}; char sbuf[256] = {0}; bool b; lagopus_session_t sesc, sess, sesa, sesp[3]; struct addrunion dst, src; ret = session_create(SESSION_TCP|SESSION_PASSIVE, &sess); TEST_ASSERT_EQUAL(LAGOPUS_RESULT_OK, ret); addrunion_ipv4_set(&src, "0.0.0.0"); ret = session_bind(sess, &src, 10022); TEST_ASSERT_EQUAL(LAGOPUS_RESULT_OK, ret); ret = session_create(SESSION_TCP|SESSION_ACTIVE, &sesc); TEST_ASSERT_EQUAL(LAGOPUS_RESULT_OK, ret); addrunion_ipv4_set(&dst, "127.0.0.1"); ret = session_connect(sesc, &dst, 10022, NULL, 0); if (ret == 0 || errno == EINPROGRESS) { TEST_ASSERT(true); } else { TEST_ASSERT(false); } session_write_event_set(sesc); session_read_event_set(sess); sesp[0] = sesc; sesp[1] = sess; ret = session_poll(sesp, 2, 1); TEST_ASSERT_EQUAL(2, ret); ret = session_is_writable(sesc, &b); TEST_ASSERT_EQUAL(LAGOPUS_RESULT_OK, ret); TEST_ASSERT_TRUE(b); ret = session_is_readable(sess, &b); TEST_ASSERT_EQUAL(LAGOPUS_RESULT_OK, ret); TEST_ASSERT_TRUE(b); ret = session_accept(sess, &sesa); TEST_ASSERT_EQUAL(LAGOPUS_RESULT_OK, ret); TEST_ASSERT_NOT_NULL(sesa); TEST_ASSERT_TRUE(session_is_alive(sess)); TEST_ASSERT_TRUE(session_is_alive(sesc)); TEST_ASSERT_TRUE(session_is_alive(sesa)); session_write_event_set(sesc); session_read_event_set(sess); session_read_event_set(sesa); sesp[0] = sesc; sesp[1] = sess; sesp[2] = sesa; ret = session_poll(sesp, 3, 1); TEST_ASSERT_EQUAL(1, ret); ret = session_is_writable(sesc, &b); TEST_ASSERT_EQUAL(LAGOPUS_RESULT_OK, ret); TEST_ASSERT_TRUE(b); ret = session_is_readable(sess, &b); TEST_ASSERT_EQUAL(LAGOPUS_RESULT_OK, ret); TEST_ASSERT_FALSE(b); ret = session_is_readable(sesa, &b); TEST_ASSERT_EQUAL(LAGOPUS_RESULT_OK, ret); TEST_ASSERT_FALSE(b); snprintf(cbuf, sizeof(cbuf), "hogehoge\n"); ret = session_write(sesc, cbuf, strlen(cbuf)); TEST_ASSERT_EQUAL(ret, strlen(cbuf)); session_read_event_set(sesa); sesp[0] = sesa; ret = session_poll(sesp, 1, 1); TEST_ASSERT_EQUAL(1, ret); ret = session_is_readable(sesa, &b); TEST_ASSERT_EQUAL(LAGOPUS_RESULT_OK, ret); TEST_ASSERT_TRUE(b); ret = session_read(sesa, sbuf, sizeof(sbuf)); TEST_ASSERT_EQUAL(ret, strlen(sbuf)); ret = session_write(sesa, sbuf, strlen(sbuf)); TEST_ASSERT_EQUAL(ret, strlen(sbuf)); ret = session_read(sesc, cbuf, sizeof(cbuf)); TEST_ASSERT_EQUAL(ret, strlen(cbuf)); session_close(sesc); TEST_ASSERT_FALSE(session_is_alive(sesc)); session_close(sesa); TEST_ASSERT_FALSE(session_is_alive(sesa)); session_close(sess); TEST_ASSERT_FALSE(session_is_alive(sesa)); session_write_event_set(sesc); session_read_event_set(sess); session_read_event_set(sesa); sesp[0] = sesc; sesp[1] = sess; sesp[2] = sesa; ret = session_poll(sesp, 3, 1); TEST_ASSERT_EQUAL(LAGOPUS_RESULT_TIMEDOUT, ret); ret = session_is_writable(sesc, &b); TEST_ASSERT_EQUAL(LAGOPUS_RESULT_OK, ret); TEST_ASSERT_FALSE(b); ret = session_is_readable(sess, &b); TEST_ASSERT_EQUAL(LAGOPUS_RESULT_OK, ret); TEST_ASSERT_FALSE(b); ret = session_is_readable(sesa, &b); TEST_ASSERT_EQUAL(LAGOPUS_RESULT_OK, ret); TEST_ASSERT_FALSE(b); session_destroy(sesc); session_destroy(sesa); session_destroy(sess); }
void test_session_fgets(void) { ssize_t ret; char *c; #if 0 char cbuf[256] = {0}; #endif char sbuf[256] = {0}; lagopus_session_t sesc, sess, sesa, sesp[1]; struct addrunion dst, src; ret = session_create(SESSION_TCP|SESSION_PASSIVE, &sess); TEST_ASSERT_EQUAL(LAGOPUS_RESULT_OK, ret); addrunion_ipv4_set(&src, "0.0.0.0"); ret = session_bind(sess, &src, 10022); TEST_ASSERT_EQUAL(LAGOPUS_RESULT_OK, ret); ret = session_create(SESSION_TCP|SESSION_ACTIVE, &sesc); TEST_ASSERT_EQUAL(LAGOPUS_RESULT_OK, ret); addrunion_ipv4_set(&dst, "127.0.0.1"); ret = session_connect(sesc, &dst, 10022, NULL, 0); if (ret == 0 || errno == EINPROGRESS) { TEST_ASSERT(true); } else { TEST_ASSERT(false); } ret = session_accept(sess, &sesa); TEST_ASSERT_EQUAL(LAGOPUS_RESULT_OK, ret); TEST_ASSERT_NOT_NULL(sesa); TEST_ASSERT_TRUE(session_is_alive(sess)); TEST_ASSERT_TRUE(session_is_alive(sesc)); TEST_ASSERT_TRUE(session_is_alive(sesa)); ret = session_printf(sesc, "%s", "hogehoge\n\nhoge"); TEST_ASSERT_EQUAL(ret, strlen("hogehoge\n\nhoge")); session_read_event_set(sesa); sesp[0] = sesa; ret = session_poll(sesp, 1, 1); TEST_ASSERT_EQUAL(ret, 1); c = session_fgets(sbuf, 5, sesa); fprintf(stderr, "1.%s\n", sbuf); TEST_ASSERT_NOT_NULL(c); TEST_ASSERT_EQUAL(0, strncmp(sbuf, "hoge", 5)); c = session_fgets(sbuf, 10, sesa); fprintf(stderr, "2.%s\n", sbuf); TEST_ASSERT_NOT_NULL(c); TEST_ASSERT_EQUAL(0, strncmp(sbuf, "hoge\n", 5)); c = session_fgets(sbuf, 10, sesa); fprintf(stderr, "3.%s\n", sbuf); TEST_ASSERT_NOT_NULL(c); TEST_ASSERT_EQUAL(0, strncmp(sbuf, "\n", 1)); c = session_fgets(sbuf, 5, sesa); fprintf(stderr, "4.%s\n", sbuf); TEST_ASSERT_NOT_NULL(c); TEST_ASSERT_EQUAL(0, strncmp(sbuf, "hoge", 5)); #if 0 do { fprintf(stderr, "out:%s", sbuf); fgets(cbuf, sizeof(cbuf), stdin); fprintf(stderr, "in :%s", cbuf); session_write(sesc, cbuf, strlen(cbuf)); } while (session_fgets(sbuf, sizeof(sbuf), sesa) != NULL); #endif session_close(sesc); TEST_ASSERT_FALSE(session_is_alive(sesc)); session_close(sesa); TEST_ASSERT_FALSE(session_is_alive(sesa)); session_close(sess); TEST_ASSERT_FALSE(session_is_alive(sesa)); session_destroy(sesc); session_destroy(sesa); session_destroy(sess); }
void test_session_tls(void) { #if 0 /* this test code is not work, use openssl s_server/s_client commands for tls session tests. */ lagopus_result_t ret; char cbuf[256] = {0}; char sbuf[256] = {0}; lagopus_session_t sesc, sess, sesa; struct addrunion src, dst; session_tls_set_ca_dir("ca"); session_tls_set_server_cert("./server1.pem"); session_tls_set_server_key("./server1_key_nopass.pem"); session_tls_set_client_key("./client1_key_nopass.pem"); ret = session_create(SESSION_TCP|SESSION_PASSIVE|SESSION_TLS, &sess); TEST_ASSERT_EQUAL(LAGOPUS_RESULT_OK, ret); addrunion_ipv4_set(&src, "0.0.0.0"); ret = session_bind(sess, &src, 10024); addrunion_ipv4_set(&dst, "127.0.0.1"); ret = session_create(SESSION_TCP|SESSION_TLS|SESSION_ACTIVE, &sesc); TEST_ASSERT_EQUAL(LAGOPUS_RESULT_OK, ret); ret = session_connect(sesc, &dst, 10024, &dst, 0); if (ret == 0 || errno == EINPROGRESS) { TEST_ASSERT(true); } else { TEST_ASSERT(false); } ret = session_accept(sess, &sesa); TEST_ASSERT_EQUAL(LAGOPUS_RESULT_OK, ret); TEST_ASSERT_NOT_NULL(sesa); TEST_ASSERT_TRUE(session_is_alive(sess)); TEST_ASSERT_TRUE(session_is_alive(sesa)); ret = session_read(sesa, sbuf, sizeof(sbuf)); TEST_ASSERT_EQUAL(ret, strlen(sbuf)); ret = session_write(sesa, sbuf, strlen(sbuf)); TEST_ASSERT_EQUAL(ret, strlen(sbuf)); TEST_ASSERT_TRUE(session_is_alive(sesc)); snprintf(cbuf, sizeof(cbuf), "hogehoge\n"); ret = session_write(sesc, cbuf, strlen(cbuf)); TEST_ASSERT_EQUAL(ret, strlen(cbuf)); ret = session_read(sesa, sbuf, sizeof(sbuf)); TEST_ASSERT_EQUAL(ret, strlen(sbuf)); ret = session_write(sesa, sbuf, strlen(sbuf)); TEST_ASSERT_EQUAL(ret, strlen(sbuf)); ret = session_read(sesc, cbuf, sizeof(cbuf)); TEST_ASSERT_EQUAL(ret, strlen(cbuf)); session_destroy(sesc); session_destroy(sesa); session_destroy(sess); #endif }
/** * @brief Record action entry point * * Record action will start MixMonitor on given channel and will * set some variables for record post processing (in h extension). * * @param sess Session rnuning this application * @param app The application structure * @param args Hangup action args "ActionID" and "UniqueID" * @return 0 if the call is found, -1 otherwise */ int record_exec(session_t *sess, app_t *app, const char *args) { struct app_call_info *info; char actionid[ACTIONID_LEN]; char filename[128]; time_t timer; char timestr[25]; struct tm* tm_info; // This can only be done after authentication if (!session_test_flag(sess, SESS_FLAG_AUTHENTICATED)) { return NOT_AUTHENTICATED; } // Get Hangup parameteres if (sscanf(args, "%s %s", actionid, filename) != 2) { return INVALID_ARGUMENTS; } // Try to find the action info of the given actionid if ((info = get_call_info_from_id(sess, actionid)) && !isaac_strlen_zero(info->ochannel)) { // Check if this call is already being recorded if (info->recording) { session_write(sess, "RECORDFAILED CALL IS ALREADY BEING RECORDED\r\n"); return -1; } ami_message_t msg; memset(&msg, 0, sizeof(ami_message_t)); message_add_header(&msg, "Action: MixMonitor"); message_add_header(&msg, "Channel: %s", info->ochannel); message_add_header(&msg, "File: %s/%s.wav", call_config.record_path, filename); manager_write_message(manager, &msg); memset(&msg, 0, sizeof(ami_message_t)); message_add_header(&msg, "Action: Setvar"); message_add_header(&msg, "Channel: %s", info->ochannel); message_add_header(&msg, "Variable: GRABACIONES_%s_MODULO", info->ouid); message_add_header(&msg, "Value: %sCC", info->grabaciones_modulo); manager_write_message(manager, &msg); memset(&msg, 0, sizeof(ami_message_t)); message_add_header(&msg, "Action: Setvar"); message_add_header(&msg, "Channel: %s", info->ochannel); message_add_header(&msg, "Variable: GRABACIONES_%s_PLATAFORMA", info->ouid); message_add_header(&msg, "Value: %s", info->grabaciones_plataforma); manager_write_message(manager, &msg); memset(&msg, 0, sizeof(ami_message_t)); message_add_header(&msg, "Action: Setvar"); message_add_header(&msg, "Channel: %s", info->ochannel); message_add_header(&msg, "Variable: GRABACIONES_%s_TIPO", info->ouid); message_add_header(&msg, "Value: %son-demand_ISAAC", info->grabaciones_tipo); manager_write_message(manager, &msg); memset(&msg, 0, sizeof(ami_message_t)); message_add_header(&msg, "Action: Setvar"); message_add_header(&msg, "Channel: %s", info->ochannel); message_add_header(&msg, "Variable: GRABACIONES_%s_ORIGEN", info->ouid); message_add_header(&msg, "Value: %s%s",info->grabaciones_origen,session_get_variable(sess, "AGENT")); manager_write_message(manager, &msg); memset(&msg, 0, sizeof(ami_message_t)); message_add_header(&msg, "Action: Setvar"); message_add_header(&msg, "Channel: %s", info->ochannel); message_add_header(&msg, "Variable: GRABACIONES_%s_DESTINO", info->ouid); message_add_header(&msg, "Value: %s%s",info->grabaciones_destino, info->destiny); manager_write_message(manager, &msg); time(&timer); tm_info = localtime(&timer); strftime(timestr, 25, "%Y:%m:%d_%H:%M:%S", tm_info); memset(&msg, 0, sizeof(ami_message_t)); message_add_header(&msg, "Action: Setvar"); message_add_header(&msg, "Channel: %s", info->ochannel); message_add_header(&msg, "Variable: GRABACIONES_%s_FECHA_HORA", info->ouid); message_add_header(&msg, "Value: %s%s", info->grabaciones_fecha_hora, timestr); manager_write_message(manager, &msg); memset(&msg, 0, sizeof(ami_message_t)); message_add_header(&msg, "Action: Setvar"); message_add_header(&msg, "Channel: %s", info->ochannel); message_add_header(&msg, "Variable: GRABACIONES_%s_RUTA", info->ouid); message_add_header(&msg, "Value: %s%s", info->grabaciones_ruta, call_config.record_path); manager_write_message(manager, &msg); memset(&msg, 0, sizeof(ami_message_t)); message_add_header(&msg, "Action: Setvar"); message_add_header(&msg, "Channel: %s", info->ochannel); message_add_header(&msg, "Variable: GRABACIONES_%s_FICHERO", info->ouid); message_add_header(&msg, "Value: %s%s.wav", info->grabaciones_fichero, filename); manager_write_message(manager, &msg); // Flag this call as being recorded info->recording = true; session_write(sess, "RECORDOK\r\n"); } else { session_write(sess, "RECORDFAILED ID NOT FOUND\r\n"); return -1; } return 0; }
/** * @brief Writes to session CALLEVENT messages * * This function sends the CALLEVENTS to a session when some filter * events triggers. It is used for Agent and Remote channel events.\n * * This function will be callbacked when one of this happens:\n * - A channel sets ACTIONID variable: This gave us leg1 channel\n * - This channel begins a Dial Action: This gave us the second leg\n * - Events on any of these two channels\n * * @param filter Triggering filter structure * @param msg Matching message from Manager * @return 0 in all cases */ int call_state(filter_t *filter, ami_message_t *msg) { // Get Call information struct app_call_info *info = (struct app_call_info *) filter_get_userdata(filter); // Get message event const char *event = message_get_header(msg, "Event"); char from[80], state[80], uniqueid[80], response[256]; bool finished = false; // Initialize arrays memset(from, 0, sizeof(from)); memset(state, 0, sizeof(state)); memset(uniqueid, 0, sizeof(uniqueid)); memset(response, 0, sizeof(response)); // So this leg is first one or second one? if (!strcasecmp(message_get_header(msg, "UniqueID"), info->ouid)) { isaac_strcpy(from, "AGENT"); } else { isaac_strcpy(from, "REMOTE"); } // Send CallStatus message depending on received event if (!strcasecmp(event, "Hangup")) { // Print status message dpending on Hangup Cause const char *cause = message_get_header(msg, "Cause"); if (!strcasecmp(cause, "0") || !strcasecmp(cause, "21")) { isaac_strcpy(state, "ERROR"); } else if (!strcasecmp(cause, "16")) { isaac_strcpy(state, "HANGUP"); } else if (!strcasecmp(cause, "17")) { isaac_strcpy(state, "BUSY"); } else { sprintf(state, "UNKNOWNHANGUP %s", cause); } // This call info has ended finished = true; } else if (!strcasecmp(event, "MusicOnHold")) { if (!strcasecmp(message_get_header(msg, "State"), "Start")) { isaac_strcpy(state, "HOLD"); } else { isaac_strcpy(state, "UNHOLD"); } // In this case, the channel that receives the Hold event is the // one that is being hold, not holding. So we should swap the // AGENT <-> REMOVE value if (!strcasecmp(message_get_header(msg, "UniqueID"), info->ouid)) { isaac_strcpy(from, "REMOTE"); } else { isaac_strcpy(from, "AGENT"); } } else if (!strcasecmp(event, "Newstate")) { // Print status message depending on Channel Status const char *chanstate = message_get_header(msg, "ChannelState"); if (!strcasecmp(chanstate, "5")) { isaac_strcpy(state, "RINGING"); } else if (!strcasecmp(chanstate, "6")) { isaac_strcpy(state, "ANSWERED"); } } else if (!strcasecmp(event, "Rename")) { if (!strcasecmp(message_get_header(msg, "UniqueID"), info->ouid)) { strcpy(info->ochannel, message_get_header(msg, "NewName")); } } else if (!strcasecmp(event, "VarSet")) { const char *varvalue = message_get_header(msg, "Value"); const char *varname = message_get_header(msg, "Variable"); // Progress event on cellphones if (!strcasecmp(varvalue, "SIP 183 Session Progress")) { isaac_strcpy(state, "PROGRESS"); } // Update recording variables if (!strncasecmp(varname, "GRABACIONES_", 12)) { char recordvar[256],recorduniqueid[80], grabaciones[80], recordtype[80]; isaac_strcpy(recordvar, varname); if (sscanf(recordvar, "%[^_]_%[^_]_%s", grabaciones, recorduniqueid, recordtype) == 3) { if (!strcasecmp(recordtype, "MODULO")) sprintf(info->grabaciones_modulo, "%s;", varvalue); if (!strcasecmp(recordtype, "TIPO")) sprintf(info->grabaciones_tipo, "%s;", varvalue); if (!strcasecmp(recordtype, "PLATAFORMA")) sprintf(info->grabaciones_plataforma, "%s;", varvalue); if (!strcasecmp(recordtype, "ORIGEN")) sprintf(info->grabaciones_origen, "%s;", varvalue); if (!strcasecmp(recordtype, "DESTINO")) sprintf(info->grabaciones_destino, "%s;", varvalue); if (!strcasecmp(recordtype, "FECHA_HORA")) sprintf(info->grabaciones_fecha_hora, "%s;", varvalue); if (!strcasecmp(recordtype, "RUTA")) sprintf(info->grabaciones_ruta, "%s;", varvalue); if (!strcasecmp(recordtype, "FICHERO")) sprintf(info->grabaciones_fichero, "%s;", varvalue); } else { isaac_log(LOG_WARNING, "Unhandled record variable %s\n", varname); } } // A channel has set ACTIONID var, this is our leg1 channel. It will Dial soon! if (!strcasecmp(varname, "ACTIONID")) { // Get the UniqueId from the agent channel isaac_strcpy(info->ouid, message_get_header(msg, "UniqueID")); // Store provisional Channel Name isaac_strcpy(info->ochannel, message_get_header(msg, "Channel")); // This messages are always from agent isaac_strcpy(from, "AGENT"); // Register a Filter for the agent statusthe custom manager application PlayDTMF. info->ofilter = filter_create_async(filter->sess, call_state); filter_new_condition(info->ofilter, MATCH_REGEX, "Event", "Hangup|MusicOnHold|Newstate|Rename|VarSet|Dial"); filter_new_condition(info->ofilter, MATCH_EXACT, "UniqueID", info->ouid); filter_set_userdata(info->ofilter, (void*) info); filter_register(info->ofilter); // Tell the client the channel is going on! isaac_strcpy(state, "STARTING"); } } else if (!strcasecmp(event, "Dial") && !strcasecmp(message_get_header(msg, "SubEvent"), "Begin")) { // Get the UniqueId from the agent channel strcpy(info->duid, message_get_header(msg, "DestUniqueID")); strcpy(info->dchannel, message_get_header(msg, "Destination")); // Register a Filter for the agent status info->dfilter = filter_create_async(filter->sess, call_state); filter_set_userdata(info->dfilter, info); filter_new_condition(info->ofilter, MATCH_REGEX, "Event", "Hangup|MusicOnHold|Newstate|Rename|VarSet|Dial"); filter_new_condition(info->dfilter, MATCH_EXACT, "UniqueID", info->duid); filter_register(info->dfilter); // This messages are always from agent isaac_strcpy(from, "REMOTE"); // Store the call state isaac_strcpy(state, "STARTING"); } // Built the event message if (strlen(state)) { // Add Uniqueid to response if requested if (info->print_uniqueid) { isaac_strcpy(uniqueid, !strcasecmp(from, "AGENT")?info->ouid:info->duid); sprintf(response, "CALLSTATUS %s %s %s %s\r\n", info->actionid, uniqueid, from, state); } else { sprintf(response, "CALLSTATUS %s %s %s\r\n", info->actionid, from, state); } // Send this message to other clients if requested if (info->broadcast) { session_write_broadcast(filter->sess, response); } else { session_write(filter->sess, response); } } // We dont expect more info about this filter, it's safe to unregister it here if (finished) filter_unregister(filter); return 0; }
int service_write (dk_session_t * ses, char *buffer, int bytes) { USE_GLOBAL int last_written = 0; int rc; DBG_CHECK_WRITE_FAIL (ses); if (!ses->dks_session) { longjmp_splice (&SESSION_SCH_DATA (ses)->sio_write_broken_context, 1); } while (bytes > 0) { without_scheduling_tic (); rc = session_write (ses->dks_session, &(buffer[last_written]), bytes); restore_scheduling_tic (); if (rc == 0) PROCESS_ALLOW_SCHEDULE (); if (rc > 0) { bytes = bytes - rc; last_written = last_written + rc; } if (rc < 0) { if (SESSTAT_W_ISSET (ses->dks_session, SST_INTERRUPTED)) { PROCESS_ALLOW_SCHEDULE (); } else if (SESSTAT_W_ISSET (ses->dks_session, SST_BLOCK_ON_WRITE)) { if (!_thread_sched_preempt) freeze_thread_write (ses); else { timeout_t tv = { 100, 0 }; retry: tcpses_is_write_ready (ses->dks_session, &tv); if (SESSTAT_W_ISSET (ses->dks_session, SST_TIMED_OUT)) { scheduler_io_data_t * sio = SESSION_SCH_DATA (ses); if (sio->sio_w_timeout_hook && sio->sio_w_timeout_hook (ses)) { SESSTAT_W_CLR (ses->dks_session, SST_TIMED_OUT); goto retry; } SESSTAT_W_SET (ses->dks_session, SST_BROKEN_CONNECTION); longjmp_splice (&SESSION_SCH_DATA (ses)->sio_write_broken_context, 1); } } } else { ses->dks_bytes_sent += last_written; ss_dprintf_2 (("Unrecognized I/O error rc=%d errno=%d in service_write", rc, errno)); SESSTAT_W_CLR (ses->dks_session, SST_OK); SESSTAT_W_SET (ses->dks_session, SST_BROKEN_CONNECTION); longjmp_splice (&SESSION_SCH_DATA (ses)->sio_write_broken_context, 1); } } } ses->dks_bytes_sent += last_written; return 0; }