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;
}
Beispiel #2
0
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;
}
Beispiel #3
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;
}