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
  • cellframe/cellframe-sdk
  • MIKA83/cellframe-sdk
2 results
Show changes
Commits on Source (2953)
Showing
with 1402 additions and 122 deletions
[submodule "libdap"]
path = libdap
url = ../libdap
branch = master
[submodule "libdap-crypto"]
path = libdap-crypto
url = ../libdap-crypto
branch = master
[submodule "libdap-chain-common"]
path = libdap-chain-common
url = ../libdap-chain-common
branch = master
[submodule "libdap-chain-crypto"]
path = libdap-chain-crypto
url = ../libdap-chain-crypto
branch = master
[submodule "libdap-chain"]
path = libdap-chain
url = ../libdap-chain
branch = master
[submodule "libdap-chain-wallet"]
path = libdap-chain-wallet
url = ../libdap-chain-wallet
branch = master
[submodule "libdap-chain-mempool"]
path = libdap-chain-mempool
url = ../libdap-chain-mempool
branch = master
[submodule "libdap-server-core"]
path = libdap-server-core
url = ../libdap-server-core
branch = master
[submodule "libdap-server"]
path = libdap-server
url = ../libdap-server
branch = master
[submodule "libdap-client"]
path = libdap-client
url = ../libdap-client
branch = master
[submodule "libdap-stream"]
path = libdap-stream
url = ../libdap-stream
branch = master
[submodule "libdap-stream-ch"]
path = libdap-stream-ch
url = ../libdap-stream-ch
branch = master
[submodule "libdap-server-udp"]
path = libdap-server-udp
url = ../libdap-server-udp
branch = master
[submodule "libdap-chain-net"]
path = libdap-chain-net
url = ../libdap-chain-net
branch = master
[submodule "libdap-stream-ch-chain"]
path = libdap-stream-ch-chain
url = ../libdap-stream-ch-chain
branch = master
[submodule "libdap-stream-ch-chain-net"]
path = libdap-stream-ch-chain-net
url = ../libdap-stream-ch-chain-net
branch = master
[submodule "libdap-stream-ch-chain-net-srv"]
path = libdap-stream-ch-chain-net-srv
url = ../libdap-stream-ch-chain-net-srv
branch = master
[submodule "libdap-chain-net-srv"]
path = libdap-chain-net-srv
url = ../libdap-chain-net-srv
branch = master
[submodule "libdap-chain-net-srv-vpn"]
path = libdap-chain-net-srv-vpn
url = ../libdap-chain-net-srv-vpn
branch = master
[submodule "libdap-chain-cs-dag"]
path = libdap-chain-cs-dag
url = ../libdap-chain-cs-dag
branch = master
[submodule "libdap-chain-cs-dag-poa"]
path = libdap-chain-cs-dag-poa
url = ../libdap-chain-cs-dag-poa
branch = master
[submodule "libdap-chain-cs-dag-pos"]
path = libdap-chain-cs-dag-pos
url = ../libdap-chain-cs-dag-pos
branch = master
[submodule "libdap-chain-gdb"]
path = libdap-chain-gdb
url = ../libdap-chain-gdb
branch = master
[submodule "libdap-chain-global-db"]
path = libdap-chain-global-db
url = ../libdap-chain-global-db
branch = master
[submodule "libdap-app-cli"]
path = libdap-app-cli
url = ../libdap-app-cli.git
branch = master
[submodule "libdap-chain-net-srv-app"]
path = libdap-chain-net-srv-app
url = ../libdap-chain-net-srv-app
branch = master
[submodule "libdap-chain-net-srv-app-db"]
path = libdap-chain-net-srv-app-db
url = ../libdap-chain-net-srv-app-db
branch = master
[submodule "libdap-chain-net-srv-datum"]
path = libdap-chain-net-srv-datum
url = ../libdap-chain-net-srv-datum
branch = master
[submodule "libdap-chain-net-srv-datum-pool"]
path = libdap-chain-net-srv-datum-pool
url = ../libdap-chain-net-srv-datum-pool
branch = master
......@@ -2,7 +2,7 @@ project(cellframe-sdk C)
cmake_minimum_required(VERSION 2.8)
set(CMAKE_C_STANDARD 11)
set(CELLFRAME_SDK_NATIVE_VERSION "1.2-6")
set(CELLFRAME_SDK_NATIVE_VERSION "1.3-6")
include(cmake/OS_Detection.cmake)
add_definitions ("-DCELLFRAME_SDK_VERSION=\"${CELLFRAME_SDK_NATIVE_VERSION}\"")
......
......@@ -52,7 +52,7 @@ if(UNIX)
set(_LOPT "-pg")
SET(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -pg")
else()
set(_CCOPT "-Wno-unused-function -Wno-implicit-fallthrough -Wno-unused-variable -Wno-unused-parameter -Wno-unused-but-set-variable -O3 -fPIC -fno-ident -ffast-math -ftree-vectorize -fno-asynchronous-unwind-tables -ffunction-sections -Wl,--gc-sections -Wl,--strip-all -std=gnu11")
set(_CCOPT "-Wno-unused-function -Wno-implicit-fallthrough -Wno-unused-variable -Wno-unused-parameter -Wno-unused-but-set-variable -O3 -fPIC -fno-ident -ffast-math -ftree-vectorize -fno-asynchronous-unwind-tables -ffunction-sections -Wl,--gc-sections -Wl,--strip-all -std=gnu11")
endif()
if (ANDROID)
......
Subproject commit 9d2f6f58336f4555a0cc68d11a46b64fddc574e2
Subproject commit 8c21d84db9762ba3a5c0699599d9f98823bc280b
cmake_minimum_required(VERSION 2.8)
project (dap_app_cli)
set(DAP_APP_CLI_SRCS
src/dap_app_cli.c
src/dap_app_cli_net.c
src/dap_app_cli_shell.c
)
set(DAP_APP_CLI_HEADERS
include/dap_app_cli.h
include/dap_app_cli_net.h
include/dap_app_cli_shell.h
)
if(WIN32)
#include_directories(../3rdparty/curl/include/)
endif()
add_library(${PROJECT_NAME} STATIC ${DAP_APP_CLI_SRCS} ${DAP_APP_CLI_HEADERS} )
target_link_libraries(${PROJECT_NAME} dap_core dap_chain_net m)
target_include_directories(${PROJECT_NAME} PUBLIC include/ )
# libdap-chain-cli
/*
* Authors:
* Dmitriy A. Gearasimov <kahovski@gmail.com>
* DeM Labs Inc. https://demlabs.net
* DeM Labs Open source community https://github.com/demlabsinc
* Copyright (c) 2017-2019
* All rights reserved.
This file is part of DAP (Deus Applications Prototypes) the open source project
DAP (Deus Applicaions Prototypes) is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
DAP is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with any DAP based project. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <stdint.h>
#include <stddef.h>
// command description
typedef struct dap_app_cli_cmd_state {
char *cmd_name;
char **cmd_param;
int cmd_param_count;
int ret_code;
// for reply
char *cmd_res;
size_t cmd_res_len;
size_t cmd_res_cur;
} dap_app_cli_cmd_state_t;
#ifdef __cplusplus
extern "C" {
#endif
/**
* Clear and delete memory of structure cmd_state
*/
void dap_app_cli_free_cmd_state(dap_app_cli_cmd_state_t *cmd);
int dap_app_cli_main(const char * a_app_name, const char * a_socket_path, int argc, char **argv);
#ifdef __cplusplus
}
#endif
/*
* Authors:
* Dmitriy A. Gearasimov <kahovski@gmail.com>
* DeM Labs Inc. https://demlabs.net
* DeM Labs Open source community https://github.com/demlabsinc
* Copyright (c) 2017-2019
* All rights reserved.
This file is part of DAP (Deus Applications Prototypes) the open source project
DAP (Deus Applicaions Prototypes) is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
DAP is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with any DAP based project. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include "dap_app_cli.h"
#include "dap_events_socket.h"
#define DAP_CLI_HTTP_RESPONSE_SIZE_MAX 8192
#define DAP_CLI_HTTP_TIMEOUT 10 // seconds
#define DAP_CLI_ERROR_FORMAT -1
#define DAP_CLI_ERROR_TIMEOUT -2
#define DAP_CLI_ERROR_SOCKET -3
// connection description
typedef uint64_t dap_app_cli_connect_param_t;
/**
* Connect to node unix socket server
*
* return struct connect_param if connect established, else NULL
*/
dap_app_cli_connect_param_t* dap_app_cli_connect(const char * a_socket_path);
/**
* Send request to kelvin-node
*
* return 0 if OK, else error code
*/
int dap_app_cli_post_command(dap_app_cli_connect_param_t *socket, dap_app_cli_cmd_state_t *cmd);
int dap_app_cli_disconnect(dap_app_cli_connect_param_t *socket);
/*
* Authors:
* Dmitriy A. Gearasimov <kahovski@gmail.com>
* DeM Labs Inc. https://demlabs.net
* DeM Labs Open source community https://github.com/demlabsinc
* Copyright (c) 2017-2019
* All rights reserved.
This file is part of DAP (Deus Applications Prototypes) the open source project
DAP (Deus Applicaions Prototypes) is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
DAP is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with any DAP based project. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#ifndef whitespace
#define whitespace(c) (((c) == ' ') || ((c) == '\t'))
#endif
/*
* Initialize readline (and terminal if not already).
*/
int rl_initialize(void);
/**
* Strip whitespace from the start and end of STRING. Return a pointer into STRING.
*/
char * rl_stripwhite(char *string);
/**
* Read a line of input. Prompt with PROMPT. An empty PROMPT means none.
* A return value of NULL means that EOF was encountered.
*/
char *rl_readline(const char *prompt);
/**
* Place STRING at the end of the history list.
*/
void add_history(const char *string);
int parse_shell_options(char **argv, int arg_start, int arg_end);
/*
* Authors:
* Dmitriy A. Gearasimov <kahovski@gmail.com>
* DeM Labs Inc. https://demlabs.net
* DeM Labs Open source community https://github.com/demlabsinc
* Copyright (c) 2017-2019
* All rights reserved.
This file is part of DAP (Deus Applications Prototypes) the open source project
DAP (Deus Applicaions Prototypes) is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
DAP is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with any DAP based project. If not, see <http://www.gnu.org/licenses/>.
*/
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
//#include "dap_client.h"
#include "dap_common.h"
#include "dap_file_utils.h"
#include "dap_strfuncs.h"
#include "dap_chain_node_cli.h"
#include "dap_app_cli.h"
#include "dap_app_cli_net.h"
#include "dap_app_cli_shell.h"
#ifdef _WIN32
#include "registry.h"
#endif
/**
* split string to argc and argv
*/
static char** split_word(char *line, int *argc)
{
if(!line)
{
if(argc)
*argc = 0;
return NULL ;
}
char **argv = calloc(sizeof(char*), strlen(line));
int n = 0;
char *s, *start = line;
size_t len = strlen(line);
for(s = line; s <= line + len; s++) {
if(whitespace(*s)) {
*s = '\0';
argv[n] = start;
s++;
// miss spaces
for(; whitespace(*s); s++)
;
start = s;
n++;
}
}
// last param
if(len) {
argv[n] = start;
n++;
}
if(argc)
*argc = n;
return argv;
}
/*
* Execute a command line.
*/
int execute_line(dap_app_cli_connect_param_t *cparam, char *line)
{
register int i;
dap_chain_node_cmd_item_t *command;
char *word;
/* Isolate the command word. */
i = 0;
while(line[i] && whitespace(line[i]))
i++;
word = line + i;
int argc = 0;
char **argv = split_word(word, &argc);
// Call the function
if(argc > 0) {
dap_app_cli_cmd_state_t cmd;
memset(&cmd, 0, sizeof(dap_app_cli_cmd_state_t));
cmd.cmd_name = (char *) argv[0];
cmd.cmd_param_count = argc - 1;
if(cmd.cmd_param_count > 0)
cmd.cmd_param = (char**) (argv + 1);
// Send command
int res = dap_app_cli_post_command(cparam, &cmd);
return res;
}
fprintf(stderr, "No command\n");
return -1;
}
/**
* Clear and delete memory of structure cmd_state
*/
void dap_app_cli_free_cmd_state(dap_app_cli_cmd_state_t *cmd) {
if(!cmd->cmd_param)
return;
for(int i = 0; i < cmd->cmd_param_count; i++)
{
DAP_DELETE(cmd->cmd_param[i]);
}
DAP_DELETE(cmd->cmd_res);
DAP_DELETE(cmd);
}
/**
* Read and execute commands until EOF is reached. This assumes that
* the input source has already been initialized.
*/
int shell_reader_loop(dap_app_cli_connect_param_t *cparam)
{
char *line, *s;
rl_initialize(); /* Bind our completer. */
int done = 0;
// Loop reading and executing lines until the user quits.
for(; done == 0;) {
// Read a line of input
line = rl_readline("> ");
if(!line)
break;
/* Remove leading and trailing whitespace from the line.
Then, if there is anything left, add it to the history list
and execute it. */
s = rl_stripwhite(line);
if(*s)
{
add_history(s);
execute_line(cparam, s);
}
DAP_DELETE(line);
}
return 0;
}
/**
* @brief dap_app_cli_main
* @param argc
* @param argv
* @return
*/
int dap_app_cli_main(const char * a_app_name, const char * a_socket_path, int a_argc, char **a_argv)
{
dap_set_appname(a_app_name);
if (dap_common_init(dap_get_appname(), NULL) != 0) {
printf("Fatal Error: Can't init common functions module");
return -2;
}
dap_log_level_set(L_CRITICAL);
#ifdef _WIN32
WSADATA wsaData;
WSAStartup(MAKEWORD(2,2), &wsaData);
#endif
// connect to node
dap_app_cli_connect_param_t *cparam = dap_app_cli_connect( a_socket_path );
if(!cparam)
{
printf("Can't connect to %s on socket %s\n",dap_get_appname(), a_socket_path);
exit(-1);
}
if(a_argc > 1){
// Call the function
dap_app_cli_cmd_state_t cmd;
memset(&cmd, 0, sizeof(dap_app_cli_cmd_state_t));
cmd.cmd_name = strdup(a_argv[1]);
cmd.cmd_param_count = a_argc - 2;
if(cmd.cmd_param_count > 0)
cmd.cmd_param = (char**) (a_argv + 2);
// Send command
int res = dap_app_cli_post_command(cparam, &cmd);
dap_app_cli_disconnect(cparam);
#ifdef _WIN32
WSACleanup();
#endif
return res;
}else{
// command not found, start interactive shell
shell_reader_loop(cparam);
dap_app_cli_disconnect(cparam);
}
#ifdef _WIN32
WSACleanup();
#endif
return 0;
}
/*
* Authors:
* Dmitriy A. Gerasimov <kahovski@gmail.com>
* Alexander Lysikov <alexander.lysikov@demlabs.net>
* DeM Labs Inc. https://demlabs.net
* DeM Labs Open source community https://github.com/demlabsinc
* Copyright (c) 2017-2019
* All rights reserved.
This file is part of DAP (Deus Applications Prototypes) the open source project
DAP (Deus Applicaions Prototypes) is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
DAP is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with any DAP based project. If not, see <http://www.gnu.org/licenses/>.
*/
//#include <dap_client.h>
#include <stdlib.h>
#include <sys/types.h>
#include <assert.h>
#include <errno.h>
#ifdef _WIN32
#include <winsock2.h>
#include <windows.h>
#include <mswsock.h>
#include <ws2tcpip.h>
#include <io.h>
#else
#include <sys/socket.h>
#include <sys/un.h>
#endif
#include "dap_common.h"
#include "dap_string.h"
#include "dap_strfuncs.h"
#include "dap_chain_node_cli.h" // for UNIX_SOCKET_FILE
#include "dap_app_cli.h"
#include "dap_app_cli_net.h"
static int s_status;
//callback function to receive http data
static void dap_app_cli_http_read(uint64_t *socket, dap_app_cli_cmd_state_t *l_cmd)
{
size_t l_recv_len = recv(*socket, &l_cmd->cmd_res[l_cmd->cmd_res_cur], DAP_CLI_HTTP_RESPONSE_SIZE_MAX, 0);
if (l_recv_len == -1) {
s_status = DAP_CLI_ERROR_SOCKET;
return;
}
l_cmd->cmd_res_cur += l_recv_len;
switch (s_status) {
case 1: { // Find content length
const char *l_cont_len_str = "Content-Length: ";
char *l_str_ptr = strstr(l_cmd->cmd_res, l_cont_len_str);
if (l_str_ptr && strstr(l_str_ptr, "\r\n")) {
l_cmd->cmd_res_len = atoi(l_str_ptr + strlen(l_cont_len_str));
if (l_cmd->cmd_res_len == 0) {
s_status = DAP_CLI_ERROR_FORMAT;
} else {
s_status++;
}
} else {
break;
}
}
case 2: { // Find header end and throw out header
const char *l_head_end_str = "\r\n\r\n";
char *l_str_ptr = strstr(l_cmd->cmd_res, l_head_end_str);
if (l_str_ptr) {
l_str_ptr += strlen(l_head_end_str);
size_t l_head_size = l_str_ptr - l_cmd->cmd_res;
strncpy(l_cmd->cmd_res, l_str_ptr, l_cmd->cmd_res_cur - l_head_size);
l_cmd->cmd_res_cur -= l_head_size;
s_status++;
} else {
break;
}
}
default:
case 3: { // Complete command reply
if (l_cmd->cmd_res_cur == l_cmd->cmd_res_len) {
l_cmd->cmd_res[l_cmd->cmd_res_cur] = 0;
s_status = 0;
}
} break;
}
}
/**
* @brief dap_app_cli_connect
* @details Connect to node unix socket server
* @param a_socket_path
* @return if connect established, else NULL
*/
dap_app_cli_connect_param_t* dap_app_cli_connect(const char *a_socket_path)
{
// set socket param
int buffsize = DAP_CLI_HTTP_RESPONSE_SIZE_MAX;
#ifdef WIN32
// TODO connect to the named pipe "\\\\.\\pipe\\node_cli.pipe"
uint16_t l_cli_port = dap_config_get_item_uint16 ( g_config, "conserver", "listen_port_tcp");
if (!l_cli_port)
return NULL;
SOCKET l_socket = socket(AF_INET, SOCK_STREAM, 0);
setsockopt((SOCKET)l_socket, SOL_SOCKET, SO_SNDBUF, (char *)&buffsize, sizeof(int) );
setsockopt((SOCKET)l_socket, SOL_SOCKET, SO_RCVBUF, (char *)&buffsize, sizeof(int) );
#else
if (!a_socket_path) {
return NULL;
}
// create socket
int l_socket = socket(AF_UNIX, SOCK_STREAM, 0);
if (l_socket < 0) {
return NULL;
}
setsockopt(l_socket, SOL_SOCKET, SO_SNDBUF, (void*) &buffsize, sizeof(buffsize));
setsockopt(l_socket, SOL_SOCKET, SO_RCVBUF, (void*) &buffsize, sizeof(buffsize));
#endif
// connect
int l_addr_len;
#ifdef WIN32
struct sockaddr_in l_remote_addr;
l_remote_addr.sin_family = AF_INET;
IN_ADDR _in_addr = { { .S_addr = htonl(INADDR_LOOPBACK) } };
l_remote_addr.sin_addr = _in_addr;
l_remote_addr.sin_port = l_cli_port;
l_addr_len = sizeof(struct sockaddr_in);
#else
struct sockaddr_un l_remote_addr;
l_remote_addr.sun_family = AF_UNIX;
strcpy(l_remote_addr.sun_path, a_socket_path);
l_addr_len = SUN_LEN(&l_remote_addr);
#endif
if (connect(l_socket, (struct sockaddr *)&l_remote_addr, l_addr_len) == SOCKET_ERROR) {
#ifdef __WIN32
_set_errno(WSAGetLastError());
#endif
printf("Socket connection err: %d\n", errno);
closesocket(l_socket);
return NULL;
}
uint64_t *l_ret = DAP_NEW(uint64_t);
*l_ret = l_socket;
return l_ret;
}
/**
* Send request to kelvin-node
*
* return 0 if OK, else error code
*/
int dap_app_cli_post_command( dap_app_cli_connect_param_t *a_socket, dap_app_cli_cmd_state_t *a_cmd )
{
if(!a_socket || !a_cmd || !a_cmd->cmd_name) {
assert(0);
return -1;
}
s_status = 1;
a_cmd->cmd_res = DAP_NEW_Z_SIZE(char, DAP_CLI_HTTP_RESPONSE_SIZE_MAX);
a_cmd->cmd_res_cur = 0;
dap_string_t *l_cmd_data = dap_string_new(a_cmd->cmd_name);
if (a_cmd->cmd_param) {
for (int i = 0; i < a_cmd->cmd_param_count; i++) {
if (a_cmd->cmd_param[i]) {
dap_string_append(l_cmd_data, "\r\n");
dap_string_append(l_cmd_data, a_cmd->cmd_param[i]);
}
}
}
dap_string_append(l_cmd_data, "\r\n\r\n");
dap_string_t *l_post_data = dap_string_new("");
dap_string_printf(l_post_data, "POST /connect HTTP/1.1\r\n"
"Host: localhost\r\n"
"Content-Type: text/text\r\n"
"Content-Length: %d\r\n"
"\r\n"
"%s", l_cmd_data->len, l_cmd_data->str);
send(*a_socket, l_post_data->str, l_post_data->len, 0);
//wait for command execution
time_t l_start_time = time(NULL);
while(s_status > 0) {
dap_app_cli_http_read(a_socket, a_cmd);
if (time(NULL) - l_start_time > DAP_CLI_HTTP_TIMEOUT)
return DAP_CLI_ERROR_TIMEOUT;
}
// process result
if (a_cmd->cmd_res && !s_status) {
char **l_str = dap_strsplit(a_cmd->cmd_res, "\r\n", 1);
int l_cnt = dap_str_countv(l_str);
char *l_str_reply = NULL;
if (l_cnt == 2) {
long l_err_code = strtol(l_str[0], NULL, 10);
l_str_reply = l_str[1];
}
printf("%s\n", (l_str_reply) ? l_str_reply : "no response");
dap_strfreev(l_str);
}
DAP_DELETE(a_cmd->cmd_res);
dap_string_free(l_cmd_data, true);
dap_string_free(l_post_data, true);
return s_status;
}
int dap_app_cli_disconnect(dap_app_cli_connect_param_t *a_socket)
{
closesocket(*a_socket);
DAP_DELETE(a_socket);
}
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#include <stdlib.h>
#include <stddef.h>
#include <stdint.h>
#include <unistd.h>
#include <sys/types.h>
#include <getopt.h>
#include <signal.h>
#include <string.h>
#include <assert.h>
#include <setjmp.h>
#include <locale.h>
#ifdef _WIN32
#include <winsock2.h>
#include <windows.h>
#include <mswsock.h>
#include <ws2tcpip.h>
#include <io.h>
#include <pthread.h>
#else
#include <sys/ttydefaults.h>
#endif
#include "dap_common.h"
#include "dap_app_cli.h"
#include "dap_app_cli_shell.h"
//#include "posixjmp.h"
#ifndef savestring
#define savestring(x) strcpy ((char *)malloc (1 + strlen (x)), (x))
#endif
typedef void rl_voidfunc_t(void);
typedef void rl_vintfunc_t(int);
/* Current prompt. */
char *rl_prompt = (char *) NULL;
int rl_visible_prompt_length = 0;
/* Non-zero means we have been called at least once before. */
static int rl_initialized;
/* The stuff that gets printed out before the actual text of the line.
This is usually pointing to rl_prompt. */
char *rl_display_prompt = (char *) NULL;
/* Non-zero makes this the next keystroke to read. */
int rl_pending_input = 0;
/* Make this non-zero to return the current input_line. */
int rl_done;
/* Non-zero if the previous command was a kill command. */
int _rl_last_command_was_kill = 0;
/* Top level environment for readline_internal (). */
jmp_buf _rl_top_level;
/* Length of the current input line. */
int rl_end;
/* The character that can generate an EOF. Really read from
the terminal driver... just defaulted here. */
//int _rl_eof_char = CTRL('D');
#define NEWLINE '\n'
/* Input error; can be returned by (*rl_getc_function) if readline is reading
a top-level command (RL_ISSTATE (RL_STATE_READCMD)). */
#define READERR (-2)
/* Possible state values for rl_readline_state */
#define RL_STATE_NONE 0x000000 /* no state; before first call */
#define RL_STATE_INITIALIZING 0x0000001 /* initializing */
#define RL_STATE_INITIALIZED 0x0000002 /* initialization done */
#define RL_STATE_READCMD 0x0000008 /* reading a command key */
#define RL_STATE_INPUTPENDING 0x0020000 /* rl_execute_next called */
#define RL_STATE_TERMPREPPED 0x0000004 /* terminal is prepped */
/* Flags word encapsulating the current readline state. */
unsigned long rl_readline_state = RL_STATE_NONE;
#define RL_SETSTATE(x) (rl_readline_state |= (x))
#define RL_UNSETSTATE(x) (rl_readline_state &= ~(x))
#define RL_ISSTATE(x) (rl_readline_state & (x))
/* The names of the streams that we do input and output to. */
FILE *rl_instream = (FILE *) NULL;
FILE *rl_outstream = (FILE *) NULL;
/**
* Read one symbol
*/
unsigned char rl_getc(FILE *stream)
{
int result;
unsigned char c;
while(1)
{
#if defined (__MINGW32__)
if (isatty (fileno (stream)))
return (_getch ()); /* "There is no error return." */
#endif
result = 0;
if(result >= 0)
result = read(fileno(stream), &c, sizeof(unsigned char));
if(result == sizeof(unsigned char))
return (c);
/* If zero characters are returned, then the file that we are
reading from is empty! Return EOF in that case. */
if(result == 0)
return (EOF);
}
}
/**
* Set up the prompt and expand it. Called from readline()
*/
int rl_set_prompt(const char *prompt)
{
free(rl_prompt);
rl_prompt = prompt ? savestring(prompt) : (char *) NULL;
rl_display_prompt = rl_prompt ? rl_prompt : "";
fprintf(stdout, "%s", prompt);
fflush(stdout);
//rl_visible_prompt_length = rl_expand_prompt (rl_prompt);
return 0;
}
/**
* Read a line of input. Prompt with PROMPT. An empty PROMPT means none.
* A return value of NULL means that EOF was encountered.
*/
char *rl_readline(const char *prompt)
{
int value_size = 3, value_len = 0;
char *value = DAP_NEW_Z_SIZE(char, value_size + 1);
// Set up the prompt
rl_set_prompt(prompt);
// Read a line of input from the global rl_instream, doing output on the global rl_outstream.
while(1)
{
unsigned char c = rl_getc(rl_instream);
if(c == EOF || c == NEWLINE)
break;
value[value_len] = c;
value_len++;
if(value_len == value_size) {
value_size += 32;
value = realloc(value, value_size + 1);
}
}
return (value);
}
static char* _rl_get_locale_var(const char *v)
{
char *lspec;
lspec = getenv("LC_ALL");
if(lspec == 0 || *lspec == 0)
lspec = getenv(v);
if(lspec == 0 || *lspec == 0)
lspec = getenv("LANG");
return lspec;
}
/*
* Query the right environment variables and call setlocale() to initialize
* the C library locale settings.
*/
static char* _rl_init_locale(void)
{
char *ret, *lspec;
/* Set the LC_CTYPE locale category from environment variables. */
lspec = _rl_get_locale_var("LC_CTYPE");
/* Since _rl_get_locale_var queries the right environment variables,
we query the current locale settings with setlocale(), and, if
that doesn't return anything, we set lspec to the empty string to
force the subsequent call to setlocale() to define the `native'
environment. */
if(lspec == 0 || *lspec == 0)
lspec = setlocale(LC_CTYPE, (char *) NULL);
if(lspec == 0)
lspec = "";
ret = setlocale(LC_CTYPE, lspec); /* ok, since it does not change locale */
//_rl_utf8locale = (ret && *ret) ? utf8locale (ret) : 0;
return ret;
}
/*
* Initialize readline (and terminal if not already).
*/
int rl_initialize(void)
{
/* If we have never been called before, initialize the
terminal and data structures. */
if(rl_initialized == 0)
{
RL_SETSTATE(RL_STATE_INITIALIZING);
rl_instream = (FILE *) stdin;
rl_outstream = (FILE *) stdout;
RL_UNSETSTATE(RL_STATE_INITIALIZING);
rl_initialized++;
RL_SETSTATE(RL_STATE_INITIALIZED);
}
else
(void) _rl_init_locale(); /* check current locale */
RL_SETSTATE(RL_STATE_INITIALIZING);
rl_instream = (FILE *) stdin;
rl_outstream = (FILE *) stdout;
RL_UNSETSTATE(RL_STATE_INITIALIZING);
return 0;
}
int parse_shell_options(char **argv, int arg_start, int arg_end)
{
int arg_index;
int arg_character, on_or_off, next_arg, i;
char *o_option, *arg_string;
arg_index = arg_start;
while(arg_index != arg_end && (arg_string = argv[arg_index]) &&
(*arg_string == '-' || *arg_string == '+'))
{
/* There are flag arguments, so parse them. */
next_arg = arg_index + 1;
/* A single `-' signals the end of options. From the 4.3 BSD sh.
An option `--' means the same thing; this is the standard
getopt(3) meaning. */
if(arg_string[0] == '-' &&
(arg_string[1] == '\0' ||
(arg_string[1] == '-' && arg_string[2] == '\0')))
return (next_arg);
i = 1;
on_or_off = arg_string[0];
while(arg_character = arg_string[i++])
{
switch (arg_character)
{
case 'c':
//want_pending_command = 1;
break;
case 'l':
//make_login_shell = 1;
break;
case 's':
//read_from_stdin = 1;
break;
case 'o':
o_option = argv[next_arg];
if(o_option == 0)
{
//list_minus_o_opts(-1, (on_or_off == '-') ? 0 : 1);
break;
}
//if(set_minus_o_option(on_or_off, o_option) != EXECUTION_SUCCESS)
// exit(EX_BADUSAGE);
next_arg++;
break;
case 'O':
/* Since some of these can be overridden by the normal
interactive/non-interactive shell initialization or
initializing posix mode, we save the options and process
them after initialization. */
o_option = argv[next_arg];
if(o_option == 0)
{
//shopt_listopt(o_option, (on_or_off == '-') ? 0 : 1);
break;
}
//add_shopt_to_alist(o_option, on_or_off);
next_arg++;
break;
case 'D':
//dump_translatable_strings = 1;
break;
default:
break;
// if(change_flag(arg_character, on_or_off) == FLAG_ERROR)
// {
// report_error(_("%c%c: invalid option"), on_or_off, arg_character);
// show_shell_usage(stderr, 0);
// exit(EX_BADUSAGE);
// }
}
}
/* Can't do just a simple increment anymore -- what about
"bash -abouo emacs ignoreeof -hP"? */
arg_index = next_arg;
}
return (arg_index);
}
/**
* Strip whitespace from the start and end of STRING. Return a pointer into STRING.
*/
char * rl_stripwhite(char *string)
{
register char *s, *t;
for(s = string; whitespace(*s); s++)
;
if(*s == 0)
return (s);
t = s + strlen(s) - 1;
while(t > s && whitespace(*t))
t--;
*++t = '\0';
return s;
}
/* The structure used to store a history entry. */
typedef struct _hist_entry {
char *line;
char *timestamp; /* char * rather than time_t for read/write */
char *data;
} HIST_ENTRY;
/**
* Place STRING at the end of the history list.
*/
void add_history(const char *string)
{
HIST_ENTRY *temp;
// The data field is set to NULL
// TODO
}
Subproject commit 28a2ac9fb57cdc01ed124c659f604efab8d5ed02
Subproject commit 69a3f979f9d9a16e286eff099121476275020a3e
*.autosave
*.user
*.o
*.obj
Makefile
cmake_minimum_required(VERSION 2.8)
project (dap_chain_common)
set(DAP_CHAIN_COMMON_SRCS
src/dap_chain_common.c
src/dap_chain_datum.c
src/dap_chain_datum_token.c
src/dap_chain_datum_hashtree_roots.c
src/dap_chain_datum_tx_items.c
src/dap_chain_datum_tx.c
src/dap_chain_datum_tx_out_cond.c
src/dap_chain_datum_tx_token.c
src/dap_chain_datum_tx_receipt.c
)
set(DAP_CHAIN_COMMON_HEADERS
include/dap_chain_common.h
include/dap_chain_datum.h
include/dap_chain_datum_token.h
include/dap_chain_datum_hashtree_roots.h
include/dap_chain_datum_tx_items.h
include/dap_chain_datum_tx.h
include/dap_chain_datum_tx_in.h
include/dap_chain_datum_tx_in_cond.h
include/dap_chain_datum_tx_out.h
include/dap_chain_datum_tx_out_cond.h
include/dap_chain_datum_tx_pkey.h
include/dap_chain_datum_tx_sig.h
include/dap_chain_datum_tx_token.h
include/dap_chain_datum_tx_receipt.h
)
add_library(${PROJECT_NAME} STATIC ${DAP_CHAIN_COMMON_SRCS} ${DAP_CHAIN_COMMON_HEADERS})
target_link_libraries(dap_chain_common dap_core dap_crypto )
target_include_directories(dap_chain_common PUBLIC include/ )
# libdap-chain-common
/*
* Authors:
* Dmitriy A. Gearasimov <gerasimov.dmitriy@demlabs.net>
* DeM Labs Inc. https://demlabs.net https:/gitlab.com/demlabs
* Kelvin Project https://github.com/kelvinblockchain
* Copyright (c) 2017-2018
* All rights reserved.
This file is part of DAP (Deus Applications Prototypes) the open source project
DAP (Deus Applicaions Prototypes) is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
DAP is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with any DAP based project. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <stdint.h>
#include <stdio.h>
#include "dap_common.h"
#include "dap_math_ops.h"
#include "dap_enc_key.h"
#include "dap_pkey.h"
#include "dap_sign.h"
#include "dap_hash.h"
#define DAP_CHAIN_ADDR_VERSION_CURRENT 1
#define DAP_CHAIN_ID_SIZE 8
#define DAP_CHAIN_SHARD_ID_SIZE 8
#define DAP_CHAIN_NET_ID_SIZE 8
#define DAP_CHAIN_NODE_ROLE_SIZE 2
#define DAP_CHAIN_HASH_SLOW_SIZE 32
#define DAP_CHAIN_TIMESTAMP_SIZE 8
#define DAP_CHAIN_TICKER_SIZE_MAX 10
#define DATOSHI_LD 1000000000.0L
// Chain ID of the whole system
typedef union dap_chain_id {
uint8_t raw[DAP_CHAIN_ID_SIZE];
uint64_t uint64;
} DAP_ALIGN_PACKED dap_chain_id_t;
// Shard ID
typedef union dap_chain_cell_id {
uint8_t raw[DAP_CHAIN_SHARD_ID_SIZE];
uint64_t uint64;
} DAP_ALIGN_PACKED dap_chain_cell_id_t;
/**
* @struct Node address
*
*/
typedef union dap_chain_node_addr {
uint64_t uint64;
uint16_t words[sizeof(uint64_t)/2];
uint8_t raw[sizeof(uint64_t)]; // Access to selected octects
} DAP_ALIGN_PACKED dap_chain_node_addr_t;
#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
#define NODE_ADDR_FP_STR "%04hX::%04hX::%04hX::%04hX"
#define NODE_ADDR_FP_ARGS(a) a->words[2],a->words[3],a->words[0],a->words[1]
#define NODE_ADDR_FPS_ARGS(a) &a->words[2],&a->words[3],&a->words[0],&a->words[1]
#define NODE_ADDR_FP_ARGS_S(a) a.words[2],a.words[3],a.words[0],a.words[1]
#define NODE_ADDR_FPS_ARGS_S(a) &a.words[2],&a.words[3],&a.words[0],&a.words[1]
#else
#define NODE_ADDR_FP_STR "%04hX::%04hX::%04hX::%04hX"
#define NODE_ADDR_FP_ARGS(a) a->words[3],a->words[2],a->words[1],a->words[0]
#define NODE_ADDR_FPS_ARGS(a) &a->words[3],&a->words[2],&a->words[1],&a->words[0]
#define NODE_ADDR_FP_ARGS_S(a) a.words[3],a.words[2],a.words[1],a.words[0]
#define NODE_ADDR_FPS_ARGS_S(a) &a.words[3],&a.words[2],&a.words[1],&a.words[0]
#endif
inline static int dap_chain_node_addr_from_str( dap_chain_node_addr_t * a_addr, const char * a_addr_str){
return (int) sscanf(a_addr_str,NODE_ADDR_FP_STR,NODE_ADDR_FPS_ARGS(a_addr) )-4;
}
/**
*
*
*
*
*/
typedef union dap_chain_node_role{
enum {
NODE_ROLE_ROOT_MASTER=0x00,
NODE_ROLE_ROOT=0x01,
NODE_ROLE_ARCHIVE=0x02,
NODE_ROLE_CELL_MASTER=0x10,
NODE_ROLE_MASTER = 0x20,
NODE_ROLE_FULL=0xf0,
NODE_ROLE_LIGHT=0xff } enums;
uint8_t raw[DAP_CHAIN_NODE_ROLE_SIZE];
} DAP_ALIGN_PACKED dap_chain_node_role_t;
typedef union dap_chain_net_id{
uint64_t uint64;
uint8_t raw[DAP_CHAIN_NET_ID_SIZE];
} DAP_ALIGN_PACKED dap_chain_net_id_t;
typedef union dap_chain_hash_slow{
uint8_t raw[DAP_CHAIN_HASH_SLOW_SIZE];
} dap_chain_hash_slow_t;
typedef enum dap_chain_hash_slow_kind {
HASH_GOLD = 0, HASH_SILVER, HASH_COPPER, HASH_USELESS = -1
} dap_chain_hash_slow_kind_t;
typedef struct dap_chain_addr{
uint8_t addr_ver; // 0 for default
dap_chain_net_id_t net_id; // Testnet, mainnet or alternet
dap_sign_type_t sig_type;
union{
//dap_chain_hash_fast_t hash;
struct {
uint8_t key_spend[sizeof(dap_chain_hash_fast_t)/2];
uint8_t key_view[sizeof(dap_chain_hash_fast_t)/2];
} key_sv;
uint8_t key[sizeof(dap_chain_hash_fast_t)];
uint8_t hash[sizeof(dap_chain_hash_fast_t)];
dap_chain_hash_fast_t hash_fast;
} data;
dap_chain_hash_fast_t checksum;
} DAP_ALIGN_PACKED dap_chain_addr_t;
typedef uint64_t dap_chain_time_t;
static inline dap_chain_time_t dap_chain_time_now() { return (dap_chain_time_t) time(NULL); }
#define DAP_CHAIN_NET_SRV_UID_SIZE 8
typedef union {
uint8_t raw[DAP_CHAIN_NET_SRV_UID_SIZE];
#if DAP_CHAIN_NET_SRV_UID_SIZE == 8
uint64_t raw_ui64[1];
uint64_t uint64;
#elif DAP_CHAIN_NET_SRV_UID_SIZE == 16
uint64_t raw_ui64[1];
uint128_t uint128;
#endif
} dap_chain_net_srv_uid_t;
typedef enum {
SERV_UNIT_UNDEFINED = 0 ,
SERV_UNIT_MB = 0x00000001, // megabytes
SERV_UNIT_SEC = 0x00000002, // seconds
SERV_UNIT_DAY = 0x00000003, // days
SERV_UNIT_KB = 0x00000010, // kilobytes
SERV_UNIT_B = 0x00000011, // bytes
} serv_unit_enum_t;
typedef union {
uint8_t raw[4];
uint32_t raw_ui32[1];
uint32_t uint32;
serv_unit_enum_t enm;
} dap_chain_net_srv_price_unit_uid_t;
typedef enum dap_chain_tx_item_type {
TX_ITEM_TYPE_IN = 0x00, /// @brief Transaction: inputs
TX_ITEM_TYPE_OUT = 0x10, /// @brief Transaction: outputs
TX_ITEM_TYPE_PKEY = 0x20,
TX_ITEM_TYPE_SIG = 0x30,
TX_ITEM_TYPE_TOKEN = 0x40,
TX_ITEM_TYPE_TOKEN_EXT = 0x41,
TX_ITEM_TYPE_IN_COND = 0x50, /// @brief Transaction: conditon inputs
TX_ITEM_TYPE_OUT_COND = 0x60, /// @brief Transaction: conditon outputs
TX_ITEM_TYPE_RECEIPT = 0x70,
TX_ITEM_TYPE_ANY = 0xff,
} dap_chain_tx_item_type_t;
typedef struct dap_chain_receipt{
dap_chain_net_srv_uid_t srv_uid; // Service UID
dap_chain_net_srv_price_unit_uid_t units_type;
uint64_t units; // Unit of service (seconds, megabytes, etc.) Only for SERV_CLASS_PERMANENT
uint64_t value_datoshi; // Receipt value
} dap_chain_receipt_info_t;
#ifdef __cplusplus
extern "C" {
#endif
size_t dap_chain_hash_slow_to_str(dap_chain_hash_slow_t * a_hash, char * a_str, size_t a_str_max);
char* dap_chain_addr_to_str(const dap_chain_addr_t *a_addr);
dap_chain_addr_t* dap_chain_addr_from_str(const char *str);
dap_chain_net_id_t dap_chain_net_id_from_str(const char* a_str);
dap_chain_net_srv_uid_t dap_chain_net_srv_uid_from_str(const char* a_str);
void dap_chain_addr_fill(dap_chain_addr_t *a_addr, dap_enc_key_t *a_key, dap_chain_net_id_t *a_net_id);
int dap_chain_addr_check_sum(const dap_chain_addr_t *a_addr);
static inline long double dap_chain_balance_to_coins( uint128_t a_balance){
return (long double) a_balance / DATOSHI_LD;
}
static inline uint128_t dap_chain_coins_to_balance( long double a_balance){
return (uint128_t)( a_balance * DATOSHI_LD) ;
}
/**
* @brief dap_chain_hash_to_str
* @param a_hash
* @return
*/
static inline char * dap_chain_hash_slow_to_str_new(dap_chain_hash_slow_t * a_hash)
{
const size_t c_hash_str_size = sizeof(*a_hash)*2 +1 /*trailing zero*/ +2 /* heading 0x */ ;
char * ret = DAP_NEW_Z_SIZE(char, c_hash_str_size);
dap_chain_hash_slow_to_str(a_hash,ret,c_hash_str_size);
return ret;
}
/**
* @brief dap_chain_hash_kind_check
* @param a_hash
* @details
*/
static inline dap_chain_hash_slow_kind_t dap_chain_hash_slow_kind_check(dap_chain_hash_slow_t * a_hash, const uint8_t a_valuable_head )
{
register uint8_t i;
register uint8_t l_hash_first = a_hash->raw[0];
register uint8_t * l_hash_data = a_hash->raw;
for ( i = 1; i < a_valuable_head; ++i ){
if ( l_hash_data[i] != l_hash_first )
return HASH_USELESS;
}
if( l_hash_first == 0 )
return HASH_GOLD;
else
return HASH_SILVER;
}
#ifdef __cplusplus
}
#endif
/*
* Authors:
* Dmitriy A. Gearasimov <gerasimov.dmitriy@demlabs.net>
* DeM Labs Inc. https://demlabs.net
* Kelvin Project https://github.com/kelvinblockchain
* Copyright (c) 2017-2018
* All rights reserved.
This file is part of DAP (Deus Applications Prototypes) the open source project
DAP (Deus Applicaions Prototypes) is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
DAP is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with any DAP based project. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <stdint.h>
#include "dap_common.h"
#include "dap_math_ops.h"
#include "dap_chain_common.h"
#define DAP_CHAIN_DATUM_VERSION 0x00
/// End section, means all the rest of the block is empty
#define DAP_CHAIN_DATUM_BLOCK_END 0x0000
/// Section with additional roots, for example transaction roots
#define DAP_CHAIN_DATUM_BLOCK_ROOTS 0x0001
/// Transaction header section
#define DAP_CHAIN_DATUM_TX 0x0100
/// Transaction request section
#define DAP_CHAIN_DATUM_TX_REQUEST 0x0300
/// Smart contract: DVM code section
#define DAP_CHAIN_DATUM_WASM_CODE 0x0900
/// Smart contract: DVM code section
#define DAP_CHAIN_DATUM_WASM_DATA 0x0901
/// Smart contract: EVM code section
#define DAP_CHAIN_DATUM_EVM_CODE 0x0910
/// Smart contract: EVM data section
#define DAP_CHAIN_DATUM_EVM_DATA 0x0911
/// CA with public key and self signed metadata
#define DAP_CHAIN_DATUM_CA 0x0c00
/// Token
/// Simple token decl
#define DAP_CHAIN_DATUM_TOKEN_DECL 0xf000
#define DAP_CHAIN_DATUM_TOKEN_EMISSION 0xf100
#define DAP_CHAIN_DATUM_CUSTOM 0xffff
extern const char * c_datum_type_str[];
#define DAP_CHAIN_DATUM_ID_SIZE 4
// Datum subchain type id
typedef union dap_chain_datum_typeid{
uint8_t data[DAP_CHAIN_DATUM_ID_SIZE];
} DAP_ALIGN_PACKED dap_chain_datum_typeid_t;
/**
* @struct dap_chain_block_section
* @brief section inside the block
*/
typedef struct dap_chain_datum{
struct{
/// Datum version
uint8_t version_id;
/// Section type id
uint16_t type_id;
/// Data section size
uint32_t data_size;
/// Create timestamp (GM time)
uint64_t ts_create;
} DAP_ALIGN_PACKED header;
uint8_t data[]; /// Stored datum body
} DAP_ALIGN_PACKED dap_chain_datum_t;
struct dap_chain;
typedef struct dap_chain dap_chain_t;
typedef struct dap_chain_datum_iter{
dap_chain_t * chain;
dap_chain_datum_t * cur;
void * cur_item;
void * atom_iter;
} dap_chain_datum_iter_t;
typedef dap_chain_datum_iter_t* (*dap_chain_datum_callback_iter_create_t)(dap_chain_t * );
typedef dap_chain_datum_t* (*dap_chain_datum_callback_iter_get_first_t)(dap_chain_datum_iter_t * );
typedef dap_chain_datum_t* (*dap_chain_datum_callback_iter_get_next_t)(dap_chain_datum_iter_t * );
typedef void (*dap_chain_datum_callback_iter_delete_t)(dap_chain_datum_iter_t * );
static inline size_t dap_chain_datum_size(dap_chain_datum_t * a_datum)
{
if(!a_datum)
return 0;
return sizeof(a_datum->header) + a_datum->header.data_size;
}
dap_chain_datum_t * dap_chain_datum_create(uint16_t a_type_id, const void * a_data, size_t a_data_size);