diff --git a/libdap-server-udp b/libdap-server-udp
deleted file mode 160000
index fddad31ed0785452ab0aad35a0746533e6713653..0000000000000000000000000000000000000000
--- a/libdap-server-udp
+++ /dev/null
@@ -1 +0,0 @@
-Subproject commit fddad31ed0785452ab0aad35a0746533e6713653
diff --git a/libdap-server-udp/.gitignore b/libdap-server-udp/.gitignore
new file mode 100755
index 0000000000000000000000000000000000000000..e8451f4157a6dbae7124d7380a2ebf1a0119f53f
--- /dev/null
+++ b/libdap-server-udp/.gitignore
@@ -0,0 +1,2 @@
+CMakeLists.txt.user
+test/build
diff --git a/libdap-server-udp/.gitmodules b/libdap-server-udp/.gitmodules
new file mode 100755
index 0000000000000000000000000000000000000000..c6856fada453ee5dc89ecf69e8c157ccdba96757
--- /dev/null
+++ b/libdap-server-udp/.gitmodules
@@ -0,0 +1,12 @@
+[submodule "test/libdap-test"]
+    path = test/libdap-test
+    url = https://gitlab.demlabs.net/cellframe/libdap-test
+    branch = master 
+[submodule "libdap"]
+  path = libdap
+  url = https://gitlab.demlabs.net/cellframe/libdap
+  branch = master 
+[submodule "libdap-server-core"]
+  path = libdap-server-core
+  url = https://gitlab.demlabs.net/cellframe/libdap-server-core
+  branch = master 
diff --git a/libdap-server-udp/.travis.yml b/libdap-server-udp/.travis.yml
new file mode 100755
index 0000000000000000000000000000000000000000..256452d22b659f80791b9ef389c823db745803da
--- /dev/null
+++ b/libdap-server-udp/.travis.yml
@@ -0,0 +1,25 @@
+sudo: required
+language: cpp
+compiler: c
+dist: xenial
+notifications:
+  email: false
+
+before_install:
+    - git submodule init
+    - git submodule update --recursive
+
+script:
+    - mkdir build
+    - cd build 
+    - cmake -DBUILD_DAP_UDP_SERVER_TESTS=ON ../
+    - make
+    - ctest --verbose
+
+addons:
+  apt:
+    sources:
+    - ubuntu-toolchain-r-test
+    packages:
+    - libev-dev
+
diff --git a/libdap-server-udp/CMakeLists.txt b/libdap-server-udp/CMakeLists.txt
new file mode 100755
index 0000000000000000000000000000000000000000..6e1e123bf79ab592cae3ac2d82494833fdb172fa
--- /dev/null
+++ b/libdap-server-udp/CMakeLists.txt
@@ -0,0 +1,35 @@
+cmake_minimum_required(VERSION 3.1)
+project (dap_udp_server C)
+
+if(NOT SUBMODULES_NO_BUILD)
+
+#    if ( NOT ( TARGET dap_server_core ) )
+#        add_subdirectory(libdap-server-core)
+#    endif()
+
+    if ( NOT ( TARGET dap_core ) )
+      add_subdirectory(libdap)
+    endif()
+
+    if ( NOT ( TARGET dap_server_core ) )
+        add_subdirectory(libdap-server-core)
+    endif()
+
+    enable_testing()
+    add_subdirectory(test)
+endif()
+
+set(DAP_UDP_SERVER_SRCS dap_udp_server.c dap_udp_client.c dap_dns_server.c)
+set(DAP_UDP_SERVER_HEADERS dap_udp_server.h dap_udp_client.h dap_dns_server.h)
+
+if(WIN32)
+  include_directories(../3rdparty/wepoll/)
+  include_directories(../3rdparty/uthash/src/)
+  #include_directories(../3rdparty/curl/include/)
+endif()
+
+add_library(${PROJECT_NAME} STATIC ${DAP_UDP_SERVER_SRCS})
+
+target_link_libraries(${PROJECT_NAME} dap_core dap_server_core dap_chain_net)
+
+target_include_directories(${PROJECT_NAME} INTERFACE .)
diff --git a/libdap-server-udp/README.md b/libdap-server-udp/README.md
new file mode 100755
index 0000000000000000000000000000000000000000..fd721b1b5275b5e23bf6e83fb70f3dad69b08b0d
--- /dev/null
+++ b/libdap-server-udp/README.md
@@ -0,0 +1,3 @@
+# libdap-server-udp
+
+[![Build Status](https://travis-ci.com/kelvinblockchain/libdap-server-udp.svg?branch=master)](https://travis-ci.com/kelvinblockchain/libdap-server-udp)
diff --git a/libdap-server-udp/dap_dns_server.c b/libdap-server-udp/dap_dns_server.c
new file mode 100755
index 0000000000000000000000000000000000000000..a93c8f55cd8720f6f481afdc8619ba898a35f4f8
--- /dev/null
+++ b/libdap-server-udp/dap_dns_server.c
@@ -0,0 +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);
+}
diff --git a/libdap-server-udp/dap_dns_server.h b/libdap-server-udp/dap_dns_server.h
new file mode 100755
index 0000000000000000000000000000000000000000..6743732de06df3cd20c9a62f5d8fa8846ed45352
--- /dev/null
+++ b/libdap-server-udp/dap_dns_server.h
@@ -0,0 +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
+#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)
+    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);
diff --git a/libdap-server-udp/dap_udp_client.c b/libdap-server-udp/dap_udp_client.c
new file mode 100755
index 0000000000000000000000000000000000000000..ab13f7de654ba89a6184c4c38eb71a4e7a3c9d28
--- /dev/null
+++ b/libdap-server-udp/dap_udp_client.c
@@ -0,0 +1,253 @@
+/*
+ Copyright (c) 2017-2019 (c) Project "DeM Labs Inc" https://demlabs.net
+  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 Lesser 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 Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public License
+    along with any DAP based project.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdint.h>
+
+#ifndef _WIN32
+#include <arpa/inet.h>
+#include <netinet/in.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/select.h>
+#include <sys/queue.h>
+#include <errno.h>
+#include <netdb.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/epoll.h>
+#else
+#include <winsock2.h>
+#include <windows.h>
+#include <mswsock.h>
+#include <ws2tcpip.h>
+#include <io.h>
+#include <pthread.h>
+#endif
+
+#include "uthash.h"
+#include "utlist.h"
+
+#include "dap_common.h"
+#include "dap_udp_client.h"
+#include "dap_udp_server.h"
+
+#define LOG_TAG "udp_client"
+
+/**
+ * @brief get_key Make key for hash table from host and port
+ * @return 64 bit Key
+ */
+#define get_key( host, key ) (((uint64_t)host << 32) + (uint64_t)port)
+extern bool sb_payload_ready;
+
+/**
+ * @brief udp_client_create Create new client and add it to hashmap
+ * @param sh Server instance
+ * @param host Client host address
+ * @param w_client Clients event loop watcher
+ * @param port Client port
+ * @return Pointer to the new list's node
+ */
+dap_client_remote_t *dap_udp_client_create( dap_server_t *dap_srv, EPOLL_HANDLE efd, unsigned long host, unsigned short port )
+{
+  dap_udp_server_t *udp_server = DAP_UDP_SERVER( dap_srv );
+  log_it( L_DEBUG, "Client structure create with host = %x, port = %d", host, port );
+
+  dap_udp_client_t *inh = DAP_NEW_Z( dap_udp_client_t );
+  inh->host_key = get_key( host, port );
+
+  dap_client_remote_t *ret = DAP_NEW_Z( dap_client_remote_t );
+  inh->client = ret;
+
+  ret->pevent.events = EPOLLIN | EPOLLERR;
+  ret->pevent.data.fd = dap_srv->socket_listener;
+
+  ret->server = dap_srv;
+  ret->efd = efd;
+
+  ret->flags = DAP_SOCK_READY_TO_READ;
+
+//  ret->signal_close = false;
+//  ret->_ready_to_read = true;
+//  ret->_ready_to_write = false;
+
+  ret->_inheritor = inh;
+
+  pthread_mutex_init( &inh->mutex_on_client, NULL );
+
+  pthread_mutex_lock( &udp_server->mutex_on_list );
+  HASH_ADD_INT( udp_server->hclients, host_key, inh );
+  pthread_mutex_unlock( &udp_server->mutex_on_list );
+
+  if( dap_srv->client_new_callback )
+    dap_srv->client_new_callback( ret, NULL ); // Init internal structure
+
+  return ret;
+}
+
+/**
+ * @brief udp_client_get_address Get host address and port of client
+ * @param client Pointer to client structure
+ * @param host Variable for host address
+ * @param host Variable for port
+ */
+void dap_udp_client_get_address( dap_client_remote_t *client, unsigned int* host, unsigned short* port )
+{
+  dap_udp_client_t* udp_client = DAP_UDP_CLIENT( client );
+  *host = udp_client->host_key >> 32;
+  *port = udp_client->host_key;
+}
+
+/**
+ * @brief udp_client_find Find client structure by host address and port
+ * @param sh Server instance
+ * @param host Source host address
+ * @param port Source port
+ * @return Pointer to client or NULL if not found
+ */
+dap_client_remote_t *dap_udp_client_find( dap_server_t *dap_srv, unsigned long host, unsigned short port )
+{
+  dap_udp_client_t *inh = NULL;
+  dap_udp_server_t *udp_server = DAP_UDP_SERVER( dap_srv );
+
+  uint64_t token = get_key( host, port );
+
+  pthread_mutex_lock( &udp_server->mutex_on_list );
+  HASH_FIND_INT( udp_server->hclients, &token, inh );
+  pthread_mutex_unlock( &udp_server->mutex_on_list );
+
+  if( inh == NULL )
+    return NULL;
+  else
+    return inh->client;
+}
+
+/**
+ * @brief udp_client_ready_to_read Set ready_to_read flag
+ * @param dap_rclient Client structure
+ * @param is_ready Flag value
+ */
+void dap_udp_client_ready_to_read( dap_client_remote_t *sc, bool is_ready )
+{
+  if( is_ready == (bool)(sc->flags & DAP_SOCK_READY_TO_READ) )
+    return;
+
+  if ( is_ready )
+    sc->flags |= DAP_SOCK_READY_TO_READ;
+  else
+    sc->flags ^= DAP_SOCK_READY_TO_READ;
+
+  int events = EPOLLERR;
+
+  if( sc->flags & DAP_SOCK_READY_TO_READ )
+    events |= EPOLLIN;
+
+  if( sc->flags & DAP_SOCK_READY_TO_WRITE )
+    events |= EPOLLOUT;
+
+  sc->pevent.events = events;
+
+  if( epoll_ctl(sc->efd, EPOLL_CTL_MOD, sc->server->socket_listener, &sc->pevent) != 0 ) {
+    log_it( L_ERROR, "epoll_ctl failed 002" );
+  }
+}
+
+/**
+ * @brief udp_client_ready_to_write Set ready_to_write flag
+ * @param dap_rclient Client structure
+ * @param is_ready Flag value
+ */
+void dap_udp_client_ready_to_write( dap_client_remote_t *sc, bool is_ready )
+{
+  if ( is_ready == (bool)(sc->flags & DAP_SOCK_READY_TO_WRITE) )
+    return;
+
+  if ( is_ready )
+    sc->flags |= DAP_SOCK_READY_TO_WRITE;
+  else
+    sc->flags ^= DAP_SOCK_READY_TO_WRITE;
+  int events = EPOLLERR;
+
+  if( sc->flags & DAP_SOCK_READY_TO_READ )
+    events |= EPOLLIN;
+
+  if( sc->flags & DAP_SOCK_READY_TO_WRITE )
+  {
+    dap_udp_server_t *udp_server = DAP_UDP_SERVER(sc->server);
+    pthread_mutex_lock(&udp_server->mutex_on_list);
+    sb_payload_ready = true;
+    pthread_mutex_unlock(&udp_server->mutex_on_list );
+  }
+
+  sc->pevent.events = events;
+
+  if ( epoll_ctl(sc->efd, EPOLL_CTL_MOD, sc->pevent.data.fd, &sc->pevent) != 0 ) {
+    log_it( L_ERROR, "epoll_ctl failed 003" );
+  }
+}
+
+/**
+ * @brief add_waiting_client Add Client to write queue
+ * @param client Client instance
+ */
+void add_waiting_client( dap_client_remote_t *dap_rclient )
+{
+    dap_udp_client_t* udp_cl, *tmp;
+
+    dap_server_t *dap_srv = dap_rclient->server;
+    dap_udp_server_t *udp_server = DAP_UDP_SERVER( dap_srv );
+    dap_udp_client_t *udp_client = DAP_UDP_CLIENT( dap_rclient );
+
+    pthread_mutex_lock( &udp_server->mutex_on_list );
+    LL_FOREACH_SAFE( udp_server->waiting_clients, udp_cl, tmp ) {
+        if( udp_cl == udp_client ) {
+            pthread_mutex_unlock( &udp_server->mutex_on_list );
+            return;
+        }
+    }
+    LL_APPEND( udp_server->waiting_clients, udp_client );
+    pthread_mutex_unlock( &udp_server->mutex_on_list );
+}
+
+size_t dap_udp_client_write( dap_client_remote_t *dap_rclient, const void *data, size_t data_size )
+{
+    size_t size = dap_client_remote_write( dap_rclient, data, data_size );
+    add_waiting_client( dap_rclient );
+    return size;
+}
+
+size_t dap_udp_client_write_f( dap_client_remote_t *dap_rclient, const char * a_format, ... )
+{
+    size_t size = 0;
+    va_list va;
+
+    va_start( va, a_format );
+    size = dap_client_remote_write_f( dap_rclient, a_format, va );
+    va_end( va );
+
+    add_waiting_client( dap_rclient );
+    return size;
+}
+
diff --git a/libdap-server-udp/dap_udp_client.h b/libdap-server-udp/dap_udp_client.h
new file mode 100755
index 0000000000000000000000000000000000000000..7fc66f14585e359c482b97c201a7fb6bb5beb1ad
--- /dev/null
+++ b/libdap-server-udp/dap_udp_client.h
@@ -0,0 +1,66 @@
+/*
+ Copyright (c) 2017-2018 (c) Project "DeM Labs Inc" https://github.com/demlabsinc
+  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 Lesser 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 Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser 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>
+#include <stdbool.h>
+
+#ifndef WIN32
+#include <sys/queue.h>
+#endif
+
+#include "uthash.h"
+
+#include "dap_client_remote.h"
+
+typedef struct dap_udp_server dap_udp_server_t;
+struct dap_udp_client;
+
+#define UDP_CLIENT_BUF 65535
+
+typedef struct dap_udp_client {
+
+    dap_client_remote_t *client;
+    uint64_t host_key; //key contains host address in first 4 bytes and port in last 4 bytes
+
+    UT_hash_handle hh;
+
+    struct dap_udp_client *next, *prev;   //pointers for writing queue
+    pthread_mutex_t mutex_on_client;
+
+    void *_inheritor; // Internal data to specific client type, usualy states for state machine
+
+} dap_udp_client_t; // Node of bidirectional list of clients
+
+#define DAP_UDP_CLIENT(a) ((dap_udp_client_t *) (a)->_inheritor)
+
+dap_client_remote_t *dap_udp_client_create( dap_server_t *sh, EPOLL_HANDLE efd, unsigned long host, unsigned short port ); // Create new client and add it to the list
+dap_client_remote_t *dap_udp_client_find( dap_server_t *sh, unsigned long host, unsigned short port ); // Find client by host and port
+
+void dap_udp_client_ready_to_read( dap_client_remote_t *sc, bool is_ready );
+void dap_udp_client_ready_to_write( dap_client_remote_t *sc, bool is_ready );
+
+size_t dap_udp_client_write( dap_client_remote_t *sc, const void * data, size_t data_size );
+size_t dap_udp_client_write_f( dap_client_remote_t *a_client, const char * a_format, ... );
+
+void add_waiting_client( dap_client_remote_t *client ); // Add client to writing queue
+
+void dap_udp_client_get_address( dap_client_remote_t *client, unsigned int *host, unsigned short *port );
diff --git a/libdap-server-udp/dap_udp_server.c b/libdap-server-udp/dap_udp_server.c
new file mode 100644
index 0000000000000000000000000000000000000000..9469474ec03d162f0db6cb04c6ae64d52682f0ad
--- /dev/null
+++ b/libdap-server-udp/dap_udp_server.c
@@ -0,0 +1,401 @@
+/*
+ Copyright (c) 2017-2019 (c) Project "DeM Labs Inc" https://github.com/demlabsinc
+  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 Lesser 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 Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public License
+    along with any DAP based project.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <string.h>
+#include <time.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <signal.h>
+#include <stdint.h>
+
+#ifndef _WIN32
+#include <arpa/inet.h>
+#include <netinet/in.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/select.h>
+#include <sys/queue.h>
+#include <errno.h>
+#include <netdb.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/epoll.h>
+#else
+#include <winsock2.h>
+#include <windows.h>
+#include <mswsock.h>
+#include <ws2tcpip.h>
+#include <io.h>
+#include <pthread.h>
+#endif
+
+#include "uthash.h"
+#include "utlist.h"
+
+#include "dap_common.h"
+#include "dap_udp_server.h"
+
+#define LOG_TAG "dap_udp_server"
+
+#define BUFSIZE 1024
+
+char buf[ BUFSIZE ]; /* message buf */
+bool sb_payload_ready;
+//struct ev_io w_read;
+//struct ev_io w_write;
+
+EPOLL_HANDLE efd_read  = (EPOLL_HANDLE)-1;
+
+//static void write_cb( EPOLL_HANDLE efd, int revents );
+
+int check_close( dap_client_remote_t *client );
+
+/**
+ */
+static void error( char *msg ) {
+
+  perror( msg );
+  exit( 1 );
+}
+
+/**
+ * @brief dap_udp_server_new Initialize server structure
+ * @return Server pointer
+ */
+dap_server_t *dap_udp_server_new( )
+{
+  dap_udp_server_t *udp_server = (dap_udp_server_t *)calloc( 1, sizeof(dap_udp_server_t) );
+  udp_server->waiting_clients = NULL;
+
+  dap_server_t *sh = (dap_server_t *) calloc( 1, sizeof(dap_server_t) );
+  sh->_inheritor = udp_server;
+
+  udp_server->dap_server = sh;
+
+  return sh;
+}
+
+/**
+ * @brief dap_udp_server_delete Safe delete server structure
+ * @param sh Server instance
+ */
+void dap_udp_server_delete( dap_server_t *sh )
+{
+  if ( !sh ) return;
+
+//  dap_client_remote_t *client, *tmp;
+//  dap_udp_server_t *udps = (dap_udp_server_t *)sh->_inheritor;
+
+//  if ( !udps ) return;
+
+  if( sh->address )
+    free( sh->address );
+
+//  HASH_ITER( hh, udps->hclients, client, tmp )
+//    dap_client_remote_remove( client );
+
+  if ( sh->server_delete_callback )
+    sh->server_delete_callback( sh, NULL );
+
+  if ( sh->_inheritor )
+    free( sh->_inheritor );
+
+  free( sh );
+}
+
+/**
+ * @brief dap_udp_server_listen Create and bind server structure
+ * @param port Binding port
+ * @return Server instance
+ */
+dap_server_t *dap_udp_server_listen( uint16_t port ) {
+
+  dap_server_t *sh = dap_udp_server_new( );
+
+  sh->socket_listener = socket( AF_INET, SOCK_DGRAM, 0 );
+
+  if ( sh->socket_listener < 0 ) {
+    log_it ( L_ERROR, "Socket error %s", strerror(errno) );
+    dap_udp_server_delete( sh );
+    return NULL;
+  }
+
+  int optval = 1;
+  if ( setsockopt( sh->socket_listener, SOL_SOCKET, SO_REUSEADDR, (const void *)&optval , sizeof(int)) < 0 )
+    log_it( L_WARNING, "Can't set up REUSEADDR flag to the socket" );
+
+  memset( (char *)&(sh->listener_addr), 0, sizeof(sh->listener_addr) );
+
+  sh->listener_addr.sin_family = AF_INET;
+  sh->listener_addr.sin_addr.s_addr = htonl( INADDR_ANY );
+  sh->listener_addr.sin_port = htons( port );
+
+  if ( bind(sh->socket_listener, (struct sockaddr *) &(sh->listener_addr), sizeof(sh->listener_addr)) < 0) {
+    log_it( L_ERROR, "Bind error: %s", strerror(errno) );
+    dap_udp_server_delete( sh );
+    return NULL;
+  }
+  log_it(L_INFO, "UDP server listening port 0.0.0.0:%d", port);
+  pthread_mutex_init( &DAP_UDP_SERVER(sh)->mutex_on_list, NULL );
+  pthread_mutex_init( &DAP_UDP_SERVER(sh)->mutex_on_hash, NULL );
+
+  return sh;
+}
+
+/**
+ * @brief write_cb
+ */
+static void write_cb( EPOLL_HANDLE efd, int revents, dap_server_t *sh )
+{
+  dap_udp_client_t *udp_client, *tmp;
+
+//  dap_server_t *sh = watcher->data;
+  dap_udp_server_t *udp = DAP_UDP_SERVER( sh );
+
+  pthread_mutex_lock( &udp->mutex_on_list );
+
+  LL_FOREACH_SAFE( udp->waiting_clients, udp_client, tmp ) {
+
+        //log_it(L_INFO,"write_cb");
+        //pthread_mutex_lock(&udp_client->mutex_on_client);
+
+    dap_client_remote_t *client = udp_client->client;
+
+    if( client != NULL && !check_close(client) && (client->flags & DAP_SOCK_READY_TO_WRITE) ) {
+
+      if ( sh->client_write_callback )
+        sh->client_write_callback( client, NULL );
+
+      if ( client->buf_out_size > 0 ) {
+
+
+
+        struct sockaddr_in addr;
+        addr.sin_family = AF_INET;
+        dap_udp_client_get_address( client, (unsigned int *)&addr.sin_addr.s_addr, &addr.sin_port );
+        //log_it(L_INFO,"write_cb_client host = %x, port = %d, socket = %x", addr.sin_addr.s_addr, addr.sin_port, sh->socket_listener);
+        for( size_t total_sent = 0; total_sent < client->buf_out_size; ) {
+
+          int bytes_sent = sendto( sh->socket_listener, client->buf_out + total_sent,
+                        client->buf_out_size - total_sent, 0, (struct sockaddr*) &addr, sizeof(addr) );
+
+          if ( bytes_sent < 0 ) {
+            log_it(L_ERROR,"Some error occured in send() function");
+            break;
+          }
+          total_sent += bytes_sent;
+        }
+        client->buf_out_size = 0;
+        memset( client->buf_out, 0, sizeof(client->buf_out) );
+        client->flags &= ~DAP_SOCK_READY_TO_WRITE;
+        sb_payload_ready = false;
+      }
+      LL_DELETE( udp->waiting_clients, udp_client );
+    }
+    else if( client == NULL ) {
+      LL_DELETE( udp->waiting_clients, udp_client );
+    }
+    //pthread_mutex_unlock(&udp_client->mutex_on_client);
+
+  } // for client
+  pthread_mutex_unlock(&udp->mutex_on_list);
+}
+
+/**
+ * @brief check_close Check if client need to close
+ * @param client Client structure
+ * @return 1 if client deleted, 0 if client is no need to delete
+ */
+int check_close( dap_client_remote_t *client )
+{
+  dap_udp_client_t *client_check, *tmp;
+
+  if( !(client->flags & DAP_SOCK_SIGNAL_CLOSE) ) return 0;
+
+  dap_udp_client_t *udp_client = DAP_UDP_CLIENT( client );
+  dap_server_t *sh = client->server;
+  dap_udp_server_t *udp_server = DAP_UDP_SERVER( sh );
+
+  LL_FOREACH_SAFE( udp_server->waiting_clients, client_check, tmp ) {
+
+    if ( client_check->host_key == udp_client->host_key )
+      LL_DELETE( udp_server->waiting_clients, client_check );
+  }
+
+  dap_client_remote_remove( client );
+
+  return 1;
+}
+
+/**
+ * @brief read_cb
+ */
+static void read_cb( EPOLL_HANDLE efd, int revents, dap_server_t *sh )
+{
+//    if ( !(revents & EV_READ) ) return;
+
+    struct sockaddr_in clientaddr;
+    int clientlen = sizeof(clientaddr);
+//    dap_server_t *sh = watcher->data;
+
+    memset( buf, 0, BUFSIZE );
+
+    int32_t bytes = (int32_t) recvfrom( sh->socket_listener, buf, BUFSIZE, 0,(struct sockaddr *) &clientaddr, &clientlen );
+
+    dap_client_remote_t *client = dap_udp_client_find( sh, clientaddr.sin_addr.s_addr, clientaddr.sin_port );
+
+    if( client != NULL && check_close(client) != 0 )
+            return;
+
+    if ( bytes > 0 ) {
+
+        char *hostaddrp = inet_ntoa( clientaddr.sin_addr );
+
+        if ( hostaddrp == NULL ) {
+            dap_udp_server_delete( sh );
+            error("ERROR on inet_ntoa\n");
+        }
+
+        if ( client == NULL ) {
+            client = dap_udp_client_create( sh, efd, clientaddr.sin_addr.s_addr, clientaddr.sin_port );
+            if(client == NULL) {
+                dap_udp_server_delete( sh );
+                error("ERROR create client structure\n");
+            }
+        }
+
+        dap_udp_client_t* udp_client = client->_inheritor;
+
+        pthread_mutex_lock( &udp_client->mutex_on_client );
+
+        size_t bytes_processed = 0;
+        size_t bytes_recieved = bytes;
+
+        while ( bytes_recieved > 0 ) {
+
+            size_t bytes_to_transfer = 0;
+
+            if ( bytes_recieved > UDP_CLIENT_BUF - client->buf_in_size )
+                bytes_to_transfer = UDP_CLIENT_BUF - client->buf_in_size;
+            else
+                bytes_to_transfer = bytes_recieved;
+
+            memcpy( client->buf_in + client->buf_in_size,buf + bytes_processed, bytes_to_transfer );
+            client->buf_in_size += bytes_to_transfer;
+
+            if ( sh->client_read_callback )
+                sh->client_read_callback( client, NULL );
+
+            bytes_processed += bytes_to_transfer;
+            bytes_recieved -= bytes_to_transfer;
+        }
+
+        client->buf_in_size = 0;
+        memset( client->buf_in, 0, sizeof(client->buf_out) );
+
+        pthread_mutex_unlock( &udp_client->mutex_on_client );
+
+    }
+    else if ( bytes < 0 ) {
+
+        log_it( L_ERROR, "Bytes read Error %s", strerror(errno) );
+        if( client != NULL )
+            client->flags |= DAP_SOCK_SIGNAL_CLOSE;
+    }
+    else if (bytes == 0) {
+        if ( client != NULL )
+            client->flags |= DAP_SOCK_SIGNAL_CLOSE;
+    }
+}
+
+/**
+ * @brief dap_udp_server_loop Start server event loop
+ * @param sh Server instance
+ */
+void dap_udp_server_loop( dap_server_t *d_server )
+{
+  efd_read  = epoll_create1( 0 );
+
+  if ( (intptr_t)efd_read == -1 ) {
+
+    log_it( L_ERROR, "epoll_create1 failed" );
+    goto udp_error;
+  }
+
+  sb_payload_ready = false;
+
+  struct epoll_event  pev;
+  struct epoll_event  events[ 16 ];
+
+  pev.events = EPOLLIN | EPOLLERR;
+  pev.data.fd = d_server->socket_listener;
+
+  if ( epoll_ctl( efd_read, EPOLL_CTL_ADD, d_server->socket_listener, &pev) != 0 ) {
+    log_it( L_ERROR, "epoll_ctl failed 000" );
+    goto udp_error;
+  }
+
+  while( 1 ) {
+
+    int32_t n = epoll_wait( efd_read, &events[0], 16, -1 );
+
+    if ( !n ) continue;
+
+    if ( n < 0 ) {
+      if ( errno == EINTR )
+        continue;
+      log_it( L_ERROR, "Server epoll error" );
+      break;
+    }
+
+    for( int32_t i = 0; i < n; ++ i ) {
+
+      if ( events[i].events & EPOLLIN ) {
+        read_cb( efd_read, events[i].events, d_server );
+      }
+      if ( events[i].events & EPOLLOUT) {
+        // Do nothing. It always true until socket eturn EAGAIN
+      }
+      if (sb_payload_ready) {
+        write_cb( efd_read, events[i].events, d_server );
+      }
+      if( events[i].events & EPOLLERR ) {
+        log_it( L_ERROR, "Server socket error event" );
+        goto udp_error;
+      }
+    }
+
+  }
+
+udp_error:
+
+  #ifndef _WIN32
+    if ( efd_read != -1 )
+      close( efd_read );
+  #else
+    if ( efd_read != INVALID_HANDLE_VALUE )
+      epoll_close( efd_read );
+  #endif
+
+  return;
+}
+
diff --git a/libdap-server-udp/dap_udp_server.h b/libdap-server-udp/dap_udp_server.h
new file mode 100755
index 0000000000000000000000000000000000000000..2ed9465c012118bf5f4edd3761ae1b92f58fa39a
--- /dev/null
+++ b/libdap-server-udp/dap_udp_server.h
@@ -0,0 +1,64 @@
+/*
+ Copyright (c) 2017-2019 (c) Project "DeM Labs Inc" https://github.com/demlabsinc
+  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 Lesser 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 Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public License
+    along with any DAP based project.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#pragma once
+
+#ifndef WIN32
+
+#include <stdint.h>
+#include <sys/socket.h>
+#include <netdb.h>
+#include <arpa/inet.h>
+#include <netinet/in.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/select.h>
+#include <sys/queue.h>
+#define EPOLL_HANDLE  int
+#endif
+
+#include "dap_udp_client.h"
+#include "dap_server.h"
+#include "dap_client_remote.h"
+
+struct dap_udp_server;
+
+typedef struct dap_udp_thread {
+    pthread_t tid;
+} dap_udp_thread_t;
+
+typedef void (*dap_udp_server_callback_t) (struct dap_udp_server *,void *arg); // Callback for specific server's operations
+
+typedef struct dap_udp_server {
+
+    dap_udp_client_t *hclients;
+    dap_udp_client_t *waiting_clients; // List clients for writing data
+    pthread_mutex_t mutex_on_list;
+    pthread_mutex_t mutex_on_hash;
+    void *_inheritor;
+    dap_server_t *dap_server;
+
+} dap_udp_server_t;
+
+#define DAP_UDP_SERVER(a) ((dap_udp_server_t *) (a)->_inheritor)
+
+void dap_udp_server_delete( dap_server_t *sh );
+void dap_udp_server_loop( dap_server_t *udp_server );      // Start server event loop
+dap_server_t *dap_udp_server_listen( uint16_t port );      // Create and bind serv
diff --git a/libdap-server-udp/libdap b/libdap-server-udp/libdap
new file mode 160000
index 0000000000000000000000000000000000000000..78cc4a3aca1775288662ef7a9f49f7b747479e15
--- /dev/null
+++ b/libdap-server-udp/libdap
@@ -0,0 +1 @@
+Subproject commit 78cc4a3aca1775288662ef7a9f49f7b747479e15
diff --git a/libdap-server-udp/libdap-server-core b/libdap-server-udp/libdap-server-core
new file mode 160000
index 0000000000000000000000000000000000000000..bbe4d2b4e00012effac21cda4c2d3554dc6173e0
--- /dev/null
+++ b/libdap-server-udp/libdap-server-core
@@ -0,0 +1 @@
+Subproject commit bbe4d2b4e00012effac21cda4c2d3554dc6173e0
diff --git a/libdap-server-udp/test/CMakeLists.txt b/libdap-server-udp/test/CMakeLists.txt
new file mode 100755
index 0000000000000000000000000000000000000000..998462efc70d1e565c198cca14e9d87496a3fc84
--- /dev/null
+++ b/libdap-server-udp/test/CMakeLists.txt
@@ -0,0 +1,20 @@
+cmake_minimum_required(VERSION 3.0)
+project(udp-server-test)
+
+set(CMAKE_C_STANDARD 11)
+
+if ( NOT ( TARGET dap_test ) )
+    add_subdirectory(libdap-test)
+endif()
+
+file(GLOB SRC *.h *.c)
+
+add_executable(${PROJECT_NAME} ${SRC})
+
+target_link_libraries(${PROJECT_NAME} dap_test)
+
+add_test(
+    NAME udp-server-test
+    COMMAND udp-server-test
+)
+
diff --git a/libdap-server-udp/test/libdap-test b/libdap-server-udp/test/libdap-test
new file mode 160000
index 0000000000000000000000000000000000000000..b76175acc517f085c319c8e66c62bd143f96bf94
--- /dev/null
+++ b/libdap-server-udp/test/libdap-test
@@ -0,0 +1 @@
+Subproject commit b76175acc517f085c319c8e66c62bd143f96bf94
diff --git a/libdap-server-udp/test/main.c b/libdap-server-udp/test/main.c
new file mode 100755
index 0000000000000000000000000000000000000000..e02c1ef950a56e4077faed96e1ee2f6c5cfe8a3f
--- /dev/null
+++ b/libdap-server-udp/test/main.c
@@ -0,0 +1,5 @@
+#include <stdio.h>
+int main()
+{
+    return 0;
+}