[Freeswitch-users] API question

Ítalo Rossi italo at freeswitch.org
Fri May 20 16:54:53 MSD 2016


Hi Chris,

> On 20 de mai de 2016, at 09:15, Chris Mandra <mandra at gmail.com> wrote:
> 
> Hi guys - Happy Friday - I have a question:
> 
> My main question is how can I generate a custom reply event for an api call with custom body and headers for an API method defined in a custom module?

The reply event is a pretty standard and you’ll return a body from your api function and the body will be added to the reply event. 

> - is the only mechanism using this stream object?

Why do you need this customization? You can add in the api body response a json string and parse this data in your consuming app, there’s no need for such customization.

> or can you directly create the reply event.  and if so, how does the caller receive the reply event and know it corresponds to the API call made?

What I can say here is that you can create additional events like switch_event_t *myevent; then switch_event_create_subclass(&myevent, SWITCH_EVENT_CUSTOM, MY_CUSTOM_EVENT); and fire this event with switch_event_fire(&myevent);
Read the other modules to know how they do this.

> I want to provide a response to an API command defined in a module via:
> 
> 
> 
> 
> 
> #define SWITCH_STANDARD_API(name) static switch_status_t name (​_In_opt_z_​ const char *cmd, ​_In_opt_​ switch_core_session_t *session, ​_In_​ switch_stream_handle_t *stream)
> 
> 
> 
> 
> 
> and my understanding (which may be incorrect) is that the stream object can be used to provide a response.
> 
> 
> 
> When the API is called, an event is automatically generated which uses the stream object.  Is there a way to directly modify the event that is generated in response to an API call?  How can I modify the headers and body of the event generated from an API call directly?
> 
> 
> 
> 
> 
> it looks like the stream data is put in the body of the response as per: switch_event_add_body(event, "%s", reply);
> 
> 
> 
> 
> 
> the relevant code is in api_exec
> 
> 
> 
> 
> 
> static void *SWITCH_THREAD_FUNC api_exec(switch_thread_t *thread, void *obj)
> 
> {
> 
> 
> 
>     struct api_command_struct ​*acs = (struct api_command_struct *​) obj;
> 
>     switch_stream_handle_t stream = { 0 };
> 
>     char *reply, *freply = NULL;
> 
>     switch_status_t status;
> 
> 
> 
>     switch_mutex_lock(globals.listener_mutex);
> 
>     prefs.threads++;
> 
>     switch_mutex_unlock(globals.listener_mutex);
> 
> 
> 
> 
> 
>     if (!acs) {
> 
>         switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Internal error.\n");
> 
>         goto cleanup;
> 
>     }
> 
> 
> 
>     if (!acs->listener || !switch_test_flag(acs->listener, LFLAG_RUNNING) ||
> 
>         !acs->listener->rwlock || switch_thread_rwlock_tryrdlock(acs->listener->rwlock) != SWITCH_STATUS_SUCCESS) {
> 
>         switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error! cannot get read lock.\n");
> 
>         acs->ack = -1;
> 
>         goto done;
> 
>     }
> 
> 
> 
>     acs->ack = 1;
> 
> 
> 
>     SWITCH_STANDARD_STREAM(stream);
> 
> 
> 
>     if (acs->console_execute) {
> 
>         if ((status = switch_console_execute(acs->api_cmd, 0, &stream)) != SWITCH_STATUS_SUCCESS) {
> 
>             stream.write_function(&stream, "-ERR %s Command not found!\n", acs->api_cmd);
> 
>         }
> 
>     } else {
> 
>         status = switch_api_execute(acs->api_cmd, acs->arg, NULL, &stream);
> 
>     }
> 
> 
> 
>     if (status == SWITCH_STATUS_SUCCESS) {
> 
>         reply = stream.data;
> 
>     } else {
> 
>         freply = switch_mprintf("-ERR %s Command not found!\n", acs->api_cmd);
> 
>         reply = freply;
> 
>     }
> 
> 
> 
>     if (!reply) {
> 
>         reply = "Command returned no output!";
> 
>     }
> 
> 
> 
>     if (acs->bg) {
> 
>         switch_event_t *event;
> 
> 
> 
>         if (switch_event_create(&event, SWITCH_EVENT_BACKGROUND_JOB) == SWITCH_STATUS_SUCCESS) {
> 
>             switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Job-UUID", acs->uuid_str);
> 
>             switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Job-Command", acs->api_cmd);
> 
>             if (acs->arg) {
> 
>                 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Job-Command-Arg", acs->arg);
> 
>             }
> 
>             switch_event_add_body(event, "%s", reply);
> 
>             switch_event_fire(&event);
> 
>         }
> 
>     } else {
> 
>         switch_size_t rlen, blen;
> 
>         char buf[1024] = "";
> 
> 
> 
>         if (!(rlen = strlen(reply))) {
> 
>             reply = "-ERR no reply\n";
> 
>             rlen = strlen(reply);
> 
>         }
> 
> 
> 
>         switch_snprintf(buf, sizeof(buf), "Content-Type: api/response\nContent-Length: %" SWITCH_SSIZE_T_FMT "\n\n", rlen);
> 
>         blen = strlen(buf);
> 
>         switch_socket_send(acs->listener->sock, buf, &blen);
> 
>         switch_socket_send(acs->listener->sock, reply, &rlen);
> 
>     }
> 
> 
> 
>     switch_safe_free(stream.data);
> 
>     switch_safe_free(freply);
> 
> 
> 
>     if (acs->listener->rwlock) {
> 
>         switch_thread_rwlock_unlock(acs->listener->rwlock);
> 
>     }
> 
> 
> 
> Thanks, as ever, for your help,
> 
> chris
> 
> 
> 
> _________________________________________________________________________
> Professional FreeSWITCH Consulting Services: 
> consulting at freeswitch.org
> http://www.freeswitchsolutions.com
> 
> Official FreeSWITCH Sites
> http://www.freeswitch.org
> http://confluence.freeswitch.org
> http://www.cluecon.com
> 
> FreeSWITCH-users mailing list
> FreeSWITCH-users at lists.freeswitch.org
> http://lists.freeswitch.org/mailman/listinfo/freeswitch-users
> UNSUBSCRIBE:http://lists.freeswitch.org/mailman/options/freeswitch-users
> http://www.freeswitch.org

Ítalo Rossi
italo at freeswitch.org






Join us at ClueCon 2016 Aug 8-12, 2016
More information about the FreeSWITCH-users mailing list