Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • dap/dap-sdk
1 result
Show changes
Commits on Source (22)
Showing
with 323 additions and 116 deletions
......@@ -61,10 +61,11 @@
#ifndef __cplusplus
# include <stdatomic.h>
#else
# include <atomic>
# define _Atomic(X) std::atomic< X >
#include <atomic>
#define _Atomic(X) std::atomic< X >
#define atomic_bool _Atomic(bool)
#define atomic_uint _Atomic(uint)
#define atomic_int _Atomic(int)
#endif
#ifdef __MACH__
......
......@@ -39,6 +39,7 @@ DAP_PRINTF_ATTR(1, 2) char *dap_strdup_printf(const char *a_format, ...);
char *dap_strncpy(char *a_dst, const char *a_src, size_t a_limit);
char* dap_stpcpy(char *a_dest, const char *a_src);
char* dap_strstr_len(const char *a_haystack, ssize_t a_haystack_len, const char *a_needle);
const char* dap_str_find(const char **a_str_array, const char *a_str);
// concatenates all of str_array's strings, sliding in an optional separator, the returned string is newly allocated.
char* dap_strjoinv(const char *a_separator, char **a_str_array);
char *dap_strjoin(const char *a_separator, ...);
......
......@@ -523,6 +523,16 @@ char* dap_strjoinv(const char *a_separator, char **a_str_array)
return l_string;
}
const char* dap_str_find(const char **a_str_array, const char *a_str) {
if (!a_str_array || !a_str)
return NULL;
for (size_t i = 0; !!a_str_array[i]; ++i) {
if ( !dap_strcmp(a_str, a_str_array[i]) )
return (const char*)a_str_array[i];
}
return NULL;
}
/**
* dap_strjoin:
* @a_separator: (allow-none): a string to insert between each of the
......
......@@ -74,11 +74,9 @@ dap_time_t dap_time_now(void)
*/
dap_nanotime_t dap_nanotime_now(void)
{
dap_nanotime_t l_time_nsec;
struct timespec cur_time;
clock_gettime(CLOCK_REALTIME, &cur_time);
l_time_nsec = (dap_nanotime_t)cur_time.tv_sec * DAP_NSEC_PER_SEC + cur_time.tv_nsec;
return l_time_nsec;
return (dap_nanotime_t)cur_time.tv_sec * DAP_NSEC_PER_SEC + cur_time.tv_nsec;
}
/**
......@@ -171,16 +169,13 @@ int dap_time_to_str_rfc822(char *a_out, size_t a_out_size_max, dap_time_t a_time
*/
dap_time_t dap_time_from_str_rfc822(const char *a_time_str)
{
dap_time_t l_time = 0;
if(!a_time_str) {
return l_time;
}
struct tm l_tm = {};
strptime(a_time_str, "%d %b %Y %T %z", &l_tm);
dap_return_val_if_fail(a_time_str, 0);
struct tm l_tm = { };
char *ret = strptime(a_time_str, "%d %b %Y %T %z", &l_tm);
if ( !ret || *ret )
return log_it(L_ERROR, "Invalid timestamp \"%s\", expected RFC822 string", a_time_str), 0;
time_t tmp = mktime(&l_tm);
l_time = (tmp <= 0) ? 0 : tmp;
return l_time;
return tmp > 0 ? (dap_time_t)tmp : 0;
}
/**
......@@ -190,16 +185,14 @@ dap_time_t dap_time_from_str_rfc822(const char *a_time_str)
*/
dap_time_t dap_time_from_str_simplified(const char *a_time_str)
{
dap_time_t l_time = 0;
if(!a_time_str) {
return l_time;
}
dap_return_val_if_fail(a_time_str, 0);
struct tm l_tm = {};
strptime(a_time_str, "%y%m%d", &l_tm);
char *ret = strptime(a_time_str, "%y%m%d", &l_tm);
if ( !ret || *ret )
return log_it(L_ERROR, "Invalid timestamp \"%s\", expected simplified string \"yy\"mm\"dd", a_time_str), 0;
l_tm.tm_sec++;
time_t tmp = mktime(&l_tm);
l_time = (tmp <= 0) ? 0 : tmp;
return l_time;
return tmp > 0 ? (dap_time_t)tmp : 0;
}
/**
......
......@@ -45,7 +45,7 @@ static inline dap_guuid_t dap_guuid_new()
DAP_STATIC_INLINE dap_guuid_t dap_guuid_compose(uint64_t a_net_id, uint64_t a_service_id)
{
return (dap_guuid_t){ .net_id = a_net_id, .srv_id = a_service_id };
return (dap_guuid_t){{ .net_id = a_net_id, .srv_id = a_service_id }};
}
dap_guuid_str_t dap_guuid_to_hex_str_(dap_guuid_t a_guuid);
#define dap_guuid_to_hex_str(guid) dap_guuid_to_hex_str_(guid).s
......
......@@ -1319,7 +1319,7 @@ int dap_global_db_unpin(const char *a_group, const char *a_key, dap_global_db_ca
* @param a_key
* @return
*/
static int s_del_sync_with_dbi(dap_global_db_instance_t *a_dbi, const char *a_group, const char *a_key)
static int s_del_sync_with_dbi_ex(dap_global_db_instance_t *a_dbi, const char *a_group, const char *a_key, const char * a_value, size_t a_value_len)
{
dap_store_obj_t l_store_obj = {
.key = (char*)a_key,
......@@ -1327,6 +1327,12 @@ static int s_del_sync_with_dbi(dap_global_db_instance_t *a_dbi, const char *a_gr
.flags = DAP_GLOBAL_DB_RECORD_NEW | (a_key ? DAP_GLOBAL_DB_RECORD_DEL : DAP_GLOBAL_DB_RECORD_ERASE),
.timestamp = dap_nanotime_now()
};
if (a_value) {
l_store_obj.value = (byte_t*)a_value;
l_store_obj.value_len = a_value_len;
}
if (a_key)
l_store_obj.sign = dap_store_obj_sign(&l_store_obj, a_dbi->signing_key, &l_store_obj.crc);
......@@ -1344,12 +1350,23 @@ static int s_del_sync_with_dbi(dap_global_db_instance_t *a_dbi, const char *a_gr
return l_res;
}
static int s_del_sync_with_dbi(dap_global_db_instance_t *a_dbi, const char *a_group, const char *a_key) {
return s_del_sync_with_dbi_ex(a_dbi, a_group, a_key, NULL, 0);
}
inline int dap_global_db_del_sync(const char *a_group, const char *a_key)
{
dap_return_val_if_fail(s_dbi && a_group, DAP_GLOBAL_DB_RC_ERROR);
return s_del_sync_with_dbi(s_dbi, a_group, a_key);
}
inline int dap_global_db_del_sync_ex(const char *a_group, const char *a_key, const char * a_value, size_t a_value_len)
{
dap_return_val_if_fail(s_dbi && a_group, DAP_GLOBAL_DB_RC_ERROR);
return s_del_sync_with_dbi_ex(s_dbi, a_group, a_key, a_value, a_value_len);
}
/**
* @brief dap_global_db_delete
* @param a_group
......@@ -1358,7 +1375,8 @@ inline int dap_global_db_del_sync(const char *a_group, const char *a_key)
* @param a_arg
* @return
*/
int dap_global_db_del(const char * a_group, const char *a_key, dap_global_db_callback_result_t a_callback, void *a_arg)
int dap_global_db_del_ex(const char * a_group, const char *a_key, const void * a_value,
const size_t a_value_len, dap_global_db_callback_result_t a_callback, void *a_arg)
{
dap_return_val_if_fail(s_dbi && a_group, DAP_GLOBAL_DB_RC_ERROR);
struct queue_io_msg *l_msg = DAP_NEW_Z_RET_VAL_IF_FAIL(struct queue_io_msg, DAP_GLOBAL_DB_RC_CRITICAL);
......@@ -1368,6 +1386,10 @@ int dap_global_db_del(const char * a_group, const char *a_key, dap_global_db_cal
l_msg->key = dap_strdup(a_key);
l_msg->callback_arg = a_arg;
l_msg->callback_result = a_callback;
if (a_value_len) {
l_msg->value = DAP_DUP_SIZE(a_value, a_value_len);
l_msg->value_length = a_value_len;
}
int l_ret = dap_proc_thread_callback_add(NULL, s_queue_io_callback, l_msg);
if (l_ret != 0) {
......@@ -1379,6 +1401,10 @@ int dap_global_db_del(const char * a_group, const char *a_key, dap_global_db_cal
return l_ret;
}
int dap_global_db_del(const char * a_group, const char *a_key, dap_global_db_callback_result_t a_callback, void *a_arg) {
return dap_global_db_del_ex(a_group, a_key, NULL, 0, a_callback, a_arg);
}
/**
* @brief erase table, call dap_global_db_del_sync with NULL key
* @param a_group - table name
......@@ -1408,7 +1434,12 @@ DAP_INLINE int dap_global_db_erase_table(const char *a_group, dap_global_db_call
*/
static void s_msg_opcode_delete(struct queue_io_msg * a_msg)
{
int l_res = dap_global_db_del_sync(a_msg->group, a_msg->key);
int l_res = 0;
if (a_msg->value && a_msg->value_length) {
l_res = dap_global_db_del_sync_ex(a_msg->group, a_msg->key, a_msg->value, a_msg->value_length);
} else {
l_res = dap_global_db_del_sync(a_msg->group, a_msg->key);
}
if(a_msg->callback_result) {
a_msg->callback_result(a_msg->dbi, l_res==0 ? DAP_GLOBAL_DB_RC_SUCCESS:
......
......@@ -140,6 +140,8 @@ int dap_global_db_set_raw(dap_store_obj_t *a_store_objs, size_t a_store_objs_cou
int dap_global_db_pin(const char *a_group, const char *a_key, dap_global_db_callback_result_t a_callback, void *a_arg);
int dap_global_db_unpin(const char *a_group, const char *a_key, dap_global_db_callback_result_t a_callback, void *a_arg);
int dap_global_db_del(const char *a_group, const char *a_key, dap_global_db_callback_result_t a_callback, void *a_arg);
int dap_global_db_del_ex(const char * a_group, const char *a_key, const void * a_value, const size_t a_value_len,
dap_global_db_callback_result_t a_callback, void *a_arg);
int dap_global_db_flush( dap_global_db_callback_result_t a_callback, void *a_arg);
// Set multiple. In callback writes total processed objects to a_values_total and a_values_count to the a_values_count as well
......@@ -162,6 +164,7 @@ int dap_global_db_set_raw_sync(dap_store_obj_t *a_store_objs, size_t a_store_obj
int dap_global_db_pin_sync(const char *a_group, const char *a_key);
int dap_global_db_unpin_sync(const char *a_group, const char *a_key);
int dap_global_db_del_sync(const char *a_group, const char *a_key);
int dap_global_db_del_sync_ex(const char *a_group, const char *a_key, const char * a_value, size_t a_value_size);
int dap_global_db_flush_sync();
bool dap_global_db_isalnum_group_key(const dap_store_obj_t *a_obj, bool a_not_null_key);
......
......@@ -552,7 +552,7 @@ int dap_worker_thread_loop(dap_context_t * a_context)
if (l_cur->callbacks.read_callback) {
l_cur->last_time_active = time(NULL);
debug_if(g_debug_reactor, L_DEBUG, "Received %lu bytes from socket %zu", l_bytes, l_cur->socket);
l_cur->callbacks.read_callback(l_cur, NULL);
l_cur->callbacks.read_callback(l_cur, l_cur->callbacks.arg);
if (!l_cur->context) {
debug_if(g_debug_reactor, L_DEBUG, "Es %p : %zu unattached from context %u", l_cur, l_cur->socket, a_context->id);
continue;
......
......@@ -1325,8 +1325,8 @@ void dap_events_socket_set_readable_unsafe_ex(dap_events_socket_t *a_es, bool a_
return;
default:
a_es->pending_read = 0;
log_it(L_ERROR, "Operation \"%s\" on [%s] "DAP_FORMAT_ESOCKET_UUID" failed with error %lu",
func, dap_events_socket_get_type_str(a_es), a_es->uuid, l_err);
log_it(L_ERROR, "Operation \"%s\" on [%s] "DAP_FORMAT_ESOCKET_UUID" failed with error %ld: \"%s\"",
func, dap_events_socket_get_type_str(a_es), a_es->uuid, l_err, dap_strerror(l_err));
if ( a_es->callbacks.error_callback )
a_es->callbacks.error_callback(a_es, l_err);
if ( !a_es->no_close )
......@@ -1428,8 +1428,8 @@ void dap_events_socket_set_writable_unsafe_ex( dap_events_socket_t *a_es, bool a
return;
default:
--a_es->pending_write;
log_it(L_ERROR, "Operation \"%s\" on [%s] "DAP_FORMAT_ESOCKET_UUID" failed with error %lu",
func, dap_events_socket_get_type_str(a_es), a_es->uuid, l_err);
log_it(L_ERROR, "Operation \"%s\" on [%s] "DAP_FORMAT_ESOCKET_UUID" failed with error %ld: \"%s\"",
func, dap_events_socket_get_type_str(a_es), a_es->uuid, l_err, dap_strerror(l_err));
if ( a_es->callbacks.error_callback )
a_es->callbacks.error_callback(a_es, l_err);
if ( !a_es->no_close )
......
......@@ -189,10 +189,8 @@ int dap_server_listen_addr_add( dap_server_t *a_server, const char *a_addr, uint
#ifdef SO_REUSEPORT
l_option = 1;
if ( setsockopt(l_socket, SOL_SOCKET, SO_REUSEPORT, (const char*)&l_option, sizeof(int)) < 0 ) {
close_socket_due_to_fail("setsockopt(SO_REUSEPORT)");
return 5;
}
if ( setsockopt(l_socket, SOL_SOCKET, SO_REUSEPORT, (const char*)&l_option, sizeof(int)) < 0 )
debug_if(a_server->ext_log, L_INFO, "setsockopt(SO_REUSEPORT) is not supported");
#endif
if ( bind(l_socket, (struct sockaddr*)&l_saddr, l_len) < 0 ) {
......@@ -283,6 +281,14 @@ dap_server_t *dap_server_new(const char *a_cfg_section, dap_events_socket_callba
if ( dap_server_listen_addr_add(l_server, l_cur_ip, l_cur_port, DESCRIPTOR_TYPE_SOCKET_LISTENING, &l_callbacks) )
log_it( L_ERROR, "Can't add address \"%s : %u\" to listen in server", l_cur_ip, l_cur_port);
}
l_server->whitelist = dap_config_get_array_str(g_config, a_cfg_section, DAP_CFG_PARAM_WHITE_LIST, NULL);
l_server->blacklist = dap_config_get_array_str(g_config, a_cfg_section, DAP_CFG_PARAM_BLACK_LIST, NULL);
if (l_server->whitelist && l_server->blacklist) {
log_it(L_CRITICAL, "Server can't have both black- and whitelists, fix section [%s]", a_cfg_section);
l_server->whitelist = NULL; /* Blacklist will have priority */
}
}
if (!l_server->es_listeners) {
log_it(L_INFO, "Server with no listeners created. "
......@@ -323,7 +329,7 @@ static void s_es_server_accept(dap_events_socket_t *a_es_listener, SOCKET a_remo
dap_server_t *l_server = a_es_listener->server;
assert(l_server);
dap_events_socket_t * l_es_new = NULL;
dap_events_socket_t *l_es_new = NULL;
debug_if(l_server->ext_log, L_DEBUG, "Listening socket %"DAP_FORMAT_SOCKET" uuid "DAP_FORMAT_ESOCKET_UUID" binded on %s:%u "
"accepted new connection from remote %"DAP_FORMAT_SOCKET"",
a_es_listener->socket, a_es_listener->uuid,
......@@ -336,43 +342,54 @@ static void s_es_server_accept(dap_events_socket_t *a_es_listener, SOCKET a_remo
a_es_listener->socket, errno, dap_strerror(errno));
return;
}
l_es_new = dap_events_socket_wrap_no_add(a_remote_socket, &l_server->client_callbacks);
l_es_new->server = l_server;
unsigned short l_family = a_remote_addr->ss_family;
l_es_new->type = DESCRIPTOR_TYPE_SOCKET_CLIENT;
l_es_new->addr_storage = *a_remote_addr;
char l_port_str[NI_MAXSERV];
char l_remote_addr_str[INET6_ADDRSTRLEN] = "", l_port_str[NI_MAXSERV] = "";
switch (l_family) {
dap_events_desc_type_t l_es_type = DESCRIPTOR_TYPE_SOCKET_CLIENT;
switch (a_remote_addr->ss_family) {
#ifdef DAP_OS_UNIX
case AF_UNIX:
l_es_new->type = DESCRIPTOR_TYPE_SOCKET_LOCAL_CLIENT;
l_es_type = DESCRIPTOR_TYPE_SOCKET_LOCAL_CLIENT;
debug_if(l_server->ext_log, L_INFO, "Connection accepted at \"%s\", socket %"DAP_FORMAT_SOCKET,
a_es_listener->remote_addr_str, a_remote_socket);
break;
#endif
case AF_INET:
case AF_INET6:
if (getnameinfo((struct sockaddr*)a_remote_addr, sizeof(*a_remote_addr), l_es_new->remote_addr_str,
sizeof(l_es_new->remote_addr_str), l_port_str, sizeof(l_port_str), NI_NUMERICHOST | NI_NUMERICSERV))
if ( getnameinfo((struct sockaddr*)a_remote_addr, sizeof(*a_remote_addr),
l_remote_addr_str, sizeof(l_remote_addr_str),
l_port_str, sizeof(l_port_str), NI_NUMERICHOST | NI_NUMERICSERV) )
{
#ifdef DAP_OS_WINDOWS
_set_errno(WSAGetLastError());
#endif
log_it(L_ERROR, "getnameinfo() error %d: %s", errno, dap_strerror(errno));
closesocket(a_remote_socket);
return;
}
l_es_new->remote_port = strtol(l_port_str, NULL, 10);
debug_if(l_server->ext_log, L_INFO, "Connection accepted from %s : %hu, socket %"DAP_FORMAT_SOCKET,
l_es_new->remote_addr_str, l_es_new->remote_port, a_remote_socket);
}
if (( l_server->whitelist
? !dap_str_find(l_server->whitelist, l_remote_addr_str)
: !!dap_str_find(l_server->blacklist, l_remote_addr_str) )) {
closesocket(a_remote_socket);
return debug_if(l_server->ext_log, L_INFO, "Connection from %s : %s denied. Dump it",
l_remote_addr_str, l_port_str);
}
debug_if(l_server->ext_log, L_INFO, "Connection accepted from %s : %s, socket %"DAP_FORMAT_SOCKET,
l_remote_addr_str, l_port_str, a_remote_socket);
int one = 1;
if ( setsockopt(l_es_new->socket, IPPROTO_TCP, TCP_NODELAY, (const char*)&one, sizeof(one)) < 0 )
if ( setsockopt(a_remote_socket, IPPROTO_TCP, TCP_NODELAY, (const char*)&one, sizeof(one)) < 0 )
log_it(L_WARNING, "Can't disable Nagle alg, error %d: %s", errno, dap_strerror(errno));
break;
default:
log_it(L_ERROR, "Unsupported protocol family %hu from accept()", l_family);
break;
closesocket(a_remote_socket);
return log_it(L_ERROR, "Unsupported protocol family %hu from accept()", a_remote_addr->ss_family);
}
l_es_new = dap_events_socket_wrap_no_add(a_remote_socket, &l_server->client_callbacks);
l_es_new->server = l_server;
l_es_new->type = l_es_type;
l_es_new->addr_storage = *a_remote_addr;
l_es_new->remote_port = strtol(l_port_str, NULL, 10);
dap_strncpy(l_es_new->remote_addr_str, l_remote_addr_str, sizeof(INET6_ADDRSTRLEN));
dap_worker_add_events_socket( dap_events_worker_get_auto(), l_es_new );
}
......
......@@ -47,6 +47,8 @@
#define DAP_CFG_PARAM_SOCK_PATH "listen-path"
#define DAP_CFG_PARAM_SOCK_PERMISSIONS "listen-unix-socket-permissions"
#define DAP_CFG_PARAM_LEGACY_PORT "listen-port-tcp"
#define DAP_CFG_PARAM_WHITE_LIST "white-list"
#define DAP_CFG_PARAM_BLACK_LIST "black-list"
#ifdef __cplusplus
extern "C" {
......
......@@ -53,6 +53,7 @@ typedef struct dap_server {
dap_server_callback_t delete_callback;
dap_cpu_stats_t cpu_stats;
dap_list_t *es_listeners;
const char **whitelist, **blacklist;
void *_inheritor;
bool ext_log;
} dap_server_t;
......
......@@ -23,7 +23,7 @@ target_include_directories(${PROJECT_NAME} PRIVATE .)
target_include_directories(${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/../../3rdparty/uthash/src)
if(INSTALL_DAP_SDK)
set_target_properties(${PROJECT_NAME} PROPERTIES PUBLIC_HEADER "${DAP_CLIENT_HEADERS}")
set_target_properties(${PROJECT_NAME} PROPERTIES PUBLIC_HEADER "${DAP_LINK_MANAGER_HEADERS}")
INSTALL(TARGETS ${PROJECT_NAME}
LIBRARY DESTINATION lib/dap/net/link_manager/
ARCHIVE DESTINATION lib/dap/net/link_manager/
......
......@@ -64,43 +64,89 @@ typedef struct cli_cmd_arg {
dap_worker_t *worker;
dap_events_socket_uuid_t es_uid;
size_t buf_size;
char buf[];
char *buf, status;
} cli_cmd_arg_t;
static bool s_cli_cmd_exec(void *a_arg);
DAP_STATIC_INLINE void s_cli_cmd_schedule(dap_events_socket_t *a_es, UNUSED_ARG void *a_arg) {
static const char l_content_len_str[] = "Content-Length: ";
char *l_len_token = strstr((char*)a_es->buf_in, l_content_len_str);
#define m_dump_error_and_ret ({ \
const char l_error_str[] = "{ \"type\": 0, \"result\":\" Invalid request\", \"errors\": null, \"id\": 1 }", \
l_err_format_str[] = "HTTP/1.1 400 Bad Request\r\nContent-Length: %zu\r\n\r\n%s"; \
dap_events_socket_write_f_unsafe(a_es, l_err_format_str, sizeof(l_error_str) - 1, l_error_str); \
char *buf_dump = dap_dump_hex(a_es->buf_in, dap_max(a_es->buf_in_size, (size_t)65536)); \
log_it(L_DEBUG, "Incomplete cmd request: %s", buf_dump); \
DAP_DELETE(buf_dump); \
})
if (!l_len_token || !strpbrk(l_len_token, "\r\n"))
return m_dump_error_and_ret;
long l_cmd_len = strtol(l_len_token + sizeof(l_content_len_str) - 1, NULL, 10);
if (!l_cmd_len || l_cmd_len > 65536)
return m_dump_error_and_ret;
static const char l_head_end_str[] = "\r\n\r\n";
char *l_hdr_end_token = strstr(l_len_token, l_head_end_str);
if (!l_hdr_end_token)
return m_dump_error_and_ret;
else
l_hdr_end_token += ( sizeof(l_head_end_str) - 1 );
if (a_es->buf_in_size > l_cmd_len + (size_t)(l_hdr_end_token - (char*)a_es->buf_in))
return m_dump_error_and_ret;
cli_cmd_arg_t *l_arg = DAP_NEW_Z_SIZE(cli_cmd_arg_t, sizeof(cli_cmd_arg_t) + l_cmd_len + 1);
*l_arg = (cli_cmd_arg_t){ .worker = a_es->worker, .es_uid = a_es->uuid, .buf_size = l_cmd_len };
memcpy(l_arg->buf, l_hdr_end_token, l_cmd_len);
dap_proc_thread_callback_add_pri(NULL, s_cli_cmd_exec, l_arg, DAP_QUEUE_MSG_PRIORITY_HIGH);
a_es->buf_in_size = 0;
#undef m_dump_error_and_ret
static bool s_allowed_cmd_check(char *a_buf) {
enum json_tokener_error jterr;
const char *l_method;
json_object *jobj = json_tokener_parse_verbose(a_buf, &jterr),
*jobj_method = NULL;
if ( jterr != json_tokener_success )
return log_it(L_ERROR, "Can't parse json command, error %s", json_tokener_error_desc(jterr)), false;
if ( json_object_object_get_ex(jobj, "method", &jobj_method) )
l_method = json_object_get_string(jobj_method);
else {
log_it(L_ERROR, "Invalid command request, dump it");
json_object_put(jobj);
return false;
}
bool l_allowed = !!dap_str_find( dap_config_get_array_str(g_config, "cli-server", "allowed_cmd", NULL), l_method );
return debug_if(!l_allowed, L_ERROR, "Command %s is restricted", l_method), json_object_put(jobj), l_allowed;
}
DAP_STATIC_INLINE void s_cli_cmd_schedule(dap_events_socket_t *a_es, void *a_arg) {
cli_cmd_arg_t *l_arg = a_arg ? (cli_cmd_arg_t*)a_arg : DAP_NEW_Z(cli_cmd_arg_t);
switch (l_arg->status) {
case 0: {
a_es->callbacks.arg = l_arg;
++l_arg->status;
}
case 1: {
static const char l_content_len_str[] = "Content-Length: ";
l_arg->buf = strstr((char*)a_es->buf_in, l_content_len_str);
if ( !l_arg->buf || !strpbrk(l_arg->buf, "\r\n") )
return;
if (( l_arg->buf_size = (size_t)strtol(l_arg->buf + sizeof(l_content_len_str) - 1, NULL, 10) ))
++l_arg->status;
else
break;
}
case 2: { // Find header end and throw out header
static const char l_head_end_str[] = "\r\n\r\n";
char *l_hdr_end_token = strstr(l_arg->buf, l_head_end_str);
if (!l_hdr_end_token)
return;
l_arg->buf = l_hdr_end_token + sizeof(l_head_end_str) - 1;
++l_arg->status;
}
case 3:
default: {
size_t l_hdr_len = (size_t)(l_arg->buf - (char*)a_es->buf_in);
if ( a_es->buf_in_size < l_arg->buf_size + l_hdr_len )
return;
if ( ((struct sockaddr_in*)&a_es->addr_storage)->sin_addr.s_addr != htonl(INADDR_LOOPBACK)
#ifdef DAP_OS_UNIX
&& a_es->addr_storage.ss_family != AF_UNIX
#endif
&& !s_allowed_cmd_check(l_arg->buf) ) {
dap_events_socket_write_f_unsafe(a_es, "HTTP/1.1 403 Forbidden\r\n");
a_es->flags |= DAP_SOCK_SIGNAL_CLOSE;
return DAP_DELETE(l_arg);
}
l_arg->buf = strndup(l_arg->buf, l_arg->buf_size);
l_arg->worker = a_es->worker;
l_arg->es_uid = a_es->uuid;
dap_proc_thread_callback_add_pri(NULL, s_cli_cmd_exec, l_arg, DAP_QUEUE_MSG_PRIORITY_HIGH);
a_es->buf_in_size = 0;
a_es->callbacks.arg = NULL;
} return;
}
dap_events_socket_write_f_unsafe(a_es, "HTTP/1.1 500 Internal Server Error\r\n");
char *buf_dump = dap_dump_hex(a_es->buf_in, dap_min(a_es->buf_in_size, (size_t)65536));
log_it(L_DEBUG, "Incomplete cmd request:\r\n%s", buf_dump);
DAP_DELETE(buf_dump);
a_es->flags |= DAP_SOCK_SIGNAL_CLOSE;
}
DAP_STATIC_INLINE void s_cli_cmd_delete(dap_events_socket_t *a_es, void UNUSED_ARG *a_arg) {
DAP_DELETE(a_es->callbacks.arg);
}
/**
......@@ -114,7 +160,7 @@ DAP_STATIC_INLINE void s_cli_cmd_schedule(dap_events_socket_t *a_es, UNUSED_ARG
int dap_cli_server_init(bool a_debug_more, const char *a_cfg_section)
{
s_debug_cli = a_debug_more;
dap_events_socket_callbacks_t l_callbacks = { .read_callback = s_cli_cmd_schedule };
dap_events_socket_callbacks_t l_callbacks = { .read_callback = s_cli_cmd_schedule, .delete_callback = s_cli_cmd_delete };
if (!( s_cli_server = dap_server_new(a_cfg_section, NULL, &l_callbacks) )) {
log_it(L_ERROR, "CLI server not initialized");
return -2;
......@@ -190,11 +236,26 @@ int json_commands(const char * a_name) {
"token",
"esbocs",
"global_db",
"net_srv",
"net",
"srv_stake",
"voting",
"srv_xchange",
"emit_delegate",
"exec_cmd"
"token_decl",
"token_update",
"token_update_sign",
"token_decl_sign",
"chain_ca_pub",
"token_emit",
"find",
"version",
"remove",
"gdb_import",
"stats",
"print_log",
"stake_lock",
"exec_cmd"
};
for (size_t i = 0; i < sizeof(long_cmd)/sizeof(long_cmd[0]); i++) {
if (!strcmp(a_name, long_cmd[i])) {
......@@ -363,8 +424,7 @@ static bool s_cli_cmd_exec(void *a_arg) {
"%s", dap_strlen(l_ret), l_ret);
dap_events_socket_write_mt(l_arg->worker, l_arg->es_uid, l_full_ret, dap_strlen(l_full_ret));
// TODO: pagination
//dap_events_socket_remove_and_delete_mt(l_arg->worker, l_arg->es_uid); // No need...
DAP_DEL_MULTY(l_ret, /*l_full_ret,*/ a_arg);
DAP_DEL_MULTY(l_ret, l_arg->buf, /* l_full_ret, */ l_arg);
return false;
}
......
......@@ -18,3 +18,12 @@ target_include_directories(${PROJECT_NAME} INTERFACE . include/)
target_include_directories(${PROJECT_NAME} PUBLIC include)
target_link_libraries(${PROJECT_NAME} dap_core dap_json-c dap_client dap_cli_server)
if(INSTALL_DAP_SDK)
set_target_properties(${PROJECT_NAME} PROPERTIES PUBLIC_HEADER "${JSON_RPC_CORE_HEADERS}")
INSTALL(TARGETS ${PROJECT_NAME}
LIBRARY DESTINATION lib/dap/net/server/json_rpc/rpc_core/
ARCHIVE DESTINATION lib/dap/net/server/json_rpc/rpc_core/
PUBLIC_HEADER DESTINATION include/dap/net/server/json_rpc/rpc_core/
)
endif()
\ No newline at end of file
......@@ -136,6 +136,8 @@ dap_json_rpc_type_param_t dap_json_rpc_params_get_type_param(dap_json_rpc_params
*/
dap_json_rpc_params_t * dap_json_rpc_params_create_from_array_list(json_object *a_array_list);
dap_json_rpc_params_t * dap_json_rpc_params_create_from_subcmd_and_args(json_object *a_subcmd, json_object *a_args, const char* a_method);
/**
* Get a JSON string representation of dap_json_rpc_params_t.
*
......
#include "dap_json_rpc_params.h"
#include "dap_string.h"
#define LOG_TAG "dap_json_rpc_params"
dap_json_rpc_param_t* dap_json_rpc_create_param(void * data, dap_json_rpc_type_param_t type)
{
dap_json_rpc_param_t *param = DAP_NEW(dap_json_rpc_param_t);
if (!param) {
log_it(L_CRITICAL, "%s", c_error_memory_alloc);
return NULL;
}
param->value_param = data;
param->type = type;
return param;
dap_json_rpc_param_t param = { .type = type, .value_param = data };
return DAP_DUP(&param);
}
dap_json_rpc_params_t* dap_json_rpc_params_create(void)
{
dap_json_rpc_params_t *params = DAP_NEW_Z_RET_VAL_IF_FAIL(dap_json_rpc_params_t, NULL);
return params;
return DAP_NEW_Z(dap_json_rpc_params_t);
}
void dap_json_rpc_params_add_data(dap_json_rpc_params_t *a_params, const void *a_value,
......@@ -59,11 +51,13 @@ void dap_json_rpc_params_add_param(dap_json_rpc_params_t *a_params, dap_json_rpc
void dap_json_rpc_param_remove(dap_json_rpc_param_t *param)
{
dap_return_if_fail(param);
DAP_DEL_MULTY(param->value_param, param);
}
void dap_json_rpc_params_remove_all(dap_json_rpc_params_t *a_params)
{
dap_return_if_fail(a_params);
for (uint32_t i=0x0 ; i < dap_json_rpc_params_length(a_params); i++){
dap_json_rpc_param_remove(a_params->params[i]);
}
......@@ -72,17 +66,17 @@ void dap_json_rpc_params_remove_all(dap_json_rpc_params_t *a_params)
uint32_t dap_json_rpc_params_length(dap_json_rpc_params_t *a_params)
{
return a_params->length;
return a_params ? a_params->length : 0;
}
void *dap_json_rpc_params_get(dap_json_rpc_params_t *a_params, uint32_t index)
{
return a_params->length > index ? a_params->params[index]->value_param : NULL;
return a_params && a_params->length > index ? a_params->params[index]->value_param : NULL;
}
dap_json_rpc_type_param_t dap_json_rpc_params_get_type_param(dap_json_rpc_params_t *a_params, uint32_t index)
{
return a_params->length > index ? a_params->params[index]->type : TYPE_PARAM_NULL;
return a_params && a_params->length > index ? a_params->params[index]->type : TYPE_PARAM_NULL;
}
dap_json_rpc_params_t * dap_json_rpc_params_create_from_array_list(json_object *a_array_list)
......@@ -125,6 +119,83 @@ dap_json_rpc_params_t * dap_json_rpc_params_create_from_array_list(json_object *
return params;
}
dap_json_rpc_params_t * dap_json_rpc_params_create_from_subcmd_and_args(json_object *a_subcmd, json_object *a_args, const char* a_method)
{
if (a_method == NULL )
return NULL;
dap_json_rpc_params_t *params = dap_json_rpc_params_create();
dap_string_t * l_str_tmp = dap_string_new("");
// add subcmd to params
dap_string_append_printf(l_str_tmp, "%s;", a_method);
if(a_subcmd){
enum json_type l_subcmd_type = json_object_get_type(a_subcmd);
if(l_subcmd_type == json_type_array){
int length = json_object_array_length(a_subcmd);
for (int i = 0; i < length; i++){
json_object *jobj = json_object_array_get_idx(a_subcmd, i);
json_type jobj_type = json_object_get_type(jobj);
if (jobj_type != json_type_string){
log_it(L_ERROR, "Bad subcommand type");
dap_string_free(l_str_tmp, true);
return NULL;
}
dap_string_append_printf(l_str_tmp, "%s;", json_object_get_string(jobj));
}
} else if (l_subcmd_type == json_type_string) {
dap_string_append_printf(l_str_tmp, "%s;", json_object_get_string( a_subcmd));
} else {
return log_it(L_CRITICAL, "Subcomand must be array or string type."), dap_string_free(l_str_tmp, true), NULL;
}
}
if (a_args){
json_object_object_foreach(a_args, key, val){
const char *l_key_str = NULL;
const char *l_val_str = NULL;
enum json_type l_arg_type = json_object_get_type(val);
if(l_arg_type == json_type_string ||
l_arg_type == json_type_null || l_arg_type == json_type_object) {
l_key_str = key;
l_val_str = json_object_get_string(val);
} else if(l_arg_type == json_type_array){
int length = json_object_array_length(val);
dap_string_append_printf(l_str_tmp, "-%s;", key);
for (int i = 0; i < length; i++){
json_object *jobj = json_object_array_get_idx(val, i);
json_type jobj_type = json_object_get_type(jobj);
if (jobj_type != json_type_string){
log_it(L_ERROR, "Bad subcommand type");
dap_string_free(l_str_tmp, true);
return NULL;
}
dap_string_append_printf(l_str_tmp, "%s%s", json_object_get_string(jobj), i == length - 1 ? ";" : ",");
}
continue;
}
if(l_key_str){
dap_string_append_printf(l_str_tmp, "-%s;%s;", l_key_str, l_val_str ? l_val_str : "");
} else {
return log_it(L_CRITICAL, "Bad argument!"), dap_string_free(l_str_tmp, true), NULL;
}
}
}
l_str_tmp->str[strlen(l_str_tmp->str) - 1] = '\0';
dap_json_rpc_params_add_data(params, l_str_tmp->str, TYPE_PARAM_STRING);
dap_string_free(l_str_tmp, true);
return params;
}
char *dap_json_rpc_params_get_string_json(dap_json_rpc_params_t * a_params)
{
dap_return_val_if_fail(a_params, NULL);
......
......@@ -236,7 +236,9 @@ dap_json_rpc_request_t *dap_json_rpc_request_from_json(const char *a_data)
json_object *jobj = json_tokener_parse_verbose(a_data, &jterr),
*jobj_id = NULL,
*jobj_method = NULL,
*jobj_params = NULL;
*jobj_params = NULL,
*jobj_subcmd = NULL,
*l_arguments_obj = NULL;
if (jterr == json_tokener_success)
do {
if (json_object_object_get_ex(jobj, "id", &jobj_id))
......@@ -253,13 +255,21 @@ dap_json_rpc_request_t *dap_json_rpc_request_from_json(const char *a_data)
break;
}
if (json_object_object_get_ex(jobj, "params", &jobj_params))
json_object_object_get_ex(jobj, "params", &jobj_params);
json_object_object_get_ex(jobj, "subcommand", &jobj_subcmd);
json_object_object_get_ex(jobj, "arguments", &l_arguments_obj);
if (jobj_params)
request->params = dap_json_rpc_params_create_from_array_list(jobj_params);
else {
log_it(L_ERROR, "Error parse JSON string, Can't find array params for request with id: %" DAP_UINT64_FORMAT_U, request->id);
break;
}
else
request->params = dap_json_rpc_params_create_from_subcmd_and_args(jobj_subcmd, l_arguments_obj, request->method);
json_object_put(jobj);
if (!request->params){
dap_json_rpc_params_remove_all(request->params);
DAP_DEL_MULTY(request->method, request);
return NULL;
}
return request;
} while (0);
else
......
......@@ -18,11 +18,7 @@ dap_json_rpc_response_t* dap_json_rpc_response_create(void * result, dap_json_rp
return NULL;
}
dap_json_rpc_response_t *response = DAP_NEW(dap_json_rpc_response_t);
if (!response) {
log_it(L_CRITICAL, "%s", c_error_memory_alloc);
return NULL;
}
dap_json_rpc_response_t *response = DAP_NEW_Z_RET_VAL_IF_FAIL(dap_json_rpc_response_t, NULL);
response->id = id;
response->type = type;
......