Merge pull request #1098 in FS/freeswitch from ~LAZEDO/freeswitch:feature/FS-9813 to master
* commit '01decbf434ea323c155fec5e863f5e51e55bad97': FS-9813 [mod_kazoo] add kz_http_put
This commit is contained in:
commit
a9c13d3fc6
|
@ -31,6 +31,7 @@
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
#include "mod_kazoo.h"
|
#include "mod_kazoo.h"
|
||||||
|
#include <switch_curl.h>
|
||||||
|
|
||||||
#define UUID_SET_DESC "Set a variable"
|
#define UUID_SET_DESC "Set a variable"
|
||||||
#define UUID_SET_SYNTAX "<uuid> <var> [value]"
|
#define UUID_SET_SYNTAX "<uuid> <var> [value]"
|
||||||
|
@ -38,6 +39,9 @@
|
||||||
#define UUID_MULTISET_DESC "Set multiple variables"
|
#define UUID_MULTISET_DESC "Set multiple variables"
|
||||||
#define UUID_MULTISET_SYNTAX "<uuid> <var>=<value>;<var>=<value>..."
|
#define UUID_MULTISET_SYNTAX "<uuid> <var>=<value>;<var>=<value>..."
|
||||||
|
|
||||||
|
#define KZ_HTTP_PUT_DESC "upload a local freeswitch file to a url"
|
||||||
|
#define KZ_HTTP_PUT_SYNTAX "localfile url"
|
||||||
|
|
||||||
SWITCH_STANDARD_API(uuid_setvar_function) {
|
SWITCH_STANDARD_API(uuid_setvar_function) {
|
||||||
switch_core_session_t *psession = NULL;
|
switch_core_session_t *psession = NULL;
|
||||||
char *mycmd = NULL, *argv[3] = { 0 };
|
char *mycmd = NULL, *argv[3] = { 0 };
|
||||||
|
@ -144,9 +148,177 @@ SWITCH_STANDARD_API(uuid_setvar_multi_function) {
|
||||||
return SWITCH_STATUS_SUCCESS;
|
return SWITCH_STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static size_t header_callback(char *buffer, size_t size, size_t nitems, void *userdata)
|
||||||
|
{
|
||||||
|
switch_event_t* event = (switch_event_t*)userdata;
|
||||||
|
int len = strlen(buffer);
|
||||||
|
char buf[1024];
|
||||||
|
if(len > 2 && len < 1024) {
|
||||||
|
strncpy(buf, buffer, len-2);
|
||||||
|
buf[len-2] = '\0';
|
||||||
|
switch_event_add_header_string(event, SWITCH_STACK_PUSH | SWITCH_STACK_BOTTOM, "Reply-Headers", buf);
|
||||||
|
}
|
||||||
|
return nitems * size;
|
||||||
|
}
|
||||||
|
|
||||||
|
SWITCH_STANDARD_API(kz_http_put)
|
||||||
|
{
|
||||||
|
switch_status_t status = SWITCH_STATUS_SUCCESS;
|
||||||
|
switch_memory_pool_t *lpool = NULL;
|
||||||
|
switch_memory_pool_t *pool = NULL;
|
||||||
|
char *args = NULL;
|
||||||
|
char *argv[10] = { 0 };
|
||||||
|
int argc = 0;
|
||||||
|
switch_event_t *params = NULL;
|
||||||
|
char *url = NULL;
|
||||||
|
char *filename = NULL;
|
||||||
|
|
||||||
|
switch_curl_slist_t *headers = NULL; /* optional linked-list of HTTP headers */
|
||||||
|
char *ext; /* file extension, used for MIME type identification */
|
||||||
|
const char *mime_type = "application/octet-stream";
|
||||||
|
char *buf = NULL;
|
||||||
|
char *error = NULL;
|
||||||
|
|
||||||
|
CURL *curl_handle = NULL;
|
||||||
|
long httpRes = 0;
|
||||||
|
struct stat file_info = {0};
|
||||||
|
FILE *file_to_put = NULL;
|
||||||
|
int fd;
|
||||||
|
|
||||||
|
if (session) {
|
||||||
|
pool = switch_core_session_get_pool(session);
|
||||||
|
} else {
|
||||||
|
switch_core_new_memory_pool(&lpool);
|
||||||
|
pool = lpool;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (zstr(cmd)) {
|
||||||
|
stream->write_function(stream, "USAGE: %s\n", KZ_HTTP_PUT_SYNTAX);
|
||||||
|
status = SWITCH_STATUS_SUCCESS;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
args = strdup(cmd);
|
||||||
|
argc = switch_separate_string(args, ' ', argv, (sizeof(argv) / sizeof(argv[0])));
|
||||||
|
if (argc != 2) {
|
||||||
|
stream->write_function(stream, "USAGE: %s\n", KZ_HTTP_PUT_SYNTAX);
|
||||||
|
status = SWITCH_STATUS_SUCCESS;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* parse params and get profile */
|
||||||
|
url = switch_core_strdup(pool, argv[0]);
|
||||||
|
if (*url == '{') {
|
||||||
|
switch_event_create_brackets(url, '{', '}', ',', ¶ms, &url, SWITCH_FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
filename = switch_core_strdup(pool, argv[1]);
|
||||||
|
|
||||||
|
/* guess what type of mime content this is going to be */
|
||||||
|
if ((ext = strrchr(filename, '.'))) {
|
||||||
|
ext++;
|
||||||
|
if (!(mime_type = switch_core_mime_ext2type(ext))) {
|
||||||
|
mime_type = "application/octet-stream";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
buf = switch_mprintf("Content-Type: %s", mime_type);
|
||||||
|
|
||||||
|
headers = switch_curl_slist_append(headers, buf);
|
||||||
|
|
||||||
|
/* open file and get the file size */
|
||||||
|
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "opening %s for upload to %s\n", filename, url);
|
||||||
|
fd = open(filename, O_RDONLY);
|
||||||
|
if (fd == -1) {
|
||||||
|
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "open() error: %s\n", strerror(errno));
|
||||||
|
status = SWITCH_STATUS_FALSE;
|
||||||
|
stream->write_function(stream, "-ERR error opening file\n");
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
if (fstat(fd, &file_info) == -1) {
|
||||||
|
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "fstat() error: %s\n", strerror(errno));
|
||||||
|
stream->write_function(stream, "-ERR fstat error\n");
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
close(fd);
|
||||||
|
|
||||||
|
/* libcurl requires FILE* */
|
||||||
|
file_to_put = fopen(filename, "rb");
|
||||||
|
if (!file_to_put) {
|
||||||
|
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "fopen() error: %s\n", strerror(errno));
|
||||||
|
status = SWITCH_STATUS_FALSE;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
curl_handle = switch_curl_easy_init();
|
||||||
|
if (!curl_handle) {
|
||||||
|
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "switch_curl_easy_init() failure\n");
|
||||||
|
status = SWITCH_STATUS_FALSE;
|
||||||
|
stream->write_function(stream, "-ERR switch_curl_easy init failure\n");
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
switch_curl_easy_setopt(curl_handle, CURLOPT_UPLOAD, 1);
|
||||||
|
switch_curl_easy_setopt(curl_handle, CURLOPT_PUT, 1);
|
||||||
|
switch_curl_easy_setopt(curl_handle, CURLOPT_NOSIGNAL, 1);
|
||||||
|
switch_curl_easy_setopt(curl_handle, CURLOPT_HTTPHEADER, headers);
|
||||||
|
switch_curl_easy_setopt(curl_handle, CURLOPT_URL, url);
|
||||||
|
switch_curl_easy_setopt(curl_handle, CURLOPT_READDATA, file_to_put);
|
||||||
|
switch_curl_easy_setopt(curl_handle, CURLOPT_INFILESIZE_LARGE, (curl_off_t)file_info.st_size);
|
||||||
|
switch_curl_easy_setopt(curl_handle, CURLOPT_FOLLOWLOCATION, 1);
|
||||||
|
switch_curl_easy_setopt(curl_handle, CURLOPT_MAXREDIRS, 10);
|
||||||
|
switch_curl_easy_setopt(curl_handle, CURLOPT_USERAGENT, "freeswitch-http-cache/1.0");
|
||||||
|
switch_curl_easy_setopt(curl_handle, CURLOPT_HEADERDATA, stream->param_event);
|
||||||
|
switch_curl_easy_setopt(curl_handle, CURLOPT_HEADERFUNCTION, header_callback);
|
||||||
|
switch_curl_easy_setopt(curl_handle, CURLOPT_SSL_VERIFYPEER, 0L);
|
||||||
|
switch_curl_easy_perform(curl_handle);
|
||||||
|
switch_curl_easy_getinfo(curl_handle, CURLINFO_RESPONSE_CODE, &httpRes);
|
||||||
|
switch_curl_easy_cleanup(curl_handle);
|
||||||
|
|
||||||
|
if (httpRes == 200 || httpRes == 201 || httpRes == 202 || httpRes == 204) {
|
||||||
|
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s saved to %s\n", filename, url);
|
||||||
|
switch_event_add_header(stream->param_event, SWITCH_STACK_BOTTOM, "API-Output", "%s saved to %s\n", filename, url);
|
||||||
|
stream->write_function(stream, "+OK\n");
|
||||||
|
} else {
|
||||||
|
error = switch_mprintf("Received HTTP error %ld trying to save %s to %s", httpRes, filename, url);
|
||||||
|
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "%s\n", error);
|
||||||
|
switch_event_add_header(stream->param_event, SWITCH_STACK_BOTTOM, "API-Error", "%s", error);
|
||||||
|
switch_event_add_header(stream->param_event, SWITCH_STACK_BOTTOM, "API-HTTP-Error", "%ld", httpRes);
|
||||||
|
stream->write_function(stream, "-ERR ");
|
||||||
|
stream->write_function(stream, error);
|
||||||
|
stream->write_function(stream, "\n");
|
||||||
|
status = SWITCH_STATUS_GENERR;
|
||||||
|
}
|
||||||
|
|
||||||
|
done:
|
||||||
|
if (file_to_put) {
|
||||||
|
fclose(file_to_put);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (headers) {
|
||||||
|
switch_curl_slist_free_all(headers);
|
||||||
|
}
|
||||||
|
|
||||||
|
switch_safe_free(buf);
|
||||||
|
switch_safe_free(error);
|
||||||
|
|
||||||
|
switch_safe_free(args);
|
||||||
|
|
||||||
|
if (lpool) {
|
||||||
|
switch_core_destroy_memory_pool(&lpool);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (params) {
|
||||||
|
switch_event_destroy(¶ms);
|
||||||
|
}
|
||||||
|
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
void add_kz_commands(switch_loadable_module_interface_t **module_interface, switch_api_interface_t *api_interface) {
|
void add_kz_commands(switch_loadable_module_interface_t **module_interface, switch_api_interface_t *api_interface) {
|
||||||
SWITCH_ADD_API(api_interface, "kz_uuid_setvar_multi", UUID_SET_DESC, uuid_setvar_multi_function, UUID_MULTISET_SYNTAX);
|
SWITCH_ADD_API(api_interface, "kz_uuid_setvar_multi", UUID_SET_DESC, uuid_setvar_multi_function, UUID_MULTISET_SYNTAX);
|
||||||
switch_console_set_complete("add kz_uuid_setvar_multi ::console::list_uuid");
|
switch_console_set_complete("add kz_uuid_setvar_multi ::console::list_uuid");
|
||||||
SWITCH_ADD_API(api_interface, "kz_uuid_setvar", UUID_MULTISET_DESC, uuid_setvar_function, UUID_SET_SYNTAX);
|
SWITCH_ADD_API(api_interface, "kz_uuid_setvar", UUID_MULTISET_DESC, uuid_setvar_function, UUID_SET_SYNTAX);
|
||||||
switch_console_set_complete("add kz_uuid_setvar ::console::list_uuid");
|
switch_console_set_complete("add kz_uuid_setvar ::console::list_uuid");
|
||||||
|
SWITCH_ADD_API(api_interface, "kz_http_put", KZ_HTTP_PUT_DESC, kz_http_put, KZ_HTTP_PUT_SYNTAX);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -377,7 +377,7 @@ static void *SWITCH_THREAD_FUNC bgapi4_exec(switch_thread_t *thread, void *obj)
|
||||||
_ei_x_encode_string(&send_msg->buf, reply);
|
_ei_x_encode_string(&send_msg->buf, reply);
|
||||||
|
|
||||||
if (stream.param_event) {
|
if (stream.param_event) {
|
||||||
ei_encode_switch_event_headers(&send_msg->buf, stream.param_event);
|
ei_encode_switch_event_headers_2(&send_msg->buf, stream.param_event, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (switch_queue_trypush(ei_node->send_msgs, send_msg) != SWITCH_STATUS_SUCCESS) {
|
if (switch_queue_trypush(ei_node->send_msgs, send_msg) != SWITCH_STATUS_SUCCESS) {
|
||||||
|
|
|
@ -84,6 +84,10 @@ static void ei_x_print_msg(ei_x_buff *buf, erlang_pid *pid, int send) {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void ei_encode_switch_event_headers(ei_x_buff *ebuf, switch_event_t *event) {
|
void ei_encode_switch_event_headers(ei_x_buff *ebuf, switch_event_t *event) {
|
||||||
|
ei_encode_switch_event_headers_2(ebuf, event, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ei_encode_switch_event_headers_2(ei_x_buff *ebuf, switch_event_t *event, int encode) {
|
||||||
switch_event_header_t *hp;
|
switch_event_header_t *hp;
|
||||||
char *uuid = switch_event_get_header(event, "unique-id");
|
char *uuid = switch_event_get_header(event, "unique-id");
|
||||||
int i;
|
int i;
|
||||||
|
@ -105,7 +109,8 @@ void ei_encode_switch_event_headers(ei_x_buff *ebuf, switch_event_t *event) {
|
||||||
for (hp = event->headers; hp; hp = hp->next) {
|
for (hp = event->headers; hp; hp = hp->next) {
|
||||||
ei_x_encode_tuple_header(ebuf, 2);
|
ei_x_encode_tuple_header(ebuf, 2);
|
||||||
ei_x_encode_binary(ebuf, hp->name, strlen(hp->name));
|
ei_x_encode_binary(ebuf, hp->name, strlen(hp->name));
|
||||||
switch_url_decode(hp->value);
|
if(encode)
|
||||||
|
switch_url_decode(hp->value);
|
||||||
ei_x_encode_binary(ebuf, hp->value, strlen(hp->value));
|
ei_x_encode_binary(ebuf, hp->value, strlen(hp->value));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
#define MAX_QUEUE_LEN 25000
|
#define MAX_QUEUE_LEN 25000
|
||||||
#define MAX_MISSED 500
|
#define MAX_MISSED 500
|
||||||
#define MAX_PID_CHARS 255
|
#define MAX_PID_CHARS 255
|
||||||
#define VERSION "mod_kazoo v1.3.0-1"
|
#define VERSION "mod_kazoo v1.4.0-1"
|
||||||
|
|
||||||
#define API_COMMAND_DISCONNECT 0
|
#define API_COMMAND_DISCONNECT 0
|
||||||
#define API_COMMAND_REMOTE_IP 1
|
#define API_COMMAND_REMOTE_IP 1
|
||||||
|
@ -153,6 +153,7 @@ switch_socket_t *create_socket(switch_memory_pool_t *pool);
|
||||||
switch_status_t create_ei_cnode(const char *ip_addr, const char *name, struct ei_cnode_s *ei_cnode);
|
switch_status_t create_ei_cnode(const char *ip_addr, const char *name, struct ei_cnode_s *ei_cnode);
|
||||||
switch_status_t ei_compare_pids(const erlang_pid *pid1, const erlang_pid *pid2);
|
switch_status_t ei_compare_pids(const erlang_pid *pid1, const erlang_pid *pid2);
|
||||||
void ei_encode_switch_event_headers(ei_x_buff *ebuf, switch_event_t *event);
|
void ei_encode_switch_event_headers(ei_x_buff *ebuf, switch_event_t *event);
|
||||||
|
void ei_encode_switch_event_headers_2(ei_x_buff *ebuf, switch_event_t *event, int decode);
|
||||||
void ei_link(ei_node_t *ei_node, erlang_pid * from, erlang_pid * to);
|
void ei_link(ei_node_t *ei_node, erlang_pid * from, erlang_pid * to);
|
||||||
void ei_encode_switch_event(ei_x_buff * ebuf, switch_event_t *event);
|
void ei_encode_switch_event(ei_x_buff * ebuf, switch_event_t *event);
|
||||||
int ei_helper_send(ei_node_t *ei_node, erlang_pid* to, ei_x_buff *buf);
|
int ei_helper_send(ei_node_t *ei_node, erlang_pid* to, ei_x_buff *buf);
|
||||||
|
|
Loading…
Reference in New Issue