From 87cd84ba18db05172ea8de336d1f4213a86ac077 Mon Sep 17 00:00:00 2001
From: "Dmitriy A. Gerasimov" <dmitriy.gerasimov@demlabs.net>
Date: Mon, 4 May 2020 01:49:05 +0700
Subject: [PATCH] [+] Added CELLFRAME_MODULES global variable to set list of
 modules to build with [*] Removed cyclic depdendece because of dap_dns_server

---
 CMakeLists.txt                                |  93 ++-
 dap-sdk/CMakeLists.txt                        |  33 +-
 dap-sdk/net/server-udp/CMakeLists.txt         |   4 +-
 dap-sdk/net/stream/ch/CMakeLists.txt          |   2 +-
 modules/CMakeLists.txt                        | 110 ++-
 modules/net/CMakeLists.txt                    |   2 +-
 .../net}/dap_dns_server.c                     | 672 +++++++++---------
 .../net}/include/dap_dns_server.h             | 244 +++----
 8 files changed, 644 insertions(+), 516 deletions(-)
 rename {dap-sdk/net/server-udp => modules/net}/dap_dns_server.c (97%)
 rename {dap-sdk/net/server-udp => modules/net}/include/dap_dns_server.h (97%)

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 6ab168b10d..52e30a7ca7 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -2,10 +2,20 @@ project(cellframe-sdk C)
 cmake_minimum_required(VERSION 2.8)
 
 set(CMAKE_C_STANDARD 11)
-set(CELLFRAME_SDK_NATIVE_VERSION "2.0-2")
+set(CELLFRAME_SDK_NATIVE_VERSION "2.0-3")
 include(cmake/OS_Detection.cmake)
 add_definitions ("-DCELLFRAME_SDK_VERSION=\"${CELLFRAME_SDK_NATIVE_VERSION}\"")
 
+set(DAPSDK_MODULES "")
+
+if (CELLFRAME_MODULES MATCHES "core")
+    SET(DAPSDK_MODULES "${DAPSDK_MODULES} core crypto")
+endif()
+
+if (CELLFRAME_MODULES MATCHES "network")
+    set(DAPSDK_MODULES "${DAPSDK_MODULES} network-core network-client network-server")
+endif()
+
 add_subdirectory(dap-sdk)
 add_subdirectory(3rdparty/monero_crypto)
 add_subdirectory(3rdparty/cuttdb)
@@ -13,14 +23,79 @@ add_subdirectory(modules/)
 
 add_library(${PROJECT_NAME} STATIC cellframe-sdk.c)
 
-set(CELLFRAME_LIBS dap_core dap_crypto dap_crypto dap_server_core dap_enc_server dap_udp_server dap_session
-            dap_enc_server dap_stream dap_stream_ch_chain dap_stream_ch_chain_net
-            dap_stream_ch_chain_net_srv dap_chain dap_chain_crypto dap_client
-            dap_chain_cs_dag dap_chain_cs_dag_poa dap_chain_cs_dag_pos
-            dap_chain_net dap_chain_net_srv
-            dap_chain_net_srv_vpn dap_chain_net_srv_app  dap_chain_net_srv_app_db
-            dap_chain_net_srv_datum  dap_chain_net_srv_datum_pool
-            dap_chain_wallet dap_chain_global_db dap_chain_mempool dap_chain_cs_none m magic pthread)
+# init libs
+set(CELLFRAME_LIBS "")
+
+# Core libs from dap-sdk
+if (CELLFRAME_MODULES MATCHES "core")
+    message("[+] Module 'core'")
+    set(CELLFRAME_LIBS ${CELLFRAME_LIBS} dap_core dap_crypto m pthread)
+endif()
+
+# General chain libs
+if (CELLFRAME_MODULES MATCHES "chains")
+    message("[+] Module 'chains'")
+    set(CELLFRAME_LIBS ${CELLFRAME_LIBS} dap_chain_common dap_chain dap_chain_global_db dap_chain_wallet dap_chain_crypto)
+endif()
+
+# Networking
+if (CELLFRAME_MODULES MATCHES "network")
+    message("[+] Module 'network'")
+    set(CELLFRAME_LIBS ${CELLFRAME_LIBS} dap_server_core dap_enc_server dap_http_server dap_udp_server dap_session 
+	dap_stream dap_stream_ch dap_client dap_stream_ch_chain dap_stream_ch_chain_net dap_chain_net dap_chain_mempool magic)
+endif()
+
+# Chain net services
+if (CELLFRAME_MODULES MATCHES "srv-" )
+    set(CELLFRAME_LIBS ${CELLFRAME_LIBS} dap_chain_net_srv dap_stream_ch_chain_net_srv)
+endif()
+
+# DAG based consensus(es)
+if (CELLFRAME_MODULES MATCHES "cs-dag-" )
+    set(CELLFRAME_LIBS ${CELLFRAME_LIBS} dap_chain_cs_dag)
+endif()
+
+# PoA consensus for DAG
+if (CELLFRAME_MODULES MATCHES "cs-dag-poa")
+    message("[+] Module 'cs-dag-poa'")
+    set(CELLFRAME_LIBS ${CELLFRAME_LIBS} dap_chain_cs_dag_poa)
+endif()
+
+# PoS consensus for DAG
+if (CELLFRAME_MODULES MATCHES "cs-dag-pos")
+    message("[+] Module 'cs-dag-pos'")
+    set(CELLFRAME_LIBS ${CELLFRAME_LIBS} dap_chain_cs_dag_pos)
+endif()
+
+# No-consensus
+if (CELLFRAME_MODULES MATCHES "cs-none")
+    message("[+] Module 'cs-none'")
+    set(CELLFRAME_LIBS ${CELLFRAME_LIBS} dap_chain_cs_none)
+endif()
+
+# Enable service Application
+if (CELLFRAME_MODULES MATCHES "srv-app")
+    message("[+] Module 'srv-app'")
+    set(CELLFRAME_LIBS ${CELLFRAME_LIBS} dap_chain_net_srv_app )
+endif()
+
+# Enable service Application DB
+if (CELLFRAME_MODULES MATCHES "srv-app-db")
+    message("[+] Module 'srv-app-db'")
+    set(CELLFRAME_LIBS ${CELLFRAME_LIBS} dap_chain_net_srv_app_db )
+endif()
+
+# Enable service datum process
+if (CELLFRAME_MODULES MATCHES "srv-datum")
+    message("[+] Module 'srv-datum'")
+    set(CELLFRAME_LIBS ${CELLFRAME_LIBS} dap_chain_net_srv_datum )
+endif()
+
+# Enable service VPN
+if (CELLFRAME_MODULES MATCHES "srv-vpn")
+    message("[+] Module 'srv-vpn'")
+    set(CELLFRAME_LIBS ${CELLFRAME_LIBS} dap_chain_net_srv_vpn )
+endif()
 
 if (WIN32)
     set(CELLFRAME_LIBS ${CELLFRAME_LIBS} KERNEL32 USER32 SHELL32 WINMM GDI32 ADVAPI32
diff --git a/dap-sdk/CMakeLists.txt b/dap-sdk/CMakeLists.txt
index c8f8276289..89f2652ec8 100644
--- a/dap-sdk/CMakeLists.txt
+++ b/dap-sdk/CMakeLists.txt
@@ -1,12 +1,25 @@
-# Core
-add_subdirectory(core)
+# Core 
+if (DAPSDK_MODULES MATCHES "core")
+    # Core
+    add_subdirectory(core)
+endif()
+if (DAPSDK_MODULES MATCHES "crypto")
+    # Cryptography
+    add_subdirectory(crypto)
+endif()
 
-# Cryptography
-add_subdirectory(crypto)
+# Networking core
+if (DAPSDK_MODULES MATCHES "network-core")
+    add_subdirectory(net/core)
+    add_subdirectory(net/stream)
+endif()
+# Networking client
+if (DAPSDK_MODULES MATCHES "network-client")
+    add_subdirectory(net/client)
+endif()
 
-# Networking
-add_subdirectory(net/core)
-add_subdirectory(net/client)
-add_subdirectory(net/server)
-add_subdirectory(net/server-udp)
-add_subdirectory(net/stream)
+# Networking server
+if (DAPSDK_MODULES MATCHES "network-server")
+    add_subdirectory(net/server)
+    add_subdirectory(net/server-udp)
+endif()
diff --git a/dap-sdk/net/server-udp/CMakeLists.txt b/dap-sdk/net/server-udp/CMakeLists.txt
index 94dda44efb..f99bd6023d 100644
--- a/dap-sdk/net/server-udp/CMakeLists.txt
+++ b/dap-sdk/net/server-udp/CMakeLists.txt
@@ -11,9 +11,9 @@ if(WIN32)
   #include_directories(../3rdparty/curl/include/)
 endif()
 
-add_library(${PROJECT_NAME} STATIC ${DAP_UDP_SERVER_SRCS})
+add_library(${PROJECT_NAME} STATIC ${DAP_UDP_SERVER_SRCS} ${DAP_UDP_SERVER_HEADERS})
 
-target_link_libraries(${PROJECT_NAME} dap_core dap_server_core dap_chain_net)
+target_link_libraries(${PROJECT_NAME} dap_core dap_server_core)
 
 target_include_directories(${PROJECT_NAME} INTERFACE .)
 target_include_directories(${PROJECT_NAME} PUBLIC include)
diff --git a/dap-sdk/net/stream/ch/CMakeLists.txt b/dap-sdk/net/stream/ch/CMakeLists.txt
index 8a2c0d822b..657546fb9d 100644
--- a/dap-sdk/net/stream/ch/CMakeLists.txt
+++ b/dap-sdk/net/stream/ch/CMakeLists.txt
@@ -11,7 +11,7 @@ endif()
 
 add_library(${PROJECT_NAME} STATIC ${DAP_STREAM_CH_SRCS} ${DAP_STREAM_CH_HDRS})
 
-target_link_libraries(dap_stream_ch dap_core dap_crypto dap_stream)
+target_link_libraries(dap_stream_ch dap_core dap_crypto dap_udp_server dap_stream )
 
 target_include_directories(dap_stream_ch INTERFACE .)
 target_include_directories(${PROJECT_NAME} PUBLIC include)
diff --git a/modules/CMakeLists.txt b/modules/CMakeLists.txt
index d9dbd649e8..7b810fc785 100644
--- a/modules/CMakeLists.txt
+++ b/modules/CMakeLists.txt
@@ -1,37 +1,77 @@
-add_subdirectory(app-cli)
-add_subdirectory(chain)
-add_subdirectory(common)
-add_subdirectory(mining)
-add_subdirectory(wallet)
-add_subdirectory(mempool)
-add_subdirectory(net)
-add_subdirectory(net/srv)
-add_subdirectory(global-db)
-
-# Consensus types
-add_subdirectory(type/dag)
-#add_subdirectory(type/block)
-
-# Consensuses
-add_subdirectory(consensus/none)
-#add_subdirectory(consensus/block-pow)
-#add_subdirectory(consensus/block-poa)
-add_subdirectory(consensus/dag-pos)
-add_subdirectory(consensus/dag-poa)
-
-# Stream channels
-add_subdirectory(channel/chain)
-add_subdirectory(channel/chain-net)
-add_subdirectory(channel/chain-net-srv)
-
-# Services 
-if(NOT (WIN32))
-  add_subdirectory(service/vpn)
-endif()
-
-add_subdirectory(service/app)
-add_subdirectory(service/app-db)
-add_subdirectory(service/datum)
-add_subdirectory(service/mining-pool)
+# Core
+if (CELLFRAME_MODULES MATCHES "core")
+    add_subdirectory(common)
+    add_subdirectory(app-cli)
+endif()
+
+# Chains
+if (CELLFRAME_MODULES MATCHES "chains")
+    add_subdirectory(chain)
+    add_subdirectory(wallet)
+    add_subdirectory(global-db)
+endif()
 
+# Network
+if (CELLFRAME_MODULES MATCHES "network")
+    add_subdirectory(mempool)
+    add_subdirectory(net)
+    # Stream channels
+    add_subdirectory(channel/chain)
+    add_subdirectory(channel/chain-net)
+    add_subdirectory(channel/chain-net-srv)
+endif()
 
+# Mining
+if (CELLFRAME_MODULES MATCHES "mining")
+    add_subdirectory(mining)
+endif()
+
+# Network services
+if (CELLFRAME_MODULES MATCHES "srv")
+    add_subdirectory(net/srv)
+endif()
+
+# Consensus type dag
+if (CELLFRAME_MODULES MATCHES "cs-dag")
+    add_subdirectory(type/dag)
+endif()
+
+# Consensus type dag
+if (CELLFRAME_MODULES MATCHES "cs-block")
+    add_subdirectory(type/block)
+endif()
+
+# No consensus
+if (CELLFRAME_MODULES MATCHES "cs-none")
+    add_subdirectory(consensus/none)
+endif()
+
+# DAG PoA
+if (CELLFRAME_MODULES MATCHES "cs-dag-poa")
+    add_subdirectory(consensus/dag-poa)
+endif()
+
+# DAG PoS
+if (CELLFRAME_MODULES MATCHES "cs-dag-pos")
+    add_subdirectory(consensus/dag-pos)
+endif()
+
+# Service App
+if (CELLFRAME_MODULES MATCHES "srv-app")
+    add_subdirectory(service/app)
+endif()
+
+# Service App DB
+if (CELLFRAME_MODULES MATCHES "srv-app-db")
+    add_subdirectory(service/app-db)
+endif()
+
+# Service Datum
+if (CELLFRAME_MODULES MATCHES "srv-datum")
+    add_subdirectory(service/datum)
+endif()
+
+# Service VPN
+if (CELLFRAME_MODULES MATCHES "srv-vpn")
+    add_subdirectory(service/vpn)
+endif()
diff --git a/modules/net/CMakeLists.txt b/modules/net/CMakeLists.txt
index 2f19f6a87b..52441d852e 100644
--- a/modules/net/CMakeLists.txt
+++ b/modules/net/CMakeLists.txt
@@ -4,7 +4,7 @@ project (dap_chain_net)
 
 file(GLOB DAP_CHAIN_NET_SRCS *.c)
 
-file(GLOB DAP_CHAIN_NET_HEADERS *.h)
+file(GLOB DAP_CHAIN_NET_HEADERS include/*.h)
 
 #if (ANDROID)
 #    set(DAP_CHAIN_NET_HEADERS ${DAP_CHAIN_NET_HEADERS}
diff --git a/dap-sdk/net/server-udp/dap_dns_server.c b/modules/net/dap_dns_server.c
similarity index 97%
rename from dap-sdk/net/server-udp/dap_dns_server.c
rename to modules/net/dap_dns_server.c
index a93c8f55cd..64322e2a78 100644
--- a/dap-sdk/net/server-udp/dap_dns_server.c
+++ b/modules/net/dap_dns_server.c
@@ -1,336 +1,336 @@
-/*
- * Authors:
- * Roman Khlopkov <roman.khlopkov@demlabs.net>
- * DeM Labs Inc.   https://demlabs.net
- * DeM Labs Open source community https://gitlab.demlabs.net
- * Copyright  (c) 2017-2020
- * 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_dns_server.h"
-#include "dap_udp_server.h"
-#include "dap_udp_client.h"
-#include "dap_client_remote.h"
-#include "dap_common.h"
-#include "dap_chain_net.h"
-#include "dap_chain_node.h"
-#include "dap_string.h"
-#include "dap_chain_global_db.h"
-#include "dap_chain_global_db_remote.h"
-
-#define UNUSED(x) (void)(x)
-#define LOG_TAG "dap_dns_server"
-
-static dap_dns_server_t *s_dns_server;
-static char s_root_alias[] = "dnsroot";
-
-/**
- * @brief dap_dns_buf_init Initialize DNS parser buffer
- * @param buf DNS buffer structure
- * @param msg DNS message
- * @return none
- */
-void dap_dns_buf_init(dap_dns_buf_t *buf, char *msg) {
-    buf->data = msg;
-    buf->ptr = 0;
-}
-
-/**
- * @brief dap_dns_buf_get_uint16 Get uint16 from network order
- * @param buf DNS buffer structure
- * @return uint16 in host order
- */
-uint16_t dap_dns_buf_get_uint16(dap_dns_buf_t *buf) {
-    char c;
-    c = buf->data[buf->ptr++];
-    return c << 8 | buf->data[buf->ptr++];
-}
-
-/**
- * @brief dap_dns_buf_put_uint16 Put uint16 to network order
- * @param buf DNS buffer structure
- * @param val uint16 in host order
- * @return none
- */
-void dap_dns_buf_put_uint16(dap_dns_buf_t *buf, uint16_t val) {
-    buf->data[buf->ptr++] = val >> 8;
-    buf->data[buf->ptr++] = val;
-}
-
-/**
- * @brief dap_dns_buf_put_uint32 Put uint32 to network order
- * @param buf DNS buffer structure
- * @param val uint32 in host order
- * @return none
- */
-void dap_dns_buf_put_uint32(dap_dns_buf_t *buf, uint32_t val) {
-    dap_dns_buf_put_uint16(buf, val >> 16);
-    dap_dns_buf_put_uint16(buf, val);
-}
-
-uint32_t dap_dns_resolve_hostname(char *str) {
-    log_it(L_DEBUG, "DNS parser retrieve hostname %s", str);
-    dap_chain_net_t *l_net = dap_chain_net_by_name("kelvin-testnet");
-    // get nodes list from global_db
-    dap_global_db_obj_t *l_objs = NULL;
-    size_t l_nodes_count = 0;
-    // read all node
-    l_objs = dap_chain_global_db_gr_load(l_net->pub.gdb_nodes, &l_nodes_count);
-    if(!l_nodes_count || !l_objs)
-        return 0;
-    size_t l_node_num = rand() % l_nodes_count;
-    dap_chain_node_info_t *l_node_info = (dap_chain_node_info_t *) l_objs[l_node_num].value;
-    uint32_t addr = l_node_info->hdr.ext_addr_v4.s_addr;
-    dap_chain_global_db_objs_delete(l_objs, l_nodes_count);
-    log_it(L_DEBUG, "DNS resolver find ip %d.%d.%d.%d", addr & 0xFF, (addr >> 8) & 0xFF, (addr >> 16) & 0xFF, (addr >> 24) & 0xFF);
-    return addr;
-}
-
-/**
- * @brief dap_dns_zone_register Register DNS zone and set callback to handle it
- * @param zone Name of zone to register
- * @param callback Callback to handle DNS zone
- * @return 0 if success, else return error code
- */
-int dap_dns_zone_register(char *zone, dap_dns_zone_callback_t callback) {
-    dap_dns_zone_hash_t *new_zone;
-    HASH_FIND_STR(s_dns_server->hash_table, zone, new_zone);
-    if (new_zone == NULL) {      // zone is not present
-      new_zone = DAP_NEW(dap_dns_zone_hash_t);
-      new_zone->zone = dap_strdup(zone);
-      HASH_ADD_KEYPTR(hh, s_dns_server->hash_table, new_zone->zone, strlen(new_zone->zone), new_zone);
-    }                           // if zone present, just reassign callback
-    new_zone->callback = callback;
-    return DNS_ERROR_NONE;
-}
-
-/**
- * @brief dap_dns_zone_unregister Unregister DNS zone
- * @param zone Name of zone to unregister
- * @return 0 if success, else return error code
- */
-int dap_dns_zone_unregister(char *zone) {
-    dap_dns_zone_hash_t *asked_zone;
-    HASH_FIND_STR(s_dns_server->hash_table, zone, asked_zone);
-    if (asked_zone == NULL) {
-        return DNS_ERROR_NAME;
-    }
-    HASH_DEL(s_dns_server->hash_table, asked_zone);
-    DAP_DELETE(asked_zone->zone);
-    DAP_DELETE(asked_zone);
-    return DNS_ERROR_NONE;
-}
-
-/**
- * @brief dap_dns_zone_find Find callback to registered DNS zone
- * @param hostname Name of host for which the zone callback being searched
- * @return Callback for registered DNS zone, else return NULL
- */
-dap_dns_zone_callback_t dap_dns_zone_find(char *hostname) {
-    dap_dns_zone_hash_t *asked_zone;
-    HASH_FIND_STR(s_dns_server->hash_table, hostname, asked_zone);
-    if (asked_zone == NULL) {
-        if (!strcmp(hostname, &s_root_alias[0])) {
-            return NULL;
-        }
-        char *zone_up = strchr(hostname, '.');
-        if (zone_up++ == NULL) {
-            zone_up = &s_root_alias[0];
-        }
-        return dap_dns_zone_find(zone_up);
-    } else {
-        return asked_zone->callback;
-    }
-    return NULL;
-}
-
-/**
- * @brief dap_dns_client_read Read and parse incoming DNS message, send reply to it
- * @param client DAP client remote structure
- * @param arg Unused
- * @return none
- */
-void dap_dns_client_read(dap_client_remote_t *client, void * arg) {
-    UNUSED(arg);
-    if (client->buf_in_size < DNS_HEADER_SIZE) {        // Bad request
-        return;
-    }
-    dap_dns_buf_t *dns_message = DAP_NEW(dap_dns_buf_t);
-    dap_dns_buf_t *dns_reply = DAP_NEW(dap_dns_buf_t);
-    dns_message->data = DAP_NEW_SIZE(char, client->buf_in_size + 1);
-    dns_message->data[client->buf_in_size] = 0;
-    dap_client_remote_read(client, dns_message->data, client->buf_in_size);
-    dns_message->ptr = 0;
-
-    // Parse incoming DNS message
-    int block_len = DNS_HEADER_SIZE;
-    dns_reply->data = DAP_NEW_SIZE(char, block_len);
-    dns_reply->ptr = 0;
-    uint16_t val = dap_dns_buf_get_uint16(dns_message); // ID
-    dap_dns_buf_put_uint16(dns_reply, val);
-    val = dap_dns_buf_get_uint16(dns_message);          // Flags
-    dns_reply->ptr += sizeof(uint16_t);                 // Put flags later
-    dap_dns_message_flags_t msg_flags;
-    msg_flags.val = val;
-    dap_dns_message_flags_bits_t *flags = &msg_flags.flags;
-    if (flags->qr) {                                     // It's not request
-        goto cleanup;
-    }
-    flags->rcode = DNS_ERROR_NONE;
-    flags->qr = 1;                                       // Response bit set
-    if (flags->tc) {                                     // Truncated messages not supported yet
-        flags->rcode = DNS_ERROR_NOT_SUPPORTED;
-    }
-    flags->ra = 0;                                       // Recursion not supported yet
-    flags->aa = 1;                                       // Authoritative answer
-    uint16_t qdcount = dap_dns_buf_get_uint16(dns_message);
-    dap_dns_buf_put_uint16(dns_reply, qdcount);
-    val = dap_dns_buf_get_uint16(dns_message);          // AN count
-    if (val) {                                          // No other sections should present
-        goto cleanup;
-    }
-    dap_dns_buf_put_uint16(dns_reply, 1);               // 1 answer section
-    val = dap_dns_buf_get_uint16(dns_message);          // NS count
-    if (val) {                                          // No other sections should present
-        goto cleanup;
-    }
-    dap_dns_buf_put_uint16(dns_reply, val);
-    val = dap_dns_buf_get_uint16(dns_message);          // AR count
-    if (val) {                                          // No other sections should present
-        goto cleanup;
-    }
-    dap_dns_buf_put_uint16(dns_reply, val);
-    int dot_count = 0;
-    dap_string_t *dns_hostname = dap_string_new("");
-    for (int i = 0; i < qdcount; i++) {
-        block_len = strlen(&dns_message->data[dns_message->ptr]) + 1 + 2 * sizeof(uint16_t);
-        dns_reply->data = DAP_REALLOC(dns_reply->data, dns_reply->ptr + block_len);
-        memcpy(&dns_reply->data[dns_reply->ptr], &dns_message->data[dns_message->ptr], block_len);
-        dns_reply->ptr += block_len;
-        if (flags->rcode)
-            break;
-        while (dns_message->ptr < dns_reply->ptr - 2 * sizeof(uint16_t)) {
-            uint8_t len = dns_message->data[dns_message->ptr++];
-            if (len > DNS_MAX_DOMAIN_NAME_LEN) {
-                flags->rcode = DNS_ERROR_NAME;
-                break;
-            }
-            if (!len) {
-                break;
-            }
-            if (dot_count) {
-                if (dot_count > 3) {                    // Max three dots allowed
-                    flags->rcode = DNS_ERROR_NAME;
-                    break;
-                }
-                dap_string_append(dns_hostname, ".");
-            }
-            dap_string_append_len(dns_hostname, &dns_message->data[dns_message->ptr], len);
-            dns_message->ptr += len;
-            dot_count++;
-            if (dns_hostname->len >= DNS_MAX_HOSTNAME_LEN) {
-                flags->rcode = DNS_ERROR_NAME;
-                break;
-            }
-        }
-        val = dap_dns_buf_get_uint16(dns_message);      // DNS record type
-        if (val != DNS_RECORD_TYPE_A) {                 // Only host address ipv4
-            flags->rcode = DNS_ERROR_NOT_SUPPORTED;
-            break;
-        }
-        val = dap_dns_buf_get_uint16(dns_message);      // DNS class type
-        if (val != DNS_CLASS_TYPE_IN) {                 // Internet only
-            flags->rcode = DNS_ERROR_NOT_SUPPORTED;
-            break;
-        }
-        if (dns_message->ptr != dns_reply->ptr) {
-            log_it(L_ERROR, "DNS parser pointer unequal, mptr = %u, rptr = %u", dns_message->ptr, dns_reply->ptr);
-        }
-    }
-    // Find ip addr
-    uint32_t ip_addr = 0;
-    if (flags->rcode == DNS_ERROR_NONE) {
-        dap_dns_zone_callback_t callback = dap_dns_zone_find(dns_hostname->str);
-        if (callback) {
-            ip_addr = callback(dns_hostname->str);
-        }
-    }
-    if (ip_addr) {
-    // Compose DNS answer
-        block_len = DNS_ANSWER_SIZE;
-        dns_reply->data = DAP_REALLOC(dns_reply->data, dns_reply->ptr + block_len);
-        val = 0xc000 | DNS_HEADER_SIZE;                // Link to host name
-        dap_dns_buf_put_uint16(dns_reply, val);
-        val = DNS_RECORD_TYPE_A;
-        dap_dns_buf_put_uint16(dns_reply, val);
-        val = DNS_CLASS_TYPE_IN;
-        dap_dns_buf_put_uint16(dns_reply, val);
-        uint32_t ttl = DNS_TIME_TO_LIVE;
-        dap_dns_buf_put_uint32(dns_reply, ttl);
-        val = 4;                                        // RD len for ipv4
-        dap_dns_buf_put_uint16(dns_reply, val);
-        dap_dns_buf_put_uint32(dns_reply, ip_addr);
-    } else if (flags->rcode == DNS_ERROR_NONE) {
-        flags->rcode = DNS_ERROR_NAME;
-    }
-    if (flags->rcode) {
-        dns_reply->data[7] = 0;                         // No answer section
-    }
-    // Set reply flags
-    dns_reply->data[2] = msg_flags.val >> 8;
-    dns_reply->data[3] = msg_flags.val;
-    // Send DNS reply
-    dap_udp_client_write(client, dns_reply->data, dns_reply->ptr);
-    dap_udp_client_ready_to_write(client, true);
-    dap_string_free(dns_hostname, true);
-cleanup:
-    DAP_DELETE(dns_reply->data);
-    DAP_DELETE(dns_message->data);
-    DAP_DELETE(dns_reply);
-    DAP_DELETE(dns_message);
-    return;
-}
-
-void dap_dns_server_start() {
-    s_dns_server = DAP_NEW(dap_dns_server_t);
-    s_dns_server->hash_table = NULL;
-    s_dns_server->instance = dap_udp_server_listen(DNS_LISTEN_PORT);
-    if (!s_dns_server->instance) {
-        log_it(L_ERROR, "Can't star DNS server");
-        return;
-    }
-    s_dns_server->instance->client_read_callback = dap_dns_client_read;
-    s_dns_server->instance->client_read_callback = *dap_dns_client_read;
-    s_dns_server->instance->client_write_callback = NULL;
-    s_dns_server->instance->client_new_callback = NULL;
-    s_dns_server->instance->client_delete_callback = NULL;
-    dap_dns_zone_register(&s_root_alias[0], dap_dns_resolve_hostname);  // root resolver
-    pthread_create(&s_dns_server->udp_thread, NULL, (void *)dap_udp_server_loop, s_dns_server->instance);
-}
-
-void dap_dns_server_stop() {
-    dap_dns_zone_hash_t *current_zone, *tmp;
-    HASH_ITER(hh, s_dns_server->hash_table, current_zone, tmp) {
-        HASH_DEL(s_dns_server->hash_table, current_zone);
-        DAP_DELETE(current_zone->zone);
-        DAP_DELETE(current_zone);
-    }
-    // TODO add code to stop udp_thread
-    dap_udp_server_delete(s_dns_server->instance);
-    DAP_DELETE(s_dns_server);
-}
+/*
+ * Authors:
+ * Roman Khlopkov <roman.khlopkov@demlabs.net>
+ * DeM Labs Inc.   https://demlabs.net
+ * DeM Labs Open source community https://gitlab.demlabs.net
+ * Copyright  (c) 2017-2020
+ * 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_dns_server.h"
+#include "dap_udp_server.h"
+#include "dap_udp_client.h"
+#include "dap_client_remote.h"
+#include "dap_common.h"
+#include "dap_chain_net.h"
+#include "dap_chain_node.h"
+#include "dap_string.h"
+#include "dap_chain_global_db.h"
+#include "dap_chain_global_db_remote.h"
+
+#define UNUSED(x) (void)(x)
+#define LOG_TAG "dap_dns_server"
+
+static dap_dns_server_t *s_dns_server;
+static char s_root_alias[] = "dnsroot";
+
+/**
+ * @brief dap_dns_buf_init Initialize DNS parser buffer
+ * @param buf DNS buffer structure
+ * @param msg DNS message
+ * @return none
+ */
+void dap_dns_buf_init(dap_dns_buf_t *buf, char *msg) {
+    buf->data = msg;
+    buf->ptr = 0;
+}
+
+/**
+ * @brief dap_dns_buf_get_uint16 Get uint16 from network order
+ * @param buf DNS buffer structure
+ * @return uint16 in host order
+ */
+uint16_t dap_dns_buf_get_uint16(dap_dns_buf_t *buf) {
+    char c;
+    c = buf->data[buf->ptr++];
+    return c << 8 | buf->data[buf->ptr++];
+}
+
+/**
+ * @brief dap_dns_buf_put_uint16 Put uint16 to network order
+ * @param buf DNS buffer structure
+ * @param val uint16 in host order
+ * @return none
+ */
+void dap_dns_buf_put_uint16(dap_dns_buf_t *buf, uint16_t val) {
+    buf->data[buf->ptr++] = val >> 8;
+    buf->data[buf->ptr++] = val;
+}
+
+/**
+ * @brief dap_dns_buf_put_uint32 Put uint32 to network order
+ * @param buf DNS buffer structure
+ * @param val uint32 in host order
+ * @return none
+ */
+void dap_dns_buf_put_uint32(dap_dns_buf_t *buf, uint32_t val) {
+    dap_dns_buf_put_uint16(buf, val >> 16);
+    dap_dns_buf_put_uint16(buf, val);
+}
+
+uint32_t dap_dns_resolve_hostname(char *str) {
+    log_it(L_DEBUG, "DNS parser retrieve hostname %s", str);
+    dap_chain_net_t *l_net = dap_chain_net_by_name("kelvin-testnet");
+    // get nodes list from global_db
+    dap_global_db_obj_t *l_objs = NULL;
+    size_t l_nodes_count = 0;
+    // read all node
+    l_objs = dap_chain_global_db_gr_load(l_net->pub.gdb_nodes, &l_nodes_count);
+    if(!l_nodes_count || !l_objs)
+        return 0;
+    size_t l_node_num = rand() % l_nodes_count;
+    dap_chain_node_info_t *l_node_info = (dap_chain_node_info_t *) l_objs[l_node_num].value;
+    uint32_t addr = l_node_info->hdr.ext_addr_v4.s_addr;
+    dap_chain_global_db_objs_delete(l_objs, l_nodes_count);
+    log_it(L_DEBUG, "DNS resolver find ip %d.%d.%d.%d", addr & 0xFF, (addr >> 8) & 0xFF, (addr >> 16) & 0xFF, (addr >> 24) & 0xFF);
+    return addr;
+}
+
+/**
+ * @brief dap_dns_zone_register Register DNS zone and set callback to handle it
+ * @param zone Name of zone to register
+ * @param callback Callback to handle DNS zone
+ * @return 0 if success, else return error code
+ */
+int dap_dns_zone_register(char *zone, dap_dns_zone_callback_t callback) {
+    dap_dns_zone_hash_t *new_zone;
+    HASH_FIND_STR(s_dns_server->hash_table, zone, new_zone);
+    if (new_zone == NULL) {      // zone is not present
+      new_zone = DAP_NEW(dap_dns_zone_hash_t);
+      new_zone->zone = dap_strdup(zone);
+      HASH_ADD_KEYPTR(hh, s_dns_server->hash_table, new_zone->zone, strlen(new_zone->zone), new_zone);
+    }                           // if zone present, just reassign callback
+    new_zone->callback = callback;
+    return DNS_ERROR_NONE;
+}
+
+/**
+ * @brief dap_dns_zone_unregister Unregister DNS zone
+ * @param zone Name of zone to unregister
+ * @return 0 if success, else return error code
+ */
+int dap_dns_zone_unregister(char *zone) {
+    dap_dns_zone_hash_t *asked_zone;
+    HASH_FIND_STR(s_dns_server->hash_table, zone, asked_zone);
+    if (asked_zone == NULL) {
+        return DNS_ERROR_NAME;
+    }
+    HASH_DEL(s_dns_server->hash_table, asked_zone);
+    DAP_DELETE(asked_zone->zone);
+    DAP_DELETE(asked_zone);
+    return DNS_ERROR_NONE;
+}
+
+/**
+ * @brief dap_dns_zone_find Find callback to registered DNS zone
+ * @param hostname Name of host for which the zone callback being searched
+ * @return Callback for registered DNS zone, else return NULL
+ */
+dap_dns_zone_callback_t dap_dns_zone_find(char *hostname) {
+    dap_dns_zone_hash_t *asked_zone;
+    HASH_FIND_STR(s_dns_server->hash_table, hostname, asked_zone);
+    if (asked_zone == NULL) {
+        if (!strcmp(hostname, &s_root_alias[0])) {
+            return NULL;
+        }
+        char *zone_up = strchr(hostname, '.');
+        if (zone_up++ == NULL) {
+            zone_up = &s_root_alias[0];
+        }
+        return dap_dns_zone_find(zone_up);
+    } else {
+        return asked_zone->callback;
+    }
+    return NULL;
+}
+
+/**
+ * @brief dap_dns_client_read Read and parse incoming DNS message, send reply to it
+ * @param client DAP client remote structure
+ * @param arg Unused
+ * @return none
+ */
+void dap_dns_client_read(dap_client_remote_t *client, void * arg) {
+    UNUSED(arg);
+    if (client->buf_in_size < DNS_HEADER_SIZE) {        // Bad request
+        return;
+    }
+    dap_dns_buf_t *dns_message = DAP_NEW(dap_dns_buf_t);
+    dap_dns_buf_t *dns_reply = DAP_NEW(dap_dns_buf_t);
+    dns_message->data = DAP_NEW_SIZE(char, client->buf_in_size + 1);
+    dns_message->data[client->buf_in_size] = 0;
+    dap_client_remote_read(client, dns_message->data, client->buf_in_size);
+    dns_message->ptr = 0;
+
+    // Parse incoming DNS message
+    int block_len = DNS_HEADER_SIZE;
+    dns_reply->data = DAP_NEW_SIZE(char, block_len);
+    dns_reply->ptr = 0;
+    uint16_t val = dap_dns_buf_get_uint16(dns_message); // ID
+    dap_dns_buf_put_uint16(dns_reply, val);
+    val = dap_dns_buf_get_uint16(dns_message);          // Flags
+    dns_reply->ptr += sizeof(uint16_t);                 // Put flags later
+    dap_dns_message_flags_t msg_flags;
+    msg_flags.val = val;
+    dap_dns_message_flags_bits_t *flags = &msg_flags.flags;
+    if (flags->qr) {                                     // It's not request
+        goto cleanup;
+    }
+    flags->rcode = DNS_ERROR_NONE;
+    flags->qr = 1;                                       // Response bit set
+    if (flags->tc) {                                     // Truncated messages not supported yet
+        flags->rcode = DNS_ERROR_NOT_SUPPORTED;
+    }
+    flags->ra = 0;                                       // Recursion not supported yet
+    flags->aa = 1;                                       // Authoritative answer
+    uint16_t qdcount = dap_dns_buf_get_uint16(dns_message);
+    dap_dns_buf_put_uint16(dns_reply, qdcount);
+    val = dap_dns_buf_get_uint16(dns_message);          // AN count
+    if (val) {                                          // No other sections should present
+        goto cleanup;
+    }
+    dap_dns_buf_put_uint16(dns_reply, 1);               // 1 answer section
+    val = dap_dns_buf_get_uint16(dns_message);          // NS count
+    if (val) {                                          // No other sections should present
+        goto cleanup;
+    }
+    dap_dns_buf_put_uint16(dns_reply, val);
+    val = dap_dns_buf_get_uint16(dns_message);          // AR count
+    if (val) {                                          // No other sections should present
+        goto cleanup;
+    }
+    dap_dns_buf_put_uint16(dns_reply, val);
+    int dot_count = 0;
+    dap_string_t *dns_hostname = dap_string_new("");
+    for (int i = 0; i < qdcount; i++) {
+        block_len = strlen(&dns_message->data[dns_message->ptr]) + 1 + 2 * sizeof(uint16_t);
+        dns_reply->data = DAP_REALLOC(dns_reply->data, dns_reply->ptr + block_len);
+        memcpy(&dns_reply->data[dns_reply->ptr], &dns_message->data[dns_message->ptr], block_len);
+        dns_reply->ptr += block_len;
+        if (flags->rcode)
+            break;
+        while (dns_message->ptr < dns_reply->ptr - 2 * sizeof(uint16_t)) {
+            uint8_t len = dns_message->data[dns_message->ptr++];
+            if (len > DNS_MAX_DOMAIN_NAME_LEN) {
+                flags->rcode = DNS_ERROR_NAME;
+                break;
+            }
+            if (!len) {
+                break;
+            }
+            if (dot_count) {
+                if (dot_count > 3) {                    // Max three dots allowed
+                    flags->rcode = DNS_ERROR_NAME;
+                    break;
+                }
+                dap_string_append(dns_hostname, ".");
+            }
+            dap_string_append_len(dns_hostname, &dns_message->data[dns_message->ptr], len);
+            dns_message->ptr += len;
+            dot_count++;
+            if (dns_hostname->len >= DNS_MAX_HOSTNAME_LEN) {
+                flags->rcode = DNS_ERROR_NAME;
+                break;
+            }
+        }
+        val = dap_dns_buf_get_uint16(dns_message);      // DNS record type
+        if (val != DNS_RECORD_TYPE_A) {                 // Only host address ipv4
+            flags->rcode = DNS_ERROR_NOT_SUPPORTED;
+            break;
+        }
+        val = dap_dns_buf_get_uint16(dns_message);      // DNS class type
+        if (val != DNS_CLASS_TYPE_IN) {                 // Internet only
+            flags->rcode = DNS_ERROR_NOT_SUPPORTED;
+            break;
+        }
+        if (dns_message->ptr != dns_reply->ptr) {
+            log_it(L_ERROR, "DNS parser pointer unequal, mptr = %u, rptr = %u", dns_message->ptr, dns_reply->ptr);
+        }
+    }
+    // Find ip addr
+    uint32_t ip_addr = 0;
+    if (flags->rcode == DNS_ERROR_NONE) {
+        dap_dns_zone_callback_t callback = dap_dns_zone_find(dns_hostname->str);
+        if (callback) {
+            ip_addr = callback(dns_hostname->str);
+        }
+    }
+    if (ip_addr) {
+    // Compose DNS answer
+        block_len = DNS_ANSWER_SIZE;
+        dns_reply->data = DAP_REALLOC(dns_reply->data, dns_reply->ptr + block_len);
+        val = 0xc000 | DNS_HEADER_SIZE;                // Link to host name
+        dap_dns_buf_put_uint16(dns_reply, val);
+        val = DNS_RECORD_TYPE_A;
+        dap_dns_buf_put_uint16(dns_reply, val);
+        val = DNS_CLASS_TYPE_IN;
+        dap_dns_buf_put_uint16(dns_reply, val);
+        uint32_t ttl = DNS_TIME_TO_LIVE;
+        dap_dns_buf_put_uint32(dns_reply, ttl);
+        val = 4;                                        // RD len for ipv4
+        dap_dns_buf_put_uint16(dns_reply, val);
+        dap_dns_buf_put_uint32(dns_reply, ip_addr);
+    } else if (flags->rcode == DNS_ERROR_NONE) {
+        flags->rcode = DNS_ERROR_NAME;
+    }
+    if (flags->rcode) {
+        dns_reply->data[7] = 0;                         // No answer section
+    }
+    // Set reply flags
+    dns_reply->data[2] = msg_flags.val >> 8;
+    dns_reply->data[3] = msg_flags.val;
+    // Send DNS reply
+    dap_udp_client_write(client, dns_reply->data, dns_reply->ptr);
+    dap_udp_client_ready_to_write(client, true);
+    dap_string_free(dns_hostname, true);
+cleanup:
+    DAP_DELETE(dns_reply->data);
+    DAP_DELETE(dns_message->data);
+    DAP_DELETE(dns_reply);
+    DAP_DELETE(dns_message);
+    return;
+}
+
+void dap_dns_server_start() {
+    s_dns_server = DAP_NEW(dap_dns_server_t);
+    s_dns_server->hash_table = NULL;
+    s_dns_server->instance = dap_udp_server_listen(DNS_LISTEN_PORT);
+    if (!s_dns_server->instance) {
+        log_it(L_ERROR, "Can't star DNS server");
+        return;
+    }
+    s_dns_server->instance->client_read_callback = dap_dns_client_read;
+    s_dns_server->instance->client_read_callback = *dap_dns_client_read;
+    s_dns_server->instance->client_write_callback = NULL;
+    s_dns_server->instance->client_new_callback = NULL;
+    s_dns_server->instance->client_delete_callback = NULL;
+    dap_dns_zone_register(&s_root_alias[0], dap_dns_resolve_hostname);  // root resolver
+    pthread_create(&s_dns_server->udp_thread, NULL, (void *)dap_udp_server_loop, s_dns_server->instance);
+}
+
+void dap_dns_server_stop() {
+    dap_dns_zone_hash_t *current_zone, *tmp;
+    HASH_ITER(hh, s_dns_server->hash_table, current_zone, tmp) {
+        HASH_DEL(s_dns_server->hash_table, current_zone);
+        DAP_DELETE(current_zone->zone);
+        DAP_DELETE(current_zone);
+    }
+    // TODO add code to stop udp_thread
+    dap_udp_server_delete(s_dns_server->instance);
+    DAP_DELETE(s_dns_server);
+}
diff --git a/dap-sdk/net/server-udp/include/dap_dns_server.h b/modules/net/include/dap_dns_server.h
similarity index 97%
rename from dap-sdk/net/server-udp/include/dap_dns_server.h
rename to modules/net/include/dap_dns_server.h
index 6743732de0..ee107a16bf 100644
--- a/dap-sdk/net/server-udp/include/dap_dns_server.h
+++ b/modules/net/include/dap_dns_server.h
@@ -1,125 +1,125 @@
-/*
- * Authors:
- * Roman Khlopkov <roman.khlopkov@demlabs.net>
- * DeM Labs Inc.   https://demlabs.net
- * DeM Labs Open source community https://gitlab.demlabs.net
- * Copyright  (c) 2017-2020
- * 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
-
-#ifdef _WIN32
-#include <pthread.h>
-#endif
-#include "dap_server.h"
-#include "uthash.h"
-
-#define DNS_LISTEN_PORT 53      // UDP
-#define DNS_TIME_TO_LIVE 600    // Seconds
-#define DNS_HEADER_SIZE 12
+/*
+ * Authors:
+ * Roman Khlopkov <roman.khlopkov@demlabs.net>
+ * DeM Labs Inc.   https://demlabs.net
+ * DeM Labs Open source community https://gitlab.demlabs.net
+ * Copyright  (c) 2017-2020
+ * 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
+
+#ifdef _WIN32
+#include <pthread.h>
+#endif
+#include "dap_server.h"
+#include "uthash.h"
+
+#define DNS_LISTEN_PORT 53      // UDP
+#define DNS_TIME_TO_LIVE 600    // Seconds
+#define DNS_HEADER_SIZE 12
 #define DNS_ANSWER_SIZE 16
 #define DNS_MAX_HOSTNAME_LEN 255
-#define DNS_MAX_DOMAIN_NAME_LEN 63
-
-typedef enum _dap_dns_query_type_t {
-    DNS_QUERY_TYPE_STANDARD,
-    DNS_QUERY_TYPE_INVERSE,
-    DNS_QUERY_TYPE_STATUS
-} dap_dns_query_type_t;
-
-typedef enum _dap_dns_error_t {
-    DNS_ERROR_NONE,         // No error
-    DNS_ERROR_FORMAT,       // DNS message parsing error
-    DNS_ERROR_FAILURE,      // Internal server error
-    DNS_ERROR_NAME,         // Only for authoritative servers. Name does not exist
-    DNS_ERROR_NOT_SUPPORTED,// This kind of query not implemented
-    DNS_ERROR_REFUSED       // Operation refused
-} dap_dns_error_t;
-
-typedef enum _dap_dns_record_type_t {
-    DNS_RECORD_TYPE_A = 1,  // Host address
-    DNS_RECORD_TYPE_NS,     // Authoritative name server
-    DNS_RECORD_TYPE_MD,     // Mail destination (obsolete, use MX)
-    DNS_RECORD_TYPE_MF,     // Mail forwarder (obsolete, use MX)
-    DNS_RECORD_TYPE_CNAME,  // Canonical name of alias
-    DNS_RECORD_TYPE_SOA,    // Marks a start of a zone of authority
-    DNS_RECORD_TYPE_MB,     // Mailbox domain name (experimental)
-    DNS_RECORD_TYPE_MG,     // Mail group member (experimental)
-    DNS_RECORD_TYPE_MR,     // Mail rename domain name (experimental)
-    DNS_RECORD_TYPE_NULL,   // NULL resource record (experimental)
-    DNS_RECORD_TYPE_WKS,    // Well known server description
-    DNS_RECORD_TYPE_PTR,    // Domain name pointer
-    DNS_RECORD_TYPE_HINFO,  // Host information
-    DNS_RECORD_TYPE_MINFO,  // Mail box or list information
-    DNS_RECORD_TYPE_MX,     // Mail exchange
-    DNS_RECORD_TYPE_TXT,    // Text strings
-    DNS_RECORD_TYPE_RP,     // Responsible person
-    DNS_RECORD_TYPE_AXFR = 252, // A request for a transfer of an entire zone - QTYPE only
-    DNS_RECORD_TYPE_MAILB,  // A request for mailbox-related records (MB, MG or MR) - QTYPE only
-    DNS_RECORD_TYPE_MAILA,  // A request for mail agent RRs (obsolete - see MX) - QTYPE only
-    DNS_RECORD_TYPE_ANY     // A request for all records - QTYPE only
-} dap_dns_record_type_t;
-
-typedef enum _dap_dns_class_type_t {
-    DNS_CLASS_TYPE_IN = 1,  // Internet
-    DNS_CLASS_TYPE_CS,      // CSNET (obsolete)
-    DNS_CLASS_TYPE_CH,      // CHAOS
-    DNS_CLASS_TYPE_HS,      // Hesiod [Dyer 87]
-    DNS_CLASS_TYPE_ANY = 255    // Any class
-} dap_dns_class_type_t;
-
-typedef struct _dap_dns_message_flags_bits_t {
-    int rcode : 4;          // response code, answer only: 0 - no error, 1 - format error, 2 - server failure, 3 - name error, 4 - not supported, 5 - refused
-    int z : 3;              // reserved, must be zero
-    int ra : 1;             // 1 - recursion available (answer only)
-    int rd : 1;             // 1 - recursion desired (query set, copied to answer)
-    int tc : 1;             // 1 - message truncated
-    int aa : 1;             // 1 - authoritative answer (answer only)
+#define DNS_MAX_DOMAIN_NAME_LEN 63
+
+typedef enum _dap_dns_query_type_t {
+    DNS_QUERY_TYPE_STANDARD,
+    DNS_QUERY_TYPE_INVERSE,
+    DNS_QUERY_TYPE_STATUS
+} dap_dns_query_type_t;
+
+typedef enum _dap_dns_error_t {
+    DNS_ERROR_NONE,         // No error
+    DNS_ERROR_FORMAT,       // DNS message parsing error
+    DNS_ERROR_FAILURE,      // Internal server error
+    DNS_ERROR_NAME,         // Only for authoritative servers. Name does not exist
+    DNS_ERROR_NOT_SUPPORTED,// This kind of query not implemented
+    DNS_ERROR_REFUSED       // Operation refused
+} dap_dns_error_t;
+
+typedef enum _dap_dns_record_type_t {
+    DNS_RECORD_TYPE_A = 1,  // Host address
+    DNS_RECORD_TYPE_NS,     // Authoritative name server
+    DNS_RECORD_TYPE_MD,     // Mail destination (obsolete, use MX)
+    DNS_RECORD_TYPE_MF,     // Mail forwarder (obsolete, use MX)
+    DNS_RECORD_TYPE_CNAME,  // Canonical name of alias
+    DNS_RECORD_TYPE_SOA,    // Marks a start of a zone of authority
+    DNS_RECORD_TYPE_MB,     // Mailbox domain name (experimental)
+    DNS_RECORD_TYPE_MG,     // Mail group member (experimental)
+    DNS_RECORD_TYPE_MR,     // Mail rename domain name (experimental)
+    DNS_RECORD_TYPE_NULL,   // NULL resource record (experimental)
+    DNS_RECORD_TYPE_WKS,    // Well known server description
+    DNS_RECORD_TYPE_PTR,    // Domain name pointer
+    DNS_RECORD_TYPE_HINFO,  // Host information
+    DNS_RECORD_TYPE_MINFO,  // Mail box or list information
+    DNS_RECORD_TYPE_MX,     // Mail exchange
+    DNS_RECORD_TYPE_TXT,    // Text strings
+    DNS_RECORD_TYPE_RP,     // Responsible person
+    DNS_RECORD_TYPE_AXFR = 252, // A request for a transfer of an entire zone - QTYPE only
+    DNS_RECORD_TYPE_MAILB,  // A request for mailbox-related records (MB, MG or MR) - QTYPE only
+    DNS_RECORD_TYPE_MAILA,  // A request for mail agent RRs (obsolete - see MX) - QTYPE only
+    DNS_RECORD_TYPE_ANY     // A request for all records - QTYPE only
+} dap_dns_record_type_t;
+
+typedef enum _dap_dns_class_type_t {
+    DNS_CLASS_TYPE_IN = 1,  // Internet
+    DNS_CLASS_TYPE_CS,      // CSNET (obsolete)
+    DNS_CLASS_TYPE_CH,      // CHAOS
+    DNS_CLASS_TYPE_HS,      // Hesiod [Dyer 87]
+    DNS_CLASS_TYPE_ANY = 255    // Any class
+} dap_dns_class_type_t;
+
+typedef struct _dap_dns_message_flags_bits_t {
+    int rcode : 4;          // response code, answer only: 0 - no error, 1 - format error, 2 - server failure, 3 - name error, 4 - not supported, 5 - refused
+    int z : 3;              // reserved, must be zero
+    int ra : 1;             // 1 - recursion available (answer only)
+    int rd : 1;             // 1 - recursion desired (query set, copied to answer)
+    int tc : 1;             // 1 - message truncated
+    int aa : 1;             // 1 - authoritative answer (answer only)
     int opcode : 4;         // type of query, copied to answer: 0 - standard, 1 - inverse, 2 - status, 3-15 - reserved
-    int qr : 1;             // 0 - query, 1 - response
-} dap_dns_message_flags_bits_t;
-
-typedef uint32_t (*dap_dns_zone_callback_t) (char *hostname); // Callback for DNS zone operations
-
-typedef union _dap_dns_message_flags_t {
-    dap_dns_message_flags_bits_t flags;
-    int val;
-} dap_dns_message_flags_t;
-
-typedef struct _dap_dns_buf_t {
-    char *data;
-    uint32_t ptr;
-} dap_dns_buf_t;
-
-typedef struct _dap_dns_zone_hash_t {
-    char *zone;
-    dap_dns_zone_callback_t callback;
-    UT_hash_handle hh;
-} dap_dns_zone_hash_t;
-
-typedef struct _dap_dns_server_t {
-    dap_server_t *instance;
-    pthread_t udp_thread;
-    dap_dns_zone_hash_t *hash_table;
-} dap_dns_server_t;
-
-void dap_dns_server_start();
-void dap_dns_server_stop();
-int dap_dns_zone_register(char *zone, dap_dns_zone_callback_t callback);
-int dap_dns_zone_unregister(char *zone);
+    int qr : 1;             // 0 - query, 1 - response
+} dap_dns_message_flags_bits_t;
+
+typedef uint32_t (*dap_dns_zone_callback_t) (char *hostname); // Callback for DNS zone operations
+
+typedef union _dap_dns_message_flags_t {
+    dap_dns_message_flags_bits_t flags;
+    int val;
+} dap_dns_message_flags_t;
+
+typedef struct _dap_dns_buf_t {
+    char *data;
+    uint32_t ptr;
+} dap_dns_buf_t;
+
+typedef struct _dap_dns_zone_hash_t {
+    char *zone;
+    dap_dns_zone_callback_t callback;
+    UT_hash_handle hh;
+} dap_dns_zone_hash_t;
+
+typedef struct _dap_dns_server_t {
+    dap_server_t *instance;
+    pthread_t udp_thread;
+    dap_dns_zone_hash_t *hash_table;
+} dap_dns_server_t;
+
+void dap_dns_server_start();
+void dap_dns_server_stop();
+int dap_dns_zone_register(char *zone, dap_dns_zone_callback_t callback);
+int dap_dns_zone_unregister(char *zone);
-- 
GitLab