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? - is the only mechanism using this stream object? 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? 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
Hi Chris,
On 20 de mai de 2016, at 09:15, Chris Mandra <mandra@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@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@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@freeswitch.org
participants (2)
-
Chris Mandra
-
Ítalo Rossi