freeswitch

How to set Application-UUID for Applications executed from ESL


I would like to know the triggering ExecuteApplication call for each CHANNEL_EXECUTE event. In Managed ESL's ExecuteAsync method there is no parameter supporting this. The signature is:

public ESLevent ExecuteAsync(string app, string arg, string uuid)

When an app is started with this ExecuteAsync FreeSwitch generates an UUID for the application and this will be present in all subsequent CHANNEL_EXECUTE event's Application-UUID header field. The problem is that the ExecuteAsynch call doesn't return this UUID. This makes it tricky to track the CHANNEL_EXECUTE events if there are multiple running applications. The event returned by ExecuteAsynch has the following form (no UUID is present):

{  
    "Event-Name": "SOCKET_DATA",
    "Content-Type": "command/reply",
    "Reply-Text": "+OK"
}

For example API call execution with Bgapi supports a job_uuid parameter which will be the value of the Job-UUID header field for the related BACKGROUND_JOB events.

 public ESLevent Bgapi(string cmd, string arg, string job_uuid)

How can the same achieved for the dialplan applications like playback?

I have checked if maybe it is hidden by the Managed Wrapper, but the esl_execute function in esl.c (which is used by the wrapper's ExecuteAsync method) doesn't seem to support this either:

ESL_DECLARE(esl_status_t) esl_execute(esl_handle_t *handle, const char *app, const char *arg, const char *uuid)

Solution

  • According to the documentation of sendmsg the Event-UUID header value is designed for that purpose. The esl_execute function in the API uses esl_send_recv to send a self composed sendmsg message, but unfortunately it does not provide a way to set this field. One way to go is to compose a similar sendmsg message which contains the Event-UUID field and send it via esl_send_recv.

    For example with Managed ESL:

    public void ExecuteApplication(ESLconnection conn, string application, string appParams, string uiid, string jobid)
    {
        var header = new Dictionary<string, string>
        {
            {"call-command", "execute"},
            {"execute-app-name", application },
            {"execute-app-arg", appParams },
            {"loops", "1" },
            {"Event-UUID", jobid },
        };
        string newLine = "\n";
        var cmd = $"sendmsg {uiid}{newLine}" + string.Join(newLine, header.Select(kvp => $"{kvp.Key}: {kvp.Value}"));
        var e = conn.SendRecv(cmd);
        ...
    }
    

    So the message to be sent will have the following form:

    sendmsg bb2652fa-467c-44a1-a2f0-0f5e4363e2f3
    call-command: execute
    execute-app-name: playback
    execute-app-arg: d:\vox\sample.vox
    loops: 1
    Event-UUID: play command id 369