gint algo_stitch_init(void) { gint ret = filter_register(IDS_TYPE_STITCH, &algo_stitch_filter); if (ret < 0) { g_error("algo_stitch_filter register failed with error code:%d\n", ret); return FALSE; } return TRUE; }
static int filter_loadall(sxc_client_t *sx, const char *filter_dir) { struct filter_ctx *fctx; DIR *dir; struct dirent *dent; struct stat sb; char *path; int ret = 0, pcnt = 0; if(!sx || !filter_dir) return 1; fctx = sxi_get_fctx(sx); if(fctx->filter_cnt == -1) { SXDEBUG("Filter subsystem not available"); sxi_seterr(sx, SXE_EFILTER, "Filter subsystem not available"); return 1; } if(!(dir = opendir(filter_dir))) { SXDEBUG("Can't open filter directory %s", filter_dir); sxi_seterr(sx, SXE_EFILTER, "Can't open filter directory %s", filter_dir); return 1; } while((dent = readdir(dir))) { if(strcmp(dent->d_name, ".") && strcmp(dent->d_name, "..")) { unsigned int pathlen = strlen(filter_dir) + strlen(dent->d_name) + 2; path = malloc(pathlen); if(!path) { SXDEBUG("OOM allocating path"); sxi_setsyserr(sx, SXE_EMEM, "OOM allocating path"); closedir(dir); return 1; } snprintf(path, pathlen, "%s/%s", filter_dir, dent->d_name); /* FIXME: path separator */ if(lstat(path, &sb) == -1) { free(path); continue; } if(S_ISDIR(sb.st_mode)) { ret = filter_loadall(sx, path); } else if(S_ISREG(sb.st_mode) && !strncmp(dent->d_name, "libsxf_", 7) && strstr(dent->d_name, ".so")) { ret = filter_register(sx, path); if(!ret) pcnt++; else if(ret == 2) ret = 0; } free(path); } } closedir(dir); if(!pcnt && ret) { sxi_seterr(sx, SXE_EFILTER, "No filters loaded due to version mismatch"); return ret; } /* if(pcnt) SXDEBUG("Loaded %d filter(s) from %s", pcnt, filter_dir); */ 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; }