[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