libcon provide the low level functions to deal with memory allocation, strings, sockets, zlib compression, simple XML parsing, and module dynamic loading.
Together with the binary module system, it acts as an abstraction layer for the operating system, allowing to quickly build safe, lightweight, performant and portable distributed applications.
The full source code for libcon is on the github libcon
Memory allocation is based on area that represent application's thread heap, host memory is statically allocated for each thread in the pool when the application initialize, and the internal allocator give the application a reference to a zone in its area, and manage garbage collection.
Each thread have their own heap, and manage it locally, which make the multi thread memory management entierely lockless.
The API to allocate new memory and get a reference to the allocated pointer is found in libcon/base/mem_base.h
void init_default_mem_area (unsigned int size);
init_default_mem_area (4*1024*1024);
unsigned int allocate_new_zone (unsigned int area_id, mem_size zone_size, mem_zone_ref *zone_ref);
mem_zone_ref myref={PTR_NULL};
allocate_new_zone ( get_mem_area_id() ,256, &myref);
mem_ptr get_zone_ptr (mem_zone_ref_const_ptr ref,mem_size ofset);
mem_zone_ref myref={PTR_NULL};
mem_ptr my_ptr;
allocate_new_zone (get_mem_area_id(), 256, &myref);
my_ptr = get_zone_ptr(&myref, 0);
mem_size get_zone_size (mem_zone_ref_const_ptr ref);
mem_zone_ref myref={PTR_NULL}; mem_size my_size;
allocate_new_zone (get_mem_area_id(), 256, &myref);
my_size = get_zone_size(&myref);
unsigned int get_zone_numref (mem_zone_ref *zone_ref);
mem_zone_ref myref={PTR_NULL}; unsigned int n_refs;
allocate_new_zone (get_mem_area_id(), 256, &myref);
n_refs = get_zone_numref(&myref);
void release_zone_ref (mem_zone_ref_ptr zone_ref);
mem_zone_ref myref={PTR_NULL};
allocate_new_zone (get_mem_area_id(), 256, &myref);
release_zone_ref(&myref);
int realloc_zone (mem_zone_ref *zone_ref,mem_size new_size);
mem_zone_ref myref={PTR_NULL};
allocate_new_zone (get_mem_area_id(), 256, &myref);
realloc_zone(&myref, 512);
int expand_zone (mem_zone_ref *ref,mem_size new_size);
mem_zone_ref myref={PTR_NULL};
allocate_new_zone (get_mem_area_id(), 256, &myref);
expand_zone(&myref,512);
void copy_zone_ref (mem_zone_ref_ptr dest_zone_ref,mem_zone_ref_const_ptr zone_ref);
mem_zone_ref myref={PTR_NULL}, myrefcopy={PTR_NULL};
allocate_new_zone (get_mem_area_id(), 256, &myref);
copy_zone_ref(&myrefcopy, &myref);
release_zone_ref(&myref); // (myref memory is not freed until the myrefcopy reference is released.)
Equivalent to the standard LIBC API to allocate direct pointer is defined in libcon/base/std_mem.h
LIBC_API mem_ptr C_API_FUNC malloc_c (mem_size sz);
LIBC_API mem_ptr C_API_FUNC calloc_c (mem_size sz,mem_size blk);
LIBC_API mem_ptr C_API_FUNC realloc_c (mem_ptr ptr,mem_size sz);
LIBC_API void C_API_FUNC free_c (mem_ptr ptr);
The base api to manipulate strings is found in libcon/include/strs.h
void init_string (struct string *str);
struct string mystring;
init_string(&string); ( equivalent to struct string mystring={PTR_NULL}; )
void free_string (struct string *str);
struct string mystring={PTR_NULL};
make_string(&mystring,"hello world");
free_string(&mystring);
int prepare_new_data (struct string *str, size_t len);
struct string mystring={PTR_NULL};
prepare_new_data(&string, 64);
int make_string (struct string *str, const char *toto);
struct string mystring={PTR_NULL};
make_string(&mystring,"hello world");
log_output(mystring.str); => "hello world"
make_cstring (const struct string *str, char *toto, size_t len);
struct string mystring={PTR_NULL}; char mycstring[64];
make_string(&mystring,"hello world");
make_cstring(&mystring,mycstring,64);log_output(mycstring); => "hello world"
int make_string_l (struct string *str, const char *toto, size_t len);
struct string mystring={PTR_NULL};
make_string_l(&mystring,"hello world",4);
log_output(mystring.str); => "hell"
int make_string_url (struct string *str, const char *toto, size_t len);
struct string mystring={PTR_NULL};
make_string_url(&mystring,"hello world",8);
log_output(mystring.str); => "hello%wo"
int make_string_from_url (struct string *str, const char *toto, size_t len);
struct string mystring={PTR_NULL};
make_string_from_url(&mystring,"hello%world",8);
log_output(mystring.str); => "hello wo"
struct host_def *make_host_def(const char *host, unsigned short port);
struct host_def *myhost=PTR_NULL;
myhost=make_host_def("google.com",80);
void free_host_def (struct host_def *host);
struct host_def *myhost=PTR_NULL;
myhost=make_host_def("google.com",80);
free_host_dest(myhost)
int clone_string (struct string *str, const struct string *str1);
struct string mystring={PTR_NULL};
struct string myclonedstring={PTR_NULL};
make_string(&mystring,"hello world");
clone_string(&myclonedstring,&mystring);
int make_string_from_uint(struct string *str, size_t i);
struct string mystring={PTR_NULL};
make_string_from_uint(&mystring,42);
log_output(mystring.str); => "42"
cat_string (struct string *str, const struct string *src);
struct string mystring={PTR_NULL};
struct string myotherstring={PTR_NULL};
make_string(&mystring,"hello ");
make_string(&myotherstring,"world");
cat_string(&mystring,&myotherstring);
log_output(mystring.str); => "hello world"
cat_cstring (struct string *str, const char *src);
struct string mystring={PTR_NULL};
make_string(&mystring,"hello ");
cat_cstring(&mystring,"world");
log_output(mystring.str); => "hello world"
cat_ncstring (struct string *str, const char *src, size_t src_len);
struct string mystring={PTR_NULL};
make_string(&mystring,"hello ");
cat_ncstring(&mystring,"world",3);
log_output(mystring.str); => "hello wor"
cat_cstring_p (struct string *str, const char *src);
struct string mystring={PTR_NULL};
make_string(&mystring,"hello");
cat_cstring_p(&mystring,"world");
log_output(mystring.str); => "hello/world" or "hello\world"
cat_ncstring_p (struct string *str, const char *src, size_t src_len);
struct string mystring={PTR_NULL};
make_string(&mystring,"hello");
cat_ncstring_p(&mystring,"world",3);
log_output(mystring.str); => "hello/wor" or "hello\wor"
strcat_uint (struct string *str, size_t i);
struct string mystring={PTR_NULL};
make_string(&mystring,"hello ");
strcat_uint(&mystring,42);
log_output(mystring.str); => "hello 42"
strcat_int (struct string *str, int i);
struct string mystring={PTR_NULL};
make_string(&mystring,"hello ");
strcat_int(&mystring,-42);
log_output(mystring.str); => "hello -42"
strcat_float (struct string *str, double f);
struct string mystring={PTR_NULL};
make_string(&mystring,"hello ");
strcat_float(&mystring,3.1459);
log_output(mystring.str); => "hello 3.1459"
The base api to manipulate files is found in libcon/include/fsio.h
int stat_file(const char *path);
if(stat_file("myfile.txt")==0)
log_output("entry exist in the file system.");
int get_file(const char *path, unsigned char **data, size_t *data_len);
unsigned char *data; size_t size;
if(get_file("myfile.txt",&data,&size)>0)
{
log_output(data);
free_c(data);
}
int put_file(const char *path, void *data, size_t data_len);
put_file("myfile.txt", "hello world", 12);
size_t file_size(const char *path);
Return size of the file.
size_t size;
size=file_size("myfile.txt");
int append_file(const char *path, const void *data, size_t data_len);
Return size of the file.
put_file("myfile.txt","hello ",6);
append_file("myfile.txt","world",5);
int truncate_file(const char *path, size_t ofset, const void *data, size_t data_len);
Truncate file to specified length, and optionally append new data at this position.
put_file("myfile.txt","hello ",6);
truncate_file("myfile.txt",4," world",3)
"myfile.txt" => "hell wor"
truncate_file("myfile.txt",4,PTR_NULL,0)
"myfile.txt" => "hell"
int move_file(const char *ipath,const char *opath);
Move file from source path to destination path.
move_file("myfile.txt","myotherfile.txt");
int del_file(const char *path);
Remove file from file system.
del_file("myfile.txt");
ctime_t get_time_c(void);
Get current time as unix timestamp in second.
ctime_t mytime;
mytime=get_time_c();
ctime_t get_system_time_c(void);
Get system high precision timer as millisec elapsed since boot.
ctime_t mytime;
get_system_time_c(&mytime);
int set_ftime(const char *path, ctime_t time);
Set file time
ctime_t mytime;
mytime=gettime_c();
set_ftime("myfile.txt",mytime);
int set_ftime(const char *path, ctime_t *time);
Set file time
ctime_t mytime;
get_ftime("myfile.txt",&mytime);
int create_dir(const char *path);
Create new directory on the local file system
create_dir("mynewdir");
int del_dir(const char *path);
Remove empty directory from the local file system
del_dir("mynewdir");
int rm_dir(const char *dir);
Remove directory and sub files / empty directory from the local file system
rm_dir("mynewdir");
int get_sub_dirs(const char *path, struct string *dir_list);
Get list of subdirectory from a specified path.
struct string dir_list={PTR_NULL};
get_sub_dirs("mynewdir",&dir_list);
free_string(&dir_list);
int get_sub_files(const char *path, struct string *file_list);
Get list of file in the directory at specified path.
struct string file_list={PTR_NULL};
get_sub_files("mynewdir",&file_list);
free_string(&file_list);
set_cwd(const char *path);
Set current working directory.
set_cwd("mynewdir");
get_cwd (char *path, size_t len);
Get current working directory.
char mycwd[256];
get_cwd(mycwd,256);
void console_print(const char *msg);
Output string to stdio/console
console_print("hello world");
int log_output(const char *data);
Output string to log
log_output("hello world");
The base api to manipulate sockect is found in libcon/include/connect.h
It support both blocking and non blocking io, and uPnp.
int network_init ();
network_init();
int network_free();
network_free();
get_if(const char *gw_ip, struct string *name, struct string *ip);
struct string if_name={PTR_NULL},if_ip={PTR_NULL};;
get_if("192.168.1.1", &if_name, &if_ip);
struct con *do_connect(const struct host_def *host);
struct host_def *myhost=PTR_NULL;
struct con *mycon;
myhost=make_host_def("google.com",80);
mycon=do_connect(myhost);
char *readline(struct con *Con, ctime_t timeout);
struct host_def *myhost=PTR_NULL;
struct con *mycon;
myhost=make_host_def("google.com",80);
mycon=do_connect(myhost);
readline(mycon,10);
int read_data(struct con *Con, size_t max);
struct host_def *myhost=PTR_NULL;
struct con *mycon;
int size;
myhost=make_host_def("google.com",80);
mycon=do_connect(myhost);
size=read_data(mycon,4096);
int read_av_data(struct con *Con, size_t max);
struct host_def *myhost=PTR_NULL;
struct con *mycon;
int size;
myhost=make_host_def("google.com",80);
mycon=do_connect(myhost);
size=read_av_data(mycon,4096);
int send_data(struct con *Con, unsigned char *data, size_t len);
struct host_def *myhost=PTR_NULL;
struct con *mycon;
int size;
struct mystring={PTR_NUL};
myhost=make_host_def("google.com",80);
mycon=do_connect(myhost);
make_string(&mystring,"hello world");
size=send_data(mycon,mystring.str,mystring.len);
int send_data_av(struct con *Con, unsigned char *data, size_t len);
struct host_def *myhost=PTR_NULL;
struct con *mycon;
int size;
struct mystring={PTR_NUL};
myhost=make_host_def("google.com",80);
mycon=do_connect(myhost);
make_string(&mystring,"hello world");
size=send_data_av(mycon,mystring.str,mystring.len);
const struct string* get_con_error(struct con *Con);
struct host_def *myhost=PTR_NULL;
struct con *mycon;
struct string *error=PTR_NUL;
myhost=make_host_def("google.com",80);
mycon=do_connect(myhost);
error=get_con_error(mycon);
int con_consume_data(struct con *Con, size_t mov_len);
struct host_def *myhost=PTR_NULL;
struct con *mycon;
struct string *data=PTR_NUL;
myhost=make_host_def("google.com",80);
mycon=do_connect(myhost);
readline(mycon,10);
data=get_con_lastline(mycon);
con_consume_data(mycon,data->len);
int reconnect(struct con *mycon);
struct host_def *myhost=PTR_NULL;
struct con *mycon;
int size;
myhost=make_host_def("google.com",80);
mycon=do_connect(myhost);
size=send_data(mycon,"hello",5);
if(size<0){reconnect(mycon);}
struct con * open_port(const char *my_addr, unsigned short port);
struct con *mycon;
int size;
mycon=open_port("127.0.0.1",80);
struct con *do_get_incoming(struct con *listen_con, unsigned int time_out);
struct con *mycon;
>struct con *netcon;
int size;
mycon=open_port("127.0.0.1",80);
netcon=do_get_incoming(mycon,10)
void con_close(struct con *Con);
struct con *mycon;
struct con *netcon;
int size;
mycon=open_port("127.0.0.1",80);
netcon=do_get_incoming(mycon,10)
size=read_data(netcon,1024);
con_close(netcon);
The base api to manipulate modules is found in libcon/include/tpo_mod.h
void tpo_mod_init(tpo_mod_file *driver);
tpo_mod_file mod;
tpo_mod_init(&mod);
int tpo_mod_load_tpo(mem_stream *file_stream, tpo_mod_file *tpo_file, unsigned int imp_func_addr);
tpo_mod_file mod;
struct mem_stream modstrm;
get_file_to_memstream("modz/libbase.tpo", &modstrm);
tpo_mod_init(&mod);
tpo_mod_load_tpo(&modstrm,&mod, 0);
mem_stream_close(&modstrm);
void_func_ptr tpo_mod_get_exp_addr(mem_stream *file_stream, const char *sym)
struct mem_stream modstrm;
void_func_ptr my_func;
get_file_to_memstream("modz/libbase.tpo", &modstrm);
my_func=tpo_mod_get_exp_addr(&modstrm,"my_func");
void register_tpo_exports(tpo_mod_file *tpo_mod, const char *mod_name);
struct mem_stream modstrm;
get_file_to_memstream("modz/libbase.tpo", &modstrm);
tpo_mod_init(&mod);
tpo_mod_load_tpo(&modstrm,&mod, 0);
mem_stream_close(&modstrm);
register_tpo_exports(&mod,"my_mod");
int load_module(const char *file, const char *mod_name, tpo_mod_file *mod);
tpo_mod_file mod;
load_module("modz/libbase.tpo","libbase",&mod);
void_func_ptr get_tpo_mod_exp_addr_name(const tpo_mod_file *tpo_mod, const char *name, unsigned int deco_type);
tpo_mod_file mod;
void_func_ptr my_func;
tpo_mod_init(&mod);
load_module("modz/libbase.tpo", &mod);
my_func=tpo_mod_get_exp_addr(&mod,"my_func",0);
int execute_script_mod_call(tpo_mod_file *tpo_mod, const char *method);
tpo_mod_file mod;
tpo_mod_init(&mod);
load_module("modz/libbase.tpo", &mod);
execute_script_mod_call(&mod,"my_func");
execute_script_mod_rcall(tpo_mod_file *tpo_mod, const char *method, mem_zone_ref_ptr input);
tpo_mod_file mod;
mem_zone_ref input={PTR_NULL}
tpo_mod_init(&mod);
load_module("modz/libbase.tpo", &mod);
tree_manager_create_node("param",NODE_GFX_INT,&input);
tree_manager_write_node_dword(&input,0,42);
execute_script_mod_rcall(&mod,"my_func",&input);
execute_script_mod_rcall(tpo_mod_file *tpo_mod, const char *method, mem_zone_ref_ptr input, mem_zone_ref_ptr output);
tpo_mod_file mod;
mem_zone_ref input={PTR_NULL},output={PTR_NULL};
tpo_mod_init(&mod);
load_module("modz/libbase.tpo", &mod);
tree_manager_create_node("param",NODE_GFX_INT,&input);
tree_manager_write_node_dword(&input,0,42);
execute_script_mod_rwcall(&mod,"my_func",&input,&output);
The source code of the nodix blockchain launcher loading the nodix.node script is on the github Nodix launcher on github
#include <base/std_def.h>
#include <base/std_mem.h>
#include <base/mem_base.h>
#include <base/std_str.h>
#include <strs.h>
#include <connect.h>
#include <mem_stream.h>
#include <tpo_mod.h>
#include <fsio.h>
typedef int C_API_FUNC app_func(mem_zone_ref_ptr params);
typedef void C_API_FUNC tree_manager_init_func(size_t size);
typedef int C_API_FUNC load_script_func(const char *file, mem_zone_ref_ptr script_vars, unsigned int opt);
typedef int C_API_FUNC resolve_script_var_func(mem_zone_ref_ptr script_vars, mem_zone_ref_ptr script_proc, const char *var_path, unsigned int var_type, mem_zone_ref_ptr out_var, mem_zone_ref_ptr pout_var);
typedef int C_API_FUNC get_script_var_value_str_func(mem_zone_ref_ptr global_vars, const char *var_path, struct string *out, unsigned int radix);
typedef int C_API_FUNC get_script_var_value_ptr_func(mem_zone_ref_ptr global_vars, const char *var_path, mem_ptr *out);
typedef int C_API_FUNC execute_script_proc_func(mem_zone_ref_ptr global_vars, mem_zone_ref_ptr proc);
typedef app_func *app_func_ptr;
typedef load_script_func *load_script_func_ptr;
typedef resolve_script_var_func *resolve_script_var_func_ptr;
typedef get_script_var_value_str_func *get_script_var_value_str_func_ptr;
typedef get_script_var_value_ptr_func *get_script_var_value_ptr_func_ptr;
typedef execute_script_proc_func *execute_script_proc_func_ptr;
typedef tree_manager_init_func *tree_manager_init_func_ptr;
load_script_func_ptr load_script = PTR_INVALID;
resolve_script_var_func_ptr resolve_script_var = PTR_INVALID;
get_script_var_value_str_func_ptr get_script_var_value_str = PTR_INVALID;
get_script_var_value_ptr_func_ptr get_script_var_value_ptr = PTR_INVALID;
execute_script_proc_func_ptr execute_script_proc = PTR_INVALID;
tree_manager_init_func_ptr tree_manager_init = PTR_INVALID;
app_func_ptr app_init = PTR_INVALID , app_start = PTR_INVALID , app_loop = PTR_INVALID , app_stop = PTR_INVALID;
tpo_mod_file libbase_mod = { 0xDEF00FED };
int main( int argc , const char ** argv)
{
struct string node_name = { PTR_NULL },data_dir={ PTR_NULL};
mem_zone_ref params = { PTR_NULL }, script_vars = { PTR_NULL }, init_node_proc = { PTR_NULL };
const_mem_ptr *params_ptr;
tpo_mod_file *nodix_mod;
int done = 0,n;
init_mem_system ();
init_default_mem_area (24 * 1024 * 1024);
set_exe_path ();
network_init ();
create_def();
tpo_mod_init (&libbase_mod);
load_module ("modz/libbase.tpo" , "libbase" , &libbase_mod);
load_script = ( load_script_func_ptr )get_tpo_mod_exp_addr_name(&libbase_mod, "load_script" , 0);
resolve_script_var = ( resolve_script_var_func_ptr )get_tpo_mod_exp_addr_name(&libbase_mod, "resolve_script_var" , 0);
get_script_var_value_str = ( get_script_var_value_str_func_ptr )get_tpo_mod_exp_addr_name(&libbase_mod, "get_script_var_value_str" , 0);;
get_script_var_value_ptr = ( get_script_var_value_ptr_func_ptr )get_tpo_mod_exp_addr_name(&libbase_mod, "get_script_var_value_ptr" , 0);;
execute_script_proc = ( execute_script_proc_func_ptr )get_tpo_mod_exp_addr_name(&libbase_mod, "execute_script_proc" , 0);;
tree_manager_init = ( tree_manager_init_func_ptr )get_tpo_mod_exp_addr_name(&libbase_mod, "tree_manager_init" , 0);;
tree_manager_init (16 * 1024 * 1024);
load_script ( "nodix.node" , &script_vars,3);
if (!get_script_var_value_str(&script_vars, "configuration.name" , &node_name, 0))
make_string(&node_name, "nodix");
if (get_script_var_value_str(&script_vars, "SelfNode.data_dir" , &data_dir, 0))
{
set_data_dir (&data_dir, "nodix");
free_string (&data_dir);
}
else
{
if (!set_home_path(node_name.str))
{
console_print( "could not set home dir 'nodix' \n" );
return 0;
}
}
get_script_var_value_ptr(&script_vars, "nodix.mod_ptr" , ( mem_ptr *)&nodix_mod);
resolve_script_var (&script_vars, PTR_NULL , "init_node" , 0xFFFFFFFF, &init_node_proc, PTR_NULL);
app_init = ( app_func_ptr )get_tpo_mod_exp_addr_name(nodix_mod, "app_init" , 0);
app_start = ( app_func_ptr )get_tpo_mod_exp_addr_name(nodix_mod, "app_start" , 0);
app_loop = ( app_func_ptr )get_tpo_mod_exp_addr_name(nodix_mod, "app_loop" , 0);
app_stop = ( app_func_ptr )get_tpo_mod_exp_addr_name(nodix_mod, "app_stop" , 0);
if (!app_init(&script_vars))
{
console_print( "could not initialize app " );
console_print(nodix_mod->name);
console_print("\n");
return 0;
}
if (!execute_script_proc(&script_vars, &init_node_proc))
{
console_print( "could not execute script initialization routine." );
return 0;
}
if (daemonize(node_name.str) <= 0)
{
console_print( "daemonize failed \n" );
return 0;
}
if ( argc > 1)
{
allocate_new_zone(0, argc*sizeof(mem_ptr ), ¶ms);
for (n = 0; n < ( argc -1); n++)
{
params_ptr = get_zone_ptr(¶ms, n* sizeof(mem_ptr));
(*params_ptr) = argv[n+1];
}
params_ptr = get_zone_ptr(¶ms, n* sizeof(mem_ptr));
(*params_ptr) = PTR_NULL;
}
if (!app_start(¶ms))
{
console_print( "could not start app " );
console_print(nodix_mod->name);
console_print("\n");
return 0;
}
while (isRunning())
{
app_loop(PTR_NULL);
}
app_stop(PTR_NULL);
}