diff --git a/CMakeLists.txt b/CMakeLists.txt
index 1c90d990..ba045021 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -10,6 +10,9 @@ option(WITH_AEON "CryptoNight-Lite support" ON)
option(WITH_HTTPD "HTTP REST API" OFF)
option(WITH_CC_CLIENT "CC Client" ON)
option(WITH_CC_SERVER "CC Server" ON)
+option(WITH_TLS "TLS support" ON)
+set(MINER_EXECUTABLE_NAME "xmrigMiner" CACHE STRING "Miner executable file name")
+set(DAEMON_EXECUTABLE_NAME "xmrigDaemon" CACHE STRING "Daemon executable file name")
include (CheckIncludeFile)
include (cmake/cpu.cmake)
@@ -17,6 +20,8 @@ include (cmake/cpu.cmake)
set(SOURCES
src/api/NetworkState.cpp
src/App.cpp
+ src/3rdparty/clib-net/deps/buffer/buffer.c
+ src/3rdparty/clib-net/src/net.c
src/net/Client.cpp
src/net/Job.cpp
src/net/Network.cpp
@@ -52,6 +57,7 @@ set(SOURCES_COMMON
src/log/Log.cpp
src/Platform.cpp
src/Cpu.cpp
+
)
if (WIN32)
@@ -66,7 +72,7 @@ if (WIN32)
)
add_definitions(/DWIN32)
- set(EXTRA_LIBS ws2_32 psapi iphlpapi userenv)
+ set(EXTRA_LIBS ws2_32 psapi iphlpapi userenv crypt32)
elseif (APPLE)
set(SOURCES_OS
src/App_unix.cpp
@@ -100,6 +106,7 @@ endif()
add_definitions(/D__STDC_FORMAT_MACROS)
add_definitions(/DUNICODE)
+add_definitions(/DMINER_EXECUTABLE_NAME=${MINER_EXECUTABLE_NAME})
#add_definitions(/DAPP_DEBUG)
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake")
@@ -108,6 +115,21 @@ find_package(UV REQUIRED)
include(cmake/flags.cmake)
+if (WITH_TLS)
+ find_package(OpenSSL)
+
+ add_definitions(/DCPPHTTPLIB_OPENSSL_SUPPORT)
+
+ if (OPENSSL_FOUND)
+ include_directories(${OPENSSL_INCLUDE_DIR})
+ set(SOURCES_SSL_TLS src/3rdparty/clib-net/src/tls.c)
+ else()
+ message(FATAL_ERROR "OpenSSL NOT found: use `-DWITH_TLS=OFF` to build without TLS support")
+ endif()
+else()
+ add_definitions(/DXMRIG_NO_TLS)
+endif()
+
if (WITH_LIBCPUID)
add_subdirectory(src/3rdparty/libcpuid)
@@ -154,7 +176,7 @@ if (WITH_CC_SERVER)
if (MHD_FOUND)
include_directories(${MHD_INCLUDE_DIRS})
else()
- message(FATAL_ERROR "microhttpd NOT found: use `-DWITH_CC=OFF` to build without CC Server support")
+ message(FATAL_ERROR "microhttpd NOT found: use `-DWITH_CC_SERVER=OFF` to build without CC Server support")
endif()
set(SOURCES_CC_SERVER
@@ -182,16 +204,23 @@ endif()
include_directories(src)
include_directories(src/3rdparty)
include_directories(${UV_INCLUDE_DIR})
+include_directories(src/3rdparty/clib-net/include)
+include_directories(src/3rdparty/clib-net/deps)
add_library(xmrig_common STATIC ${SOURCES_COMMON})
add_library(xmrig_os_dependencies STATIC ${SOURCES_OS} ${SOURCES_SYSLOG})
add_library(xmrig_cpuid STATIC ${SOURCES_CPUID})
+if (WITH_TLS)
+ add_library(xmrig_tls STATIC ${SOURCES_SSL_TLS})
+endif (WITH_TLS)
+
if (WITH_CC_SERVER OR WITH_CC_CLIENT)
add_library(xmrig_cc_common STATIC ${SOURCES_CC_COMMON})
endif (WITH_CC_SERVER OR WITH_CC_CLIENT)
add_executable(xmrigMiner ${SOURCES} ${SOURCES_CRYPTO} ${HTTPD_SOURCES} ${SOURCES_CC_CLIENT} res/app.rc)
+set_target_properties(xmrigMiner PROPERTIES OUTPUT_NAME ${MINER_EXECUTABLE_NAME})
target_link_libraries(xmrigMiner xmrig_common xmrig_os_dependencies xmrig_cpuid
${UV_LIBRARIES} ${MHD_LIBRARY} ${EXTRA_LIBS} ${CPUID_LIB})
@@ -200,7 +229,12 @@ if (WITH_CC_CLIENT)
target_link_libraries(xmrigMiner xmrig_cc_common)
endif (WITH_CC_CLIENT)
+if (WITH_TLS)
+ target_link_libraries(xmrigMiner xmrig_tls OpenSSL::SSL OpenSSL::Crypto)
+endif (WITH_TLS)
+
add_executable(xmrigDaemon src/cc/XMRigd.cpp res/app.rc)
+set_target_properties(xmrigDaemon PROPERTIES OUTPUT_NAME ${DAEMON_EXECUTABLE_NAME})
if (WITH_CC_SERVER AND MHD_FOUND)
add_library(xmrig_common_cc STATIC ${SOURCES_COMMON})
@@ -208,6 +242,11 @@ if (WITH_CC_SERVER AND MHD_FOUND)
target_link_libraries(xmrigCCServer
xmrig_common_cc xmrig_os_dependencies xmrig_cpuid xmrig_cc_common
${UV_LIBRARIES} ${MHD_LIBRARY} ${EXTRA_LIBS} ${CPUID_LIB})
+
+ if (WITH_TLS)
+ target_link_libraries(xmrigCCServer xmrig_tls OpenSSL::SSL OpenSSL::Crypto)
+ endif (WITH_TLS)
+
set_target_properties(xmrig_common_cc PROPERTIES COMPILE_FLAGS "-DXMRIG_CC_SERVER ${SHARED_FLAGS}")
set_target_properties(xmrigCCServer PROPERTIES COMPILE_FLAGS "-DXMRIG_CC_SERVER ${SHARED_FLAGS}")
endif()
diff --git a/Dockerfile b/Dockerfile
new file mode 100644
index 00000000..863d525e
--- /dev/null
+++ b/Dockerfile
@@ -0,0 +1,17 @@
+FROM ubuntu:latest
+
+RUN apt-get update && \
+ apt-get install software-properties-common git build-essential cmake libuv1-dev libssl-dev -y
+
+RUN add-apt-repository ppa:jonathonf/gcc-7.1 && \
+ apt-get update && \
+ apt-get install gcc-7 g++-7 -y
+
+RUN git clone https://github.com/Bendr0id/xmrigCC.git && \
+ cd xmrigCC && \
+ cmake . -DCMAKE_C_COMPILER=gcc-7 -DCMAKE_CXX_COMPILER=g++-7 -DWITH_CC_SERVER=OFF -DWITH_HTTPD=OFF && \
+ make
+
+COPY Dockerfile /Dockerfile
+
+ENTRYPOINT ["/xmrigCC/xmrigDaemon"]
diff --git a/README.md b/README.md
index 1b5ff905..933b85c1 100644
--- a/README.md
+++ b/README.md
@@ -15,6 +15,7 @@ The modified version can also handle commands like "update config", "start/stop
Full Windows/Linux compatible, and you can mix Linux and Windows miner on one XMRigCCServer.
## Additional features of XMRigCC (on top of XMRig)
+* **NEW: Full SSL/TLS support**
* Command and control server
* CC Dashboard with:
* statistics of all connected miners
@@ -205,7 +206,6 @@ This will limit multihash mode (multihash-factor = 2) to thread 0 and thread 2,
## Other information
* No HTTP support, only stratum protocol support.
-* No TLS support.
### CPU mining performance
diff --git a/appveyor.yml b/appveyor.yml
index 3bd5f886..5951e017 100644
--- a/appveyor.yml
+++ b/appveyor.yml
@@ -1,5 +1,5 @@
# version format
-version: 1.4.{build}
+version: 1.5.{build}
# build only tags
skip_non_tags: true
@@ -16,19 +16,18 @@ clone_folder: c:\xmrigCC
install:
- mkdir c:\xmrigCC-deps
- - curl -sL https://github.com/xmrig/xmrig-deps/releases/download/v2/xmrig-deps-v2.zip -o xmrigCC-deps-v2.zip
- - 7z x xmrigCC-deps-v2.zip -o"c:\xmrigCC-deps" -y > nul
+ - curl -sL https://github.com/Bendr0id/xmrigCC-deps/releases/download/v1/xmrigCC-deps.zip -o xmrigCC-deps.zip
+ - 7z x xmrigCC-deps.zip -o"c:\xmrigCC-deps" -y > nul
build_script:
- call "C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\Common7\Tools\VsMSBuildCmd.bat"
- cd c:\xmrigCC
- mkdir build
- cd build
- - set CMAKE_PREFIX_PATH=c:\xmrigCC-deps\msvc2017\libuv\x64\;c:\xmrigCC-deps\msvc2017\libmicrohttpd\x64\;C:\Tools\vcpkg\installed\x64-windows\
+ - set CMAKE_PREFIX_PATH=c:\xmrigCC-deps\msvc2017\libuv\x64\;c:\xmrigCC-deps\msvc2017\libmicrohttpd\x64\;c:\xmrigCC-deps\msvc2017\openssl\x64\
- cmake -G "Visual Studio 15 2017 Win64" -T v141,host=x64 ..
- msbuild xmrig.sln /p:Configuration=Release
-
after_build:
- cd c:\xmrigCC
- cmd: 7z a xmrigCC-mvc-win64.zip "c:\xmrigCC\build\Release\*.exe" "c:\xmrigCC\src\*config*" "c:\xmrigCC\index.html"
diff --git a/index.html b/index.html
index 09c521a6..b3865c22 100644
--- a/index.html
+++ b/index.html
@@ -46,6 +46,7 @@
+
@@ -112,6 +113,7 @@
{data: "client_status.avg_time", className: "right"},
{data: "client_status.shares_good", className: "right"},
{data: "client_status.shares_total", className: "right"},
+ {data: "client_status.uptime", render: uptime, className: "right"},
{data: "client_status.last_status_update", render: laststatus},
{
data: null,
@@ -450,6 +452,20 @@
});
}
+ function uptime( data, type, row ) {
+ if (type !== 'sort') {
+ var lastStatus = row.client_status.last_status_update * 1000;
+
+ if (isOnline(lastStatus)) {
+ return numeral(data/1000).format('00:00:00:00');
+ } else {
+ return "";
+ }
+ }
+
+ return data;
+ }
+
function laststatus( data, type, row ) {
if (type !== 'sort') {
var date = new Date(data*1000 - clockDrift);
@@ -594,6 +610,7 @@
Shares Good |
Shares Total |
+ Uptime |
Last Update |
Edit |
@@ -615,6 +632,7 @@
|
|
|
+ |
diff --git a/src/3rdparty/clib-net/CHANGELOGS b/src/3rdparty/clib-net/CHANGELOGS
new file mode 100644
index 00000000..602a3244
--- /dev/null
+++ b/src/3rdparty/clib-net/CHANGELOGS
@@ -0,0 +1,16 @@
+
+# Change Logs
+
+2014-4-13(v0.1.1):
+
+* add a fake function: tls_get_peer_cert
+
+* tls_handle_bio_error and tls_handle_ssl_error added for a common usage
+
+* fix a high cpu bug in uv lines
+
+* make SSL_MODE_RELEASE_BUFFERS be gracefully imported
+
+* correct onConnect and onRead for ssl
+
+* fix a memory leak in ssl part
\ No newline at end of file
diff --git a/src/3rdparty/clib-net/Makefile b/src/3rdparty/clib-net/Makefile
new file mode 100644
index 00000000..5c19c896
--- /dev/null
+++ b/src/3rdparty/clib-net/Makefile
@@ -0,0 +1,17 @@
+
+CC ?= gcc
+SRC = $(wildcard src/*.c) tests/simple.c
+DEPS = $(wildcard deps/*/*.c)
+CFLAGS = -std=c++11\
+ -Iinclude\
+ -Isrc\
+ -Ideps\
+ -Ideps/libuv/include\
+ -Ldeps/libuv/build/Release\
+ -Wall -Wno-unused-function
+LDFLAGS = -lcrypto -lssl -luv
+
+test: $(SRC)
+ $(CC) $(CFLAGS) -o $@ $(SRC) $(DEPS) $(LDFLAGS)
+
+.PHONY: test
diff --git a/src/3rdparty/clib-net/deps/buffer/History.md b/src/3rdparty/clib-net/deps/buffer/History.md
new file mode 100644
index 00000000..86de93b4
--- /dev/null
+++ b/src/3rdparty/clib-net/deps/buffer/History.md
@@ -0,0 +1,40 @@
+
+0.4.0 / 2015-01-05
+==================
+
+ * refactor
+ * buffer: Remove printf() statement
+ * Add `buffer_appendf()` (#10, marcomorain)
+
+0.3.0 / 2014-12-24
+==================
+
+ * travis: Fail the build if any memory is leaked
+ * test: Fix memory leaks
+ * travis: setup
+ * Add `buffer_append_n(buffer_t *, const char *, size_t)`
+
+0.2.1 / 2014-12-23
+==================
+
+ * fix header guard
+ * fix compilation on linux
+ * Add missing null terminator after realloc (buffer resize)
+ * Make it safe to always use `data` as a character string
+
+0.2.0 / 2013-01-05
+==================
+
+ * add print_buffer()
+ * add buffer_compact()
+
+0.1.0 / 2012-12-26
+==================
+
+ * add trim functions
+ * add buffer_clear(buffer_t *self)
+ * add buffer_fill(buffer_t *self, int c)
+ * add buffer_new_with_string_length(char *str, size_t len)
+ * add buffer_new_with_copy(char *str)
+ * add buffer_indexof()
+
diff --git a/src/3rdparty/clib-net/deps/buffer/Makefile b/src/3rdparty/clib-net/deps/buffer/Makefile
new file mode 100644
index 00000000..e2f516c8
--- /dev/null
+++ b/src/3rdparty/clib-net/deps/buffer/Makefile
@@ -0,0 +1,6 @@
+
+test: buffer.c test.c
+ @$(CC) $^ -std=c99 -o $@
+ @./test
+
+.PHONY: test
diff --git a/src/3rdparty/clib-net/deps/buffer/Readme.md b/src/3rdparty/clib-net/deps/buffer/Readme.md
new file mode 100644
index 00000000..c620ea0d
--- /dev/null
+++ b/src/3rdparty/clib-net/deps/buffer/Readme.md
@@ -0,0 +1,82 @@
+
+# buffer
+
+ Tiny C string manipulation library.
+
+## Installation
+
+ Install with [clib](https://github.com/clibs/clib):
+
+```
+$ clib install clibs/buffer
+```
+
+## API
+
+```c
+buffer_t *
+buffer_new();
+
+buffer_t *
+buffer_new_with_size(size_t n);
+
+buffer_t *
+buffer_new_with_string(char *str);
+
+buffer_t *
+buffer_new_with_string_length(char *str, size_t len);
+
+buffer_t *
+buffer_new_with_copy(char *str);
+
+size_t
+buffer_size(buffer_t *self);
+
+size_t
+buffer_length(buffer_t *self);
+
+void
+buffer_free(buffer_t *self);
+
+int
+buffer_prepend(buffer_t *self, char *str);
+
+int
+buffer_append(buffer_t *self, char *str);
+
+int
+buffer_equals(buffer_t *self, buffer_t *other);
+
+ssize_t
+buffer_indexof(buffer_t *self, char *str);
+
+buffer_t *
+buffer_slice(buffer_t *self, size_t from, ssize_t to);
+
+ssize_t
+buffer_compact(buffer_t *self);
+
+void
+buffer_fill(buffer_t *self, int c);
+
+void
+buffer_clear(buffer_t *self);
+
+void
+buffer_trim_left(buffer_t *self);
+
+void
+buffer_trim_right(buffer_t *self);
+
+void
+buffer_trim(buffer_t *self);
+
+void
+buffer_print(buffer_t *self);
+
+#define buffer_string(self) (self->data)
+```
+
+## License
+
+ MIT
diff --git a/src/3rdparty/clib-net/deps/buffer/buffer.c b/src/3rdparty/clib-net/deps/buffer/buffer.c
new file mode 100644
index 00000000..c11b67fd
--- /dev/null
+++ b/src/3rdparty/clib-net/deps/buffer/buffer.c
@@ -0,0 +1,353 @@
+//
+// buffer.c
+//
+// Copyright (c) 2012 TJ Holowaychuk
+//
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include "buffer.h"
+
+// TODO: shared with reference counting
+// TODO: linked list for append/prepend etc
+
+/*
+ * Compute the nearest multiple of `a` from `b`.
+ */
+
+#define nearest_multiple_of(a, b) \
+ (((b) + ((a) - 1)) & ~((a) - 1))
+
+/*
+ * Allocate a new buffer with BUFFER_DEFAULT_SIZE.
+ */
+
+buffer_t *
+buffer_new() {
+ return buffer_new_with_size(BUFFER_DEFAULT_SIZE);
+}
+
+/*
+ * Allocate a new buffer with `n` bytes.
+ */
+
+buffer_t *
+buffer_new_with_size(size_t n) {
+ buffer_t *self = malloc(sizeof(buffer_t));
+ if (!self) return NULL;
+ self->len = n;
+ self->data = self->alloc = calloc(n + 1, 1);
+ return self;
+}
+
+/*
+ * Allocate a new buffer with `str`.
+ */
+
+buffer_t *
+buffer_new_with_string(char *str) {
+ return buffer_new_with_string_length(str, strlen(str));
+}
+
+/*
+ * Allocate a new buffer with `str` and `len`.
+ */
+
+buffer_t *
+buffer_new_with_string_length(char *str, size_t len) {
+ buffer_t *self = malloc(sizeof(buffer_t));
+ if (!self) return NULL;
+ self->len = len;
+ self->data = self->alloc = str;
+ return self;
+}
+
+/*
+ * Allocate a new buffer with a copy of `str`.
+ */
+
+buffer_t *
+buffer_new_with_copy(char *str) {
+ size_t len = strlen(str);
+ buffer_t *self = buffer_new_with_size(len);
+ if (!self) return NULL;
+ memcpy(self->alloc, str, len);
+ self->data = self->alloc;
+ return self;
+}
+
+/*
+ * Deallocate excess memory, the number
+ * of bytes removed or -1.
+ */
+
+ssize_t
+buffer_compact(buffer_t *self) {
+ size_t len = buffer_length(self);
+ size_t rem = self->len - len;
+ char *buf = calloc(len + 1, 1);
+ if (!buf) return -1;
+ memcpy(buf, self->data, len);
+ free(self->alloc);
+ self->len = len;
+ self->data = self->alloc = buf;
+ return rem;
+}
+
+/*
+ * Free the buffer.
+ */
+
+void
+buffer_free(buffer_t *self) {
+ free(self->alloc);
+ free(self);
+}
+
+/*
+ * Return buffer size.
+ */
+
+size_t
+buffer_size(buffer_t *self) {
+ return self->len;
+}
+
+/*
+ * Return string length.
+ */
+
+size_t
+buffer_length(buffer_t *self) {
+ return strlen(self->data);
+}
+
+/*
+ * Resize to hold `n` bytes.
+ */
+
+int
+buffer_resize(buffer_t *self, size_t n) {
+ n = nearest_multiple_of(1024, n);
+ self->len = n;
+ self->alloc = self->data = realloc(self->alloc, n + 1);
+ if (!self->alloc) return -1;
+ self->alloc[n] = '\0';
+ return 0;
+}
+
+/*
+ * Append a printf-style formatted string to the buffer.
+ */
+
+int buffer_appendf(buffer_t *self, const char *format, ...) {
+ va_list ap;
+ va_list tmpa;
+ char *dst = NULL;
+ int length = 0;
+ int required = 0;
+ int bytes = 0;
+
+ va_start(ap, format);
+
+ length = buffer_length(self);
+
+ // First, we compute how many bytes are needed
+ // for the formatted string and allocate that
+ // much more space in the buffer.
+ va_copy(tmpa, ap);
+ required = vsnprintf(NULL, 0, format, tmpa);
+ va_end(tmpa);
+ if (-1 == buffer_resize(self, length + required)) {
+ va_end(ap);
+ return -1;
+ }
+
+ // Next format the string into the space that we
+ // have made room for.
+ dst = self->data + length;
+ bytes = vsnprintf(dst, 1 + required, format, ap);
+ va_end(ap);
+
+ return bytes < 0
+ ? -1
+ : 0;
+}
+
+/*
+ * Append `str` to `self` and return 0 on success, -1 on failure.
+ */
+
+int
+buffer_append(buffer_t *self, const char *str) {
+ return buffer_append_n(self, str, strlen(str));
+}
+
+/*
+ * Append the first `len` bytes from `str` to `self` and
+ * return 0 on success, -1 on failure.
+ */
+int
+buffer_append_n(buffer_t *self, const char *str, size_t len) {
+ size_t prev = strlen(self->data);
+ size_t needed = len + prev;
+
+ // enough space
+ if (self->len > needed) {
+ strncat(self->data, str, len);
+ return 0;
+ }
+
+ // resize
+ int ret = buffer_resize(self, needed);
+ if (-1 == ret) return -1;
+ strncat(self->data, str, len);
+
+ return 0;
+}
+
+/*
+ * Prepend `str` to `self` and return 0 on success, -1 on failure.
+ */
+
+int
+buffer_prepend(buffer_t *self, char *str) {
+ size_t len = strlen(str);
+ size_t prev = strlen(self->data);
+ size_t needed = len + prev;
+
+ // enough space
+ if (self->len > needed) goto move;
+
+ // resize
+ int ret = buffer_resize(self, needed);
+ if (-1 == ret) return -1;
+
+ // move
+ move:
+ memmove(self->data + len, self->data, len + 1);
+ memcpy(self->data, str, len);
+
+ return 0;
+}
+
+/*
+ * Return a new buffer based on the `from..to` slice of `buf`,
+ * or NULL on error.
+ */
+
+buffer_t *
+buffer_slice(buffer_t *buf, size_t from, ssize_t to) {
+ size_t len = strlen(buf->data);
+
+ // bad range
+ if (to < from) return NULL;
+
+ // relative to end
+ if (to < 0) to = len - ~to;
+
+ // cap end
+ if (to > len) to = len;
+
+ size_t n = to - from;
+ buffer_t *self = buffer_new_with_size(n);
+ memcpy(self->data, buf->data + from, n);
+ return self;
+}
+
+/*
+ * Return 1 if the buffers contain equivalent data.
+ */
+
+int
+buffer_equals(buffer_t *self, buffer_t *other) {
+ return 0 == strcmp(self->data, other->data);
+}
+
+/*
+ * Return the index of the substring `str`, or -1 on failure.
+ */
+
+ssize_t
+buffer_indexof(buffer_t *self, char *str) {
+ char *sub = strstr(self->data, str);
+ if (!sub) return -1;
+ return sub - self->data;
+}
+
+/*
+ * Trim leading whitespace.
+ */
+
+void
+buffer_trim_left(buffer_t *self) {
+ int c;
+ while ((c = *self->data) && isspace(c)) {
+ ++self->data;
+ }
+}
+
+/*
+ * Trim trailing whitespace.
+ */
+
+void
+buffer_trim_right(buffer_t *self) {
+ int c;
+ size_t i = buffer_length(self) - 1;
+ while ((c = self->data[i]) && isspace(c)) {
+ self->data[i--] = 0;
+ }
+}
+
+/*
+ * Trim trailing and leading whitespace.
+ */
+
+void
+buffer_trim(buffer_t *self) {
+ buffer_trim_left(self);
+ buffer_trim_right(self);
+}
+
+/*
+ * Fill the buffer with `c`.
+ */
+
+void
+buffer_fill(buffer_t *self, int c) {
+ memset(self->data, c, self->len);
+}
+
+/*
+ * Fill the buffer with 0.
+ */
+
+void
+buffer_clear(buffer_t *self) {
+ buffer_fill(self, 0);
+}
+
+/*
+ * Print a hex dump of the buffer.
+ */
+
+void
+buffer_print(buffer_t *self) {
+ int i;
+ size_t len = self->len;
+
+ printf("\n ");
+
+ // hex
+ for (i = 0; i < len; ++i) {
+ printf(" %02x", self->alloc[i]);
+ if ((i + 1) % 8 == 0) printf("\n ");
+ }
+
+ printf("\n");
+}
diff --git a/src/3rdparty/clib-net/deps/buffer/buffer.h b/src/3rdparty/clib-net/deps/buffer/buffer.h
new file mode 100644
index 00000000..f2784e13
--- /dev/null
+++ b/src/3rdparty/clib-net/deps/buffer/buffer.h
@@ -0,0 +1,106 @@
+
+//
+// buffer.h
+//
+// Copyright (c) 2012 TJ Holowaychuk
+//
+
+#ifndef BUFFER_H
+#define BUFFER_H 1
+
+#include
+
+#if defined(_MSC_VER)
+#include
+typedef SSIZE_T ssize_t;
+#endif
+
+/*
+ * Default buffer size.
+ */
+
+#ifndef BUFFER_DEFAULT_SIZE
+#define BUFFER_DEFAULT_SIZE 64
+#endif
+
+/*
+ * Buffer struct.
+ */
+
+typedef struct {
+ size_t len;
+ char *alloc;
+ char *data;
+} buffer_t;
+
+// prototypes
+
+buffer_t *
+buffer_new();
+
+buffer_t *
+buffer_new_with_size(size_t n);
+
+buffer_t *
+buffer_new_with_string(char *str);
+
+buffer_t *
+buffer_new_with_string_length(char *str, size_t len);
+
+buffer_t *
+buffer_new_with_copy(char *str);
+
+size_t
+buffer_size(buffer_t *self);
+
+size_t
+buffer_length(buffer_t *self);
+
+void
+buffer_free(buffer_t *self);
+
+int
+buffer_prepend(buffer_t *self, char *str);
+
+int
+buffer_append(buffer_t *self, const char *str);
+
+int
+buffer_appendf(buffer_t *self, const char *format, ...);
+
+int
+buffer_append_n(buffer_t *self, const char *str, size_t len);
+
+int
+buffer_equals(buffer_t *self, buffer_t *other);
+
+ssize_t
+buffer_indexof(buffer_t *self, char *str);
+
+buffer_t *
+buffer_slice(buffer_t *self, size_t from, ssize_t to);
+
+ssize_t
+buffer_compact(buffer_t *self);
+
+void
+buffer_fill(buffer_t *self, int c);
+
+void
+buffer_clear(buffer_t *self);
+
+void
+buffer_trim_left(buffer_t *self);
+
+void
+buffer_trim_right(buffer_t *self);
+
+void
+buffer_trim(buffer_t *self);
+
+void
+buffer_print(buffer_t *self);
+
+#define buffer_string(self) (self->data)
+
+#endif
diff --git a/src/3rdparty/clib-net/include/net.h b/src/3rdparty/clib-net/include/net.h
new file mode 100644
index 00000000..3ed2a9c3
--- /dev/null
+++ b/src/3rdparty/clib-net/include/net.h
@@ -0,0 +1,162 @@
+
+/*
+ * Copyright 2014
+ */
+
+#ifndef __NET_H__
+#define __NET_H__
+
+#include
+#include
+
+#ifndef XMRIG_NO_TLS
+#include "tls.h"
+#endif
+
+#define NOT_SSL 0x00
+#define USE_SSL 0x01
+
+#define NET_OK 0
+#define NET_VERSION_MAJOR 0
+#define NET_VERSION_MINOR 1
+#define NET_VERSION_PATCH 2
+#define NET_VERSION_IS_RELEASE 0
+
+typedef struct net_s net_t;
+typedef struct addrinfo net_ai;
+typedef struct sockaddr_in socketPair_t;
+
+
+struct net_s {
+ char *hostname;
+ int port;
+ int connected;
+ uv_getaddrinfo_t *resolver;
+ uv_loop_t *loop;
+ uv_tcp_t *handle;
+ uv_connect_t *conn;
+ int use_ssl;
+ int tls_established;
+
+#ifndef XMRIG_NO_TLS
+ tls_t *tls;
+#endif
+
+ void *data;
+ void (*conn_cb)(net_t*);
+ void (*read_cb)(net_t*, size_t, char*);
+ void (*error_cb)(net_t*, int, char*);
+ void (*close_cb)(uv_handle_t*);
+};
+
+/*
+ * Create an new network.
+ */
+net_t *
+net_new(char * hostname, int port);
+
+
+#ifndef XMRIG_NO_TLS
+/*
+ * Set SSL's Context
+ */
+int
+net_set_tls(net_t * net, tls_ctx * ctx);
+#endif
+/*
+ * Do connect to new
+ */
+int
+net_connect(net_t * net);
+
+/*
+ * Just close the holding connection
+ */
+int
+net_close(net_t * net, void (*cb)(uv_handle_t*));
+
+/*
+ * free connection
+ */
+int
+net_free(net_t * net);
+
+/*
+ * real free function
+ */
+void
+net_free_cb(uv_handle_t * handle);
+
+/*
+ * DNS resolve
+ */
+int
+net_resolve(net_t * net);
+
+/*
+ * DNS -> IP done, and call `net_resolve_cb`
+ */
+void
+net_resolve_cb(uv_getaddrinfo_t *rv, int stat, net_ai * ai);
+
+/*
+ * connect created, and call `net_connect_cb`
+ */
+void
+net_connect_cb(uv_connect_t *conn, int stat);
+
+/*
+ * realloc buffer before you read
+ */
+void
+net_alloc(uv_handle_t* handle, size_t size, uv_buf_t* buf);
+
+/*
+ * read buffer
+ */
+void
+net_read(uv_stream_t* handle, ssize_t nread, const uv_buf_t* buf);
+
+/*
+ * write buffer
+ */
+int
+net_write(net_t * net, char * buf);
+
+/*
+ * write buffer with length specified
+ */
+int
+net_write2(net_t * net, char * buf, unsigned int len);
+
+/*
+ * return use_ssl
+ */
+int
+net_use_ssl(net_t * net);
+
+/*
+ * continue to read after on data
+ */
+int
+net_resume(net_t * net);
+
+/*
+ * pause read
+ */
+int
+net_pause(net_t * net);
+
+/*
+ * set error_cb
+ */
+int
+net_set_error_cb(net_t * net, void * cb);
+
+/*
+ * write buffer, and call `net_write_cb`.
+ */
+void
+net_write_cb(uv_write_t *writer, int stat);
+
+#endif /* __NET_H__ */
\ No newline at end of file
diff --git a/src/3rdparty/clib-net/include/tls.h b/src/3rdparty/clib-net/include/tls.h
new file mode 100644
index 00000000..76ca8fd0
--- /dev/null
+++ b/src/3rdparty/clib-net/include/tls.h
@@ -0,0 +1,133 @@
+
+/*
+ * Copyright 2014
+ */
+
+#ifndef __TLS_H__
+#define __TLS_H__
+
+#include
+#include
+#include
+#include
+#include
+
+#define SSL_CHUNK_SIZE 512
+
+typedef SSL_CTX tls_ctx;
+typedef struct tls_s {
+ SSL_CTX * ctx;
+ SSL * ssl;
+ BIO * bio_in;
+ BIO * bio_out;
+ buffer_t * buffer;
+ int connected;
+ char * data;
+ char buf[SSL_CHUNK_SIZE]; /* internal usage */
+} tls_t;
+
+static const int X509_NAME_FLAGS = ASN1_STRFLGS_ESC_CTRL
+ | ASN1_STRFLGS_ESC_MSB
+ | XN_FLAG_SEP_MULTILINE
+ | XN_FLAG_FN_SN;
+
+/*
+ * initialize the ssl
+ */
+void
+ssl_init();
+
+/*
+ * destroy the ssl settings and internal tables
+ */
+void
+ssl_destroy();
+
+/*
+ * create a context for ssl
+ */
+tls_ctx *
+tls_ctx_new();
+
+/*
+ * create a tls instance
+ */
+tls_t *
+tls_create(tls_ctx * ctx);
+
+/*
+ * shutdown tls
+ */
+int
+tls_shutdown(tls_t * tls);
+
+/*
+ * destroy a tls instance
+ */
+int
+tls_free(tls_t * tls);
+
+/*
+ * get peer certification info
+ */
+int
+tls_get_peer_cert(tls_t * tls);
+
+/*
+ * do connect to tls
+ */
+int
+tls_connect(tls_t * tls);
+
+/*
+ * handle error in bio
+ */
+int
+tls_handle_bio_error(tls_t * tls, int err);
+
+/*
+ * handle error in ssl
+ */
+int
+tls_handle_ssl_error(tls_t *tls, int err);
+
+/*
+ * a port in tls for `bio_read`
+ */
+int
+tls_bio_read(tls_t * tls, int len);
+
+/*
+ * a port in tls for `bio_write`
+ */
+int
+tls_bio_write(tls_t * tls, char * written, int len);
+
+/*
+ * read
+ */
+int
+tls_read(tls_t * tls);
+
+/*
+ * write
+ */
+int
+tls_write(tls_t * tls, char * written, int len);
+
+/*
+ * write a tls packet
+ */
+#define REQUEST_TLS_WRITE(name, cmd, read, req) do { \
+ tls_write(req->tls, cmd); \
+ do { \
+ read = tls_bio_read(req->tls, 0); \
+ if (read > 0) { \
+ REQUEST_WRITE(req, req->tls->buf, read, name); \
+ } \
+ } while (read > 0); \
+} \
+while (0)
+
+
+#endif /* __TLS_H__ */
\ No newline at end of file
diff --git a/src/3rdparty/clib-net/readme.md b/src/3rdparty/clib-net/readme.md
new file mode 100644
index 00000000..b034d353
--- /dev/null
+++ b/src/3rdparty/clib-net/readme.md
@@ -0,0 +1,53 @@
+
+# net-client
+
+Simple network client
+
+### Requirement
+
+* libuv 0.10.x
+
+* buffer 0.2.0
+
+### Installation
+
+```sh
+$ clib install clibs/net
+$ git clone https://github.com/joyent/libuv.git deps/libuv
+$ checkout v0.10.25
+```
+
+### Run tests
+
+```sh
+make test
+./test
+```
+
+### Example
+
+```c
+static void
+imap_parser(net_t * net, size_t read, char * buf) {
+ printf("%s\n", buf);
+ printf("%zu\n", read);
+}
+
+int
+main(int argc, char *argv[]) {
+ ssl_init();
+ tls_ctx * ctx = tls_ctx_new();
+ net_t * net = net_new("imap.gmail.com", 993);
+ net->onRead = imap_parser;
+
+ // convert this socket to ssl
+ net_set_tls(net, ctx);
+ net_connect(net);
+
+ uv_run(net->loop, UV_RUN_DEFAULT);
+}
+```
+
+### License
+
+MIT
diff --git a/src/3rdparty/clib-net/src/net.c b/src/3rdparty/clib-net/src/net.c
new file mode 100644
index 00000000..69a7f596
--- /dev/null
+++ b/src/3rdparty/clib-net/src/net.c
@@ -0,0 +1,392 @@
+
+#include
+#include
+#include "net.h"
+
+net_t *
+net_new(char * hostname, int port) {
+ net_t * net = (net_t*) malloc(sizeof(net_t));
+ net->loop = uv_default_loop();
+ net->hostname = hostname;
+ net->port = port;
+ net->connected = 0;
+ net->tls_established = 0;
+ net->use_ssl = 0;
+ net->conn_cb = NULL;
+ net->read_cb = NULL;
+ net->error_cb = NULL;
+ net->close_cb = NULL;
+ net->handle = (uv_tcp_t *) malloc(sizeof(uv_tcp_t));
+ net->conn = (uv_connect_t *) malloc(sizeof(uv_connect_t));
+ net->handle->data
+ = net->conn->data
+ = (void *) net;
+
+ return net;
+}
+
+#ifndef XMRIG_NO_TLS
+int
+net_set_tls(net_t * net, tls_ctx * ctx) {
+ net->use_ssl = USE_SSL;
+ net->tls = tls_create(ctx);
+ return NET_OK;
+}
+#endif
+
+int
+net_connect(net_t * net) {
+ net_resolve(net);
+ return NET_OK;
+}
+
+int
+net_close(net_t * net, void (*cb)(uv_handle_t*)) {
+ int r = net->connected;
+ if (r == 1) {
+ net->connected = 0;
+ net->tls_established = 0;
+
+#ifndef XMRIG_NO_TLS
+ if (net->use_ssl) {
+ tls_shutdown(net->tls);
+ }
+#endif
+
+ uv_close((uv_handle_t*)net->handle, cb);
+
+#ifndef XMRIG_NO_TLS
+ if (net->use_ssl) {
+ tls_free(net->tls);
+ }
+#endif
+ }
+
+ return r;
+}
+
+int
+net_free(net_t * net) {
+ net_close(net, NULL);
+ free(net->resolver);
+ free(net);
+ return NET_OK;
+}
+
+void
+net_free_cb(uv_handle_t * handle) {
+ net_t * net = (net_t *) handle->data;
+ if (net->handle != NULL) {
+ free(net->handle);
+ net->handle = NULL;
+ }
+ if (net->conn != NULL) {
+ free(net->conn);
+ net->conn = NULL;
+ }
+ if (net->resolver != NULL) {
+ free(net->resolver);
+ net->resolver = NULL;
+ }
+ if (net != NULL) {
+ free(net);
+ net = NULL;
+ }
+}
+
+int
+net_resolve(net_t * net) {
+ net_ai hints;
+ int ret;
+ char buf[6];
+
+ snprintf(buf, sizeof(buf), "%d", net->port);
+ memset(&hints, 0, sizeof(struct addrinfo));
+ hints.ai_family = AF_INET;
+ hints.ai_socktype = SOCK_STREAM;
+
+ net->resolver = malloc(sizeof(uv_getaddrinfo_t));
+ if (!net->resolver) {
+ /*
+ * TODO(Yorkie): depent parital handles
+ */
+ return -1;
+ }
+
+ net->resolver->data = (void *) net;
+ ret = uv_getaddrinfo(net->loop, net->resolver,
+ net_resolve_cb, net->hostname, NULL, &hints);
+
+ return ret;
+}
+
+void
+net_resolve_cb(uv_getaddrinfo_t *rv, int err, net_ai * ai) {
+ net_t * net = (net_t*) rv->data;
+ char addr[INET6_ADDRSTRLEN];
+ int ret;
+ struct sockaddr_in dest;
+
+ if (err != 0) {
+ if (net->error_cb) {
+ net->error_cb(net, err, (char *) uv_strerror(err));
+ } else {
+ printf("error(%s:%d) %s", net->hostname, net->port, (char *) uv_strerror(err));
+ net_free(net);
+ }
+ return;
+ }
+
+ uv_ip4_name((socketPair_t *) ai->ai_addr, addr, INET6_ADDRSTRLEN);
+ ret = uv_ip4_addr(addr, net->port, &dest);
+
+ if (ret != 0) {
+ if (net->error_cb) {
+ net->error_cb(net, ret, (char *) uv_strerror(err));
+ } else {
+ printf("error(%s:%d) %s", net->hostname, net->port, (char *) uv_strerror(err));
+ net_free(net);
+ }
+ return;
+ }
+
+ /*
+ * create tcp instance.
+ */
+ uv_tcp_init(net->loop, net->handle);
+ ret = uv_tcp_connect(net->conn, net->handle, (const struct sockaddr*) &dest, net_connect_cb);
+ if (ret != NET_OK) {
+ if (net->error_cb) {
+ net->error_cb(net, ret, (char *) uv_strerror(err));
+ } else {
+ printf("error(%s:%d) %s", net->hostname, net->port, (char *) uv_strerror(err));
+ net_free(net);
+ }
+ return;
+ }
+
+ /*
+ * free
+ */
+ uv_freeaddrinfo(ai);
+}
+
+void
+net_connect_cb(uv_connect_t *conn, int err) {
+ net_t * net = (net_t *) conn->data;
+ int read;
+
+ if (err < 0) {
+ if (net->error_cb) {
+ net->error_cb(net, err, (char *) uv_strerror(err));
+ } else {
+ printf("error(%s:%d) %s", net->hostname, net->port, (char *) uv_strerror(err));
+ net_free(net);
+ }
+ return;
+ }
+
+ /*
+ * change the `connected` state
+ */
+ net->connected = 1;
+
+ /*
+ * read buffers via uv
+ */
+ uv_read_start((uv_stream_t *) net->handle, net_alloc, net_read);
+
+ /*
+ * call `onConnect`, the tcp connection has been
+ * established in user-land.
+ */
+ if (net->use_ssl == NOT_SSL && net->conn_cb != NULL) {
+ net->conn_cb(net);
+ }
+
+#ifndef XMRIG_NO_TLS
+ /*
+ * Handle TLS Partial
+ */
+ if (net->use_ssl == USE_SSL && tls_connect(net->tls) == NET_OK) {
+ read = 0;
+ do {
+ read = tls_bio_read(net->tls, 0);
+ if (read > 0) {
+ char* buf = (char *) calloc(read, 1);
+ uv_write_t * req = malloc(sizeof(uv_write_t));
+ req->data = net;
+ memset(buf, 0, read);
+ memcpy(buf, net->tls->buf, read);
+ uv_buf_t uvbuf = uv_buf_init(buf, read);
+ uv_write(req, (uv_stream_t*)net->handle, &uvbuf, 1, net_write_cb);
+ free(buf);
+ }
+ } while (read > 0);
+ }
+#endif
+}
+
+void
+net_alloc(uv_handle_t* handle, size_t size, uv_buf_t* buf) {
+ buf->base = (char *) calloc(size, 1);
+ buf->len = size;
+}
+
+void
+net_read(uv_stream_t* handle, ssize_t nread, const uv_buf_t* buf) {
+ net_t * net = (net_t *) handle->data;
+
+ if (nread < 0) {
+ if (net->error_cb) {
+ net->error_cb(net, nread, (char *) uv_strerror(nread));
+ } else {
+ printf("error(%s:%d) %s", net->hostname, net->port, (char *) uv_strerror(nread));
+ net_free(net);
+ }
+ return;
+ }
+
+#ifndef XMRIG_NO_TLS
+ /*
+ * BIO Return rule:
+ * All these functions return either the amount of data successfully
+ * read or written (if the return value is positive) or that no data
+ * was successfully read or written if the result is 0 or -1. If the
+ * return value is -2 then the operation is not implemented in the specific BIO type.
+ */
+ if (net->use_ssl) {
+ tls_bio_write(net->tls, buf->base, nread);
+ free(buf->base);
+
+ int read = 0;
+ int stat = tls_read(net->tls);
+ if (stat == 1) {
+ /*
+ * continue: Say hello
+ */
+ do {
+ read = tls_bio_read(net->tls, 0);
+ if (read > 0) {
+ char* buf2 = (char *) calloc(read, 1);
+ uv_write_t * req = malloc(sizeof(uv_write_t));
+ req->data = net;
+ memset(buf2, 0, read);
+ memcpy(buf2, net->tls->buf, read);
+ uv_buf_t uvbuf = uv_buf_init(buf2, read);
+ uv_write(req, (uv_stream_t*)net->handle, &uvbuf, 1, net_write_cb);
+ free(buf2);
+ }
+ } while (read > 0);
+
+ } else {
+ /*
+ * SSL Connection is created
+ * Here need to call user-land callback
+ */
+ if (!net->tls_established) {
+ net->tls_established = 1;
+ if (net->conn_cb != NULL) {
+ net->conn_cb(net);
+ }
+ }
+
+ /*
+ * read buffer
+ */
+ if (stat == 0) {
+ if (buffer_string(net->tls->buffer) > 0)
+ // uv_read_stop((uv_stream_t*)net->handle);
+
+ if (net->read_cb != NULL && net->connected && net->tls_established) {
+ net->read_cb(net, buffer_length(net->tls->buffer),
+ buffer_string(net->tls->buffer));
+ }
+ }
+ }
+ return;
+ }
+#endif
+
+ /*
+ * TCP Part, no SSL, just proxy of uv.
+ */
+ uv_read_stop(handle);
+ buf->base[nread] = 0;
+ if (net->read_cb != NULL) {
+ net->read_cb(net, nread, buf->base);
+ free(buf->base);
+ }
+}
+
+int
+net_write(net_t * net, char * buf) {
+ return net_write2(net, buf, strlen(buf));
+}
+
+int
+net_write2(net_t * net, char * buf, unsigned int len) {
+ uv_write_t * req;
+ uv_buf_t uvbuf;
+ int read = 0;
+
+ switch (net->use_ssl) {
+ case USE_SSL:
+#ifndef XMRIG_NO_TLS
+ tls_write(net->tls, buf, (int)len);
+ do {
+ read = tls_bio_read(net->tls, 0);
+ if (read > 0) {
+ req = (uv_write_t *) malloc(sizeof(uv_write_t));
+ req->data = net;
+ uvbuf = uv_buf_init(net->tls->buf, read);
+ uv_write(req, (uv_stream_t*)net->handle,
+ &uvbuf,
+ 1,
+ net_write_cb);
+ }
+ } while (read > 0);
+ break;
+#endif
+ case NOT_SSL:
+ req = (uv_write_t *) malloc(sizeof(uv_write_t));
+ req->data = net;
+ uvbuf = uv_buf_init(buf, len);
+ uv_write(req, (uv_stream_t*)net->handle,
+ &uvbuf,
+ 1,
+ net_write_cb);
+ break;
+ }
+
+ return NET_OK;
+}
+
+int
+net_use_ssl(net_t * net) {
+ return net->use_ssl == USE_SSL;
+}
+
+int
+net_resume(net_t * net) {
+ uv_read_start((uv_stream_t *)net->handle, net_alloc, net_read);
+ return NET_OK;
+}
+
+int
+net_pause(net_t * net) {
+ uv_read_stop((uv_stream_t *)net->handle);
+ return NET_OK;
+}
+
+int
+net_set_error_cb(net_t * net, void * cb) {
+ net->error_cb = cb;
+ return NET_OK;
+}
+
+void
+net_write_cb(uv_write_t *req, int stat) {
+ net_resume((net_t*)req->data);
+ free(req);
+}
diff --git a/src/3rdparty/clib-net/src/tls.c b/src/3rdparty/clib-net/src/tls.c
new file mode 100644
index 00000000..26d2e1b4
--- /dev/null
+++ b/src/3rdparty/clib-net/src/tls.c
@@ -0,0 +1,221 @@
+
+/*
+ * Copyright 2014
+ */
+
+#include
+#include "tls.h"
+
+void
+ssl_init() {
+ SSL_library_init();
+ OpenSSL_add_all_algorithms();
+ SSL_load_error_strings();
+ ERR_load_crypto_strings();
+}
+
+void
+ssl_destroy() {
+ EVP_cleanup();
+ ERR_free_strings();
+}
+
+tls_ctx *
+tls_ctx_new() {
+ tls_ctx *ctx = SSL_CTX_new(SSLv23_method());
+#ifdef SSL_OP_NO_COMPRESSION
+ SSL_CTX_set_options(ctx, SSL_OP_NO_COMPRESSION);
+#endif
+
+ return ctx;
+}
+
+tls_t *
+tls_create(tls_ctx *ctx) {
+ tls_t * tls = (tls_t *) malloc(sizeof(tls_t)+1);
+ if (tls == NULL)
+ fprintf(stderr, "tls> %s", "Out of Memory");
+
+ tls->ctx = ctx;
+ tls->ssl = SSL_new(tls->ctx);
+ tls->bio_in = BIO_new(BIO_s_mem());
+ tls->bio_out = BIO_new(BIO_s_mem());
+ tls->connected = -1;
+ tls->buffer = buffer_new();
+
+#ifdef SSL_MODE_RELEASE_BUFFERS
+ long mode = SSL_get_mode(tls->ssl);
+ SSL_set_mode(tls->ssl, mode | SSL_MODE_RELEASE_BUFFERS);
+#endif
+
+ if (tls->ssl == NULL)
+ printf("tls> %s", "Out of Memory");
+
+ SSL_set_connect_state(tls->ssl);
+ SSL_set_bio(tls->ssl, tls->bio_in, tls->bio_out);
+ return tls;
+}
+
+int
+tls_shutdown(tls_t * tls) {
+ assert(tls != NULL);
+ if (SSL_shutdown(tls->ssl) == 0) {
+ SSL_shutdown(tls->ssl);
+ }
+ return 0;
+}
+
+int
+tls_free(tls_t * tls) {
+ if (tls->ssl) {
+ SSL_free(tls->ssl);
+ SSL_CTX_free(tls->ctx);
+ tls->ssl = NULL;
+ }
+
+ buffer_free(tls->buffer);
+ free(tls);
+ return 0;
+}
+
+int
+tls_get_peer_cert(tls_t *tls) {
+ X509* peer_cert = SSL_get_peer_certificate(tls->ssl);
+ if (peer_cert != NULL) {
+ /*
+ * TODO(Yorkie): This function is used just for debug
+ */
+ X509_free(peer_cert);
+ }
+ return 0;
+}
+
+int
+tls_connect(tls_t *tls) {
+ int rv;
+ int er;
+
+ rv = SSL_do_handshake(tls->ssl);
+ if (rv == 1) {
+ /*
+ * `SSL_do_handshake()` could not return 1,
+ * that caused no message could be returned in `SSL_get_error()`.
+ * TODO(Yorkie): handle error, exit?
+ */
+ return -1;
+ }
+
+ if (!SSL_is_init_finished(tls->ssl))
+ er = SSL_connect(tls->ssl);
+ else
+ return -1;
+
+ if (er < 0 && SSL_get_error(tls->ssl, er) == SSL_ERROR_WANT_READ)
+ return 0;
+ else
+ return -1;
+}
+
+int
+tls_handle_bio_error(tls_t *tls, int err) {
+ int rv;
+ int retry = BIO_should_retry(tls->bio_out);
+ if (BIO_should_write(tls->bio_out))
+ rv = -retry;
+ else if (BIO_should_read(tls->bio_out))
+ rv = -retry;
+ else {
+ char ssl_error_buf[512];
+ ERR_error_string_n(err, ssl_error_buf, sizeof(ssl_error_buf));
+ fprintf(stderr, "[%p] BIO: read failed: (%d) %s\n", tls->ssl, err, ssl_error_buf);
+ return err;
+ }
+ return err;
+}
+
+int
+tls_handle_ssl_error(tls_t *tls, int err) {
+ int ret;
+ int rv = SSL_get_error(tls->ssl, err);
+ switch (rv) {
+ case SSL_ERROR_WANT_READ:
+ ret = 1;
+ break;
+ default:
+ ret = -2;
+ break;
+ }
+ return ret;
+}
+
+int
+tls_bio_read(tls_t *tls, int buf_len) {
+ if (buf_len == 0) {
+ buf_len = sizeof(tls->buf);
+ }
+ memset(tls->buf, 0, buf_len);
+
+ int ret = BIO_read(tls->bio_out, tls->buf, buf_len);
+ if (ret >= 0) {
+ tls->buf[ret] = 0;
+ return ret;
+ } else {
+ return tls_handle_bio_error(tls, ret);
+ }
+}
+
+int
+tls_bio_write(tls_t *tls, char *buf, int len) {
+ int ret = BIO_write(tls->bio_in, buf, len);
+ if (ret >= 0)
+ return ret;
+ else
+ return tls_handle_bio_error(tls, ret);
+}
+
+int
+tls_read(tls_t *tls) {
+ int err;
+ int ret;
+ int read;
+
+ int done = SSL_is_init_finished(tls->ssl);
+ if (!done) {
+ err = SSL_connect(tls->ssl);
+ if (err <= 0) {
+ return tls_handle_ssl_error(tls, err);
+ }
+
+ /*
+ * TODO(Yorkie): returns not 1 nor < 0
+ */
+ assert(err == 1);
+ }
+
+ /* finished */
+ buffer_clear(tls->buffer);
+
+ ret = -1;
+ do {
+ read = SSL_read(tls->ssl, tls->buf, SSL_CHUNK_SIZE);
+ if (read > 0) {
+ ret = 0;
+ tls->buf[read] = 0;
+ buffer_append(tls->buffer, tls->buf);
+ } else {
+ tls_handle_ssl_error(tls, read);
+ }
+ } while (read > 0);
+
+ if (tls->connected == -1) {
+ tls->connected = 1;
+ } else {
+ ret = 0;
+ }
+ return ret;
+}
+
+int
+tls_write(tls_t *tls, char *buf_w, int len) {
+ return SSL_write(tls->ssl, buf_w, len);
+}
\ No newline at end of file
diff --git a/src/Cpu_win.cpp b/src/Cpu_win.cpp
index d967421c..1560dd64 100644
--- a/src/Cpu_win.cpp
+++ b/src/Cpu_win.cpp
@@ -51,7 +51,7 @@ void CpuImpl::setAffinity(int id, uint64_t mask)
int threadCount = 0;
- for (int i = 0; i < m_totalThreads; i++) {
+ for (size_t i = 0; i < m_totalThreads; i++) {
if (threadAffinityMask.test(i)) {
if (threadCount == id) {
SetThreadAffinityMask(GetCurrentThread(), 1ULL << i);
diff --git a/src/Mem.h b/src/Mem.h
index ffbc7d01..ee19ebb7 100644
--- a/src/Mem.h
+++ b/src/Mem.h
@@ -40,7 +40,7 @@ struct cryptonight_ctx;
class Mem
{
public:
- typedef std::bitset<64> ThreadBitSet;
+ typedef std::bitset<128> ThreadBitSet;
enum Flags {
HugepagesAvailable = 1,
HugepagesEnabled = 2,
diff --git a/src/Mem_win.cpp b/src/Mem_win.cpp
index dff6f3be..0f46b6b3 100644
--- a/src/Mem_win.cpp
+++ b/src/Mem_win.cpp
@@ -153,7 +153,7 @@ bool Mem::allocate(const Options* options)
m_memorySize = 0;
size_t scratchPadSize = m_algo == Options::ALGO_CRYPTONIGHT ? MEMORY : MEMORY_LITE;
- for (int i=0; i < m_threads; i++) {
+ for (size_t i=0; i < m_threads; i++) {
m_memorySize += sizeof(cryptonight_ctx);
m_memorySize += scratchPadSize * getThreadHashFactor(i);
}
diff --git a/src/Options.cpp b/src/Options.cpp
index d3b15062..d26efecb 100644
--- a/src/Options.cpp
+++ b/src/Options.cpp
@@ -74,7 +74,7 @@ Options:\n"
-k, --keepalive send keepalived for prevent timeout (need pool support)\n\
-r, --retries=N number of times to retry before switch to backup server (default: 5)\n\
-R, --retry-pause=N time to pause between retries (default: 5)\n\
- --multihash-thread-mask for av=2/4 only, limits multihash to given threads (mask), (default: all threads)\n\
+ --multihash-thread-mask for av=2/4 only, limits multihash to given threads (mask), (default: all threads)\n\
--cpu-affinity set process affinity to CPU core(s), mask 0x3 for cores 0 and 1\n\
--cpu-priority set process priority (0 idle, 2 normal to 5 highest)\n\
--no-huge-pages disable huge pages support\n\
@@ -83,6 +83,7 @@ Options:\n"
--max-cpu-usage=N maximum CPU usage for automatic threads mode (default 75)\n\
--safe safe adjust threads and av settings for current CPU\n\
--nicehash enable nicehash/xmrig-proxy support\n\
+ --use-tls enable tls on pool communication\n\
--print-time=N print hashrate report every N seconds\n\
--api-port=N port for the miner API\n\
--api-access-token=T access token for API\n\
@@ -90,9 +91,10 @@ Options:\n"
# ifndef XMRIG_NO_CC
"\
--cc-url=URL url of the CC Server\n\
+ --cc-use-tls enable tls encryption for CC communication\n\
--cc-access-token=T access token for CC Server\n\
--cc-worker-id=ID custom worker-id for CC Server\n\
- --cc-update-interval-s status update interval in seconds (default: 10 min: 1)\n"
+ --cc-update-interval-s=N status update interval in seconds (default: 10 min: 1)\n"
# endif
# endif
@@ -101,7 +103,10 @@ Options:\n"
--cc-user=USERNAME CC Server admin user\n\
--cc-pass=PASSWORD CC Server admin pass\n\
--cc-access-token=T CC Server access token for CC Client\n\
- --cc-port=N CC Server\n\
+ --cc-port=N CC Server port\n\
+ --cc-use-tls enable tls encryption for CC communication\n\
+ --cc-cert-file=FILE when tls is turned on, use this to point to the right cert file (default: server.pem) \n\
+ --cc-key-file=FILE when tls is turned on, use this to point to the right key file (default: server.key) \n\
--cc-client-config-folder=FOLDER Folder contains the client config files\n\
--cc-custom-dashboard=FILE loads a custom dashboard and serve it to '/'\n"
# endif
@@ -130,7 +135,7 @@ static struct option const options[] = {
{ "api-worker-id", 1, nullptr, 4002 },
{ "av", 1, nullptr, 'v' },
{ "aesni", 1, nullptr, 'A' },
- { "multihash-factor", 1, nullptr, 'm' },
+ { "multihash-factor", 1, nullptr, 'm' },
{ "background", 0, nullptr, 'B' },
{ "config", 1, nullptr, 'c' },
{ "cpu-affinity", 1, nullptr, 1020 },
@@ -155,6 +160,7 @@ static struct option const options[] = {
{ "user-agent", 1, nullptr, 1008 },
{ "userpass", 1, nullptr, 'O' },
{ "version", 0, nullptr, 'V' },
+ { "use-tls", 1, nullptr, 1015 },
{ "api-port", 1, nullptr, 4000 },
{ "api-access-token", 1, nullptr, 4001 },
{ "api-worker-id", 1, nullptr, 4002 },
@@ -167,6 +173,9 @@ static struct option const options[] = {
{ "cc-pass", 1, nullptr, 4008 },
{ "cc-client-config-folder", 1, nullptr, 4009 },
{ "cc-custom-dashboard", 1, nullptr, 4010 },
+ { "cc-cert-file", 1, nullptr, 4014 },
+ { "cc-key-file", 1, nullptr, 4015 },
+ { "cc-use-tls", 0, nullptr, 4016 },
{ "daemonized", 0, nullptr, 4011 },
{ "doublehash-thread-mask", 1, nullptr, 4013 },
{ "multihash-thread-mask", 1, nullptr, 4013 },
@@ -207,6 +216,7 @@ static struct option const pool_options[] = {
{ "userpass", 1, nullptr, 'O' },
{ "keepalive", 0, nullptr ,'k' },
{ "nicehash", 0, nullptr, 1006 },
+ { "use-tls", 0, nullptr, 1015 },
{ nullptr, 0, nullptr, 0 }
};
@@ -224,6 +234,7 @@ static struct option const cc_client_options[] = {
{ "access-token", 1, nullptr, 4004 },
{ "worker-id", 1, nullptr, 4005 },
{ "update-interval-s", 1, nullptr, 4012 },
+ { "use-tls", 0, nullptr, 4016 },
{ nullptr, 0, nullptr, 0 }
};
@@ -234,6 +245,9 @@ static struct option const cc_server_options[] = {
{ "pass", 1, nullptr, 4008 },
{ "client-config-folder", 1, nullptr, 4009 },
{ "custom-dashboard", 1, nullptr, 4010 },
+ { "cert-file", 1, nullptr, 4014 },
+ { "key-file", 1, nullptr, 4015 },
+ { "use-tls", 0, nullptr, 4016 },
{ nullptr, 0, nullptr, 0 }
};
@@ -272,6 +286,7 @@ Options::Options(int argc, char **argv) :
m_safe(false),
m_syslog(false),
m_daemonized(false),
+ m_ccUseTls(false),
m_configFile(Platform::defaultConfigName()),
m_apiToken(nullptr),
m_apiWorkerId(nullptr),
@@ -284,6 +299,8 @@ Options::Options(int argc, char **argv) :
m_ccAdminPass(nullptr),
m_ccClientConfigFolder(nullptr),
m_ccCustomDashboard(nullptr),
+ m_ccKeyFile(nullptr),
+ m_ccCertFile(nullptr),
m_algo(ALGO_CRYPTONIGHT),
m_algoVariant(AV0_AUTO),
m_aesni(AESNI_AUTO),
@@ -483,6 +500,16 @@ bool Options::parseArg(int key, const char *arg)
m_ccCustomDashboard = strdup(arg);
break;
+ case 4014: /* --cc-cert-file */
+ free(m_ccCertFile);
+ m_ccCertFile = strdup(arg);
+ break;
+
+ case 4015: /* --cc-key-file */
+ free(m_ccKeyFile);
+ m_ccKeyFile = strdup(arg);
+ break;
+
case 4011: /* --daemonized */
m_daemonized = true;
break;
@@ -513,6 +540,12 @@ bool Options::parseArg(int key, const char *arg)
case 1009: /* --no-huge-pages */
return parseBoolean(key, false);
+ case 1015: /* --use-tls */
+ return parseBoolean(key, true);
+
+ case 4016: /* --cc-use-tls */
+ return parseBoolean(key, true);
+
case 't': /* --threads */
if (strncmp(arg, "all", 3) == 0) {
m_threads = Cpu::threads();
@@ -717,10 +750,18 @@ bool Options::parseBoolean(int key, bool enable)
m_hugePages = enable;
break;
- case 2000: /* colors */
+ case 1015: /* --use-tls */
+ m_pools.back()->setUseTls(enable);
+ break;
+
+ case 2000: /* --colors */
m_colors = enable;
break;
+ case 4016: /* --cc-use-tls */
+ m_ccUseTls = enable;
+ break;
+
default:
break;
}
diff --git a/src/Options.h b/src/Options.h
index 24bae1af..9e24c34e 100644
--- a/src/Options.h
+++ b/src/Options.h
@@ -69,6 +69,7 @@ public:
inline bool hugePages() const { return m_hugePages; }
inline bool syslog() const { return m_syslog; }
inline bool daemonized() const { return m_daemonized; }
+ inline bool ccUseTls() const { return m_ccUseTls; }
inline const char *configFile() const { return m_configFile; }
inline const char *apiToken() const { return m_apiToken; }
inline const char *apiWorkerId() const { return m_apiWorkerId; }
@@ -81,6 +82,8 @@ public:
inline const char *ccAdminPass() const { return m_ccAdminPass; }
inline const char *ccClientConfigFolder() const { return m_ccClientConfigFolder; }
inline const char *ccCustomDashboard() const { return m_ccCustomDashboard == nullptr ? "index.html" : m_ccCustomDashboard; }
+ inline const char *ccKeyFile() const { return m_ccKeyFile == nullptr ? "server.key" : m_ccKeyFile; }
+ inline const char *ccCertFile() const { return m_ccCertFile == nullptr ? "server.pem" : m_ccCertFile; }
inline const std::vector &pools() const { return m_pools; }
inline Algo algo() const { return m_algo; }
inline bool aesni() const { return m_aesni == AESNI_ON; }
@@ -134,6 +137,7 @@ private:
bool m_safe;
bool m_syslog;
bool m_daemonized;
+ bool m_ccUseTls;
const char* m_configFile;
char *m_apiToken;
char *m_apiWorkerId;
@@ -146,6 +150,8 @@ private:
char *m_ccAdminPass;
char *m_ccClientConfigFolder;
char *m_ccCustomDashboard;
+ char *m_ccKeyFile;
+ char *m_ccCertFile;
Algo m_algo;
AlgoVariant m_algoVariant;
AesNi m_aesni;
diff --git a/src/Summary.cpp b/src/Summary.cpp
index d7083417..0bb6386b 100644
--- a/src/Summary.cpp
+++ b/src/Summary.cpp
@@ -147,10 +147,11 @@ static void print_pools()
const std::vector &pools = Options::i()->pools();
for (size_t i = 0; i < pools.size(); ++i) {
- Log::i()->text(Options::i()->colors() ? "\x1B[01;32m * \x1B[01;37mPOOL #%d: \x1B[01;36m%s:%d" : " * POOL #%d: %s:%d",
- i + 1,
- pools[i]->host(),
- pools[i]->port());
+ Log::i()->text(Options::i()->colors() ? "\x1B[01;32m * \x1B[01;37mPOOL #%d: \x1B[01;36m%s:%d %s" : " * POOL #%d: %s:%d %s",
+ i + 1,
+ pools[i]->host(),
+ pools[i]->port(),
+ pools[i]->useTls() ? "(TLS)" : "");
}
# ifdef APP_DEBUG
@@ -179,7 +180,10 @@ static void print_cc()
return;
}
- Log::i()->text(Options::i()->colors() ? "\x1B[01;32m * \x1B[01;37mCC Server: \x1B[01;36m%s:%d" : " * CC Server: %s:%d", Options::i()->ccHost(), Options::i()->ccPort());
+ Log::i()->text(Options::i()->colors() ? "\x1B[01;32m * \x1B[01;37mCC Server: \x1B[01;36m%s:%d %s" : " * CC Server: %s:%d %s",
+ Options::i()->ccHost(),
+ Options::i()->ccPort(),
+ Options::i()->ccUseTls() ? "(TLS)" : "");
}
#endif
diff --git a/src/api/NetworkState.cpp b/src/api/NetworkState.cpp
index d3ffddd3..82d61c89 100644
--- a/src/api/NetworkState.cpp
+++ b/src/api/NetworkState.cpp
@@ -94,7 +94,7 @@ void NetworkState::add(const SubmitResult &result, const char *error)
}
-void NetworkState::setPool(const char *host, int port, const char *ip)
+void NetworkState::setPool(const char *host, int port)
{
snprintf(pool, sizeof(pool) - 1, "%s:%d", host, port);
diff --git a/src/api/NetworkState.h b/src/api/NetworkState.h
index d0998074..0aa8c09e 100644
--- a/src/api/NetworkState.h
+++ b/src/api/NetworkState.h
@@ -41,7 +41,7 @@ public:
uint32_t avgTime() const;
uint32_t latency() const;
void add(const SubmitResult &result, const char *error);
- void setPool(const char *host, int port, const char *ip);
+ void setPool(const char *host, int port);
void stop();
char pool[256];
diff --git a/src/cc/CCClient.cpp b/src/cc/CCClient.cpp
index 43dee832..2a8d776c 100644
--- a/src/cc/CCClient.cpp
+++ b/src/cc/CCClient.cpp
@@ -92,6 +92,8 @@ CCClient::CCClient(Options* options, uv_async_t* async)
m_clientStatus.setCpuL3(Cpu::l3());
m_clientStatus.setCurrentThreads(m_options->threads());
+ m_startTime = std::chrono::system_clock::now();
+
if (m_options->ccToken() != nullptr) {
m_authorization = std::string("Bearer ") + m_self->m_options->ccToken();
}
@@ -138,6 +140,8 @@ void CCClient::updateNetworkState(const NetworkState& network)
void CCClient::publishClientStatusReport()
{
+ refreshUptime();
+
std::string requestUrl = "/client/setClientStatus?clientId=" + m_self->m_clientStatus.getClientId();
std::string requestBuffer = m_self->m_clientStatus.toJsonString();
@@ -256,7 +260,17 @@ std::shared_ptr CCClient::performRequest(const std::string& r
const std::string& requestBuffer,
const std::string& operation)
{
- httplib::Client cli(m_self->m_options->ccHost(), m_self->m_options->ccPort());
+ std::shared_ptr cli;
+
+# ifndef XMRIG_NO_TLS
+ if (m_self->m_options->ccUseTls()) {
+ cli = std::make_shared(m_self->m_options->ccHost(), m_self->m_options->ccPort());
+ } else {
+# endif
+ cli = std::make_shared(m_self->m_options->ccHost(), m_self->m_options->ccPort());
+# ifndef XMRIG_NO_TLS
+ }
+# endif
httplib::Request req;
req.method = operation;
@@ -277,7 +291,15 @@ std::shared_ptr CCClient::performRequest(const std::string& r
auto res = std::make_shared();
- return cli.send(req, *res) ? res : nullptr;
+ return cli->send(req, *res) ? res : nullptr;
+}
+
+void CCClient::refreshUptime()
+{
+ std::chrono::time_point now = std::chrono::system_clock::now();
+ auto uptime = std::chrono::duration_cast(now - m_self->m_startTime);
+
+ m_self->m_clientStatus.setUptime(static_cast(uptime.count()));
}
void CCClient::onThreadStarted(void* handle)
diff --git a/src/cc/CCClient.h b/src/cc/CCClient.h
index 07a347df..8471d11a 100644
--- a/src/cc/CCClient.h
+++ b/src/cc/CCClient.h
@@ -28,6 +28,8 @@
#ifndef XMRIG_NO_CC
#include
+#include
+#include
#include <3rdparty/cpp-httplib/httplib.h>
#include "Options.h"
#include "ClientStatus.h"
@@ -65,11 +67,14 @@ private:
std::string m_authorization;
+ std::chrono::time_point m_startTime;
+
uv_async_t* m_async;
uv_timer_t m_timer;
uv_loop_t m_client_loop;
uv_thread_t m_thread;
+ static void refreshUptime();
};
#endif
diff --git a/src/cc/CCServer.cpp b/src/cc/CCServer.cpp
index c4969853..a65b4816 100644
--- a/src/cc/CCServer.cpp
+++ b/src/cc/CCServer.cpp
@@ -90,7 +90,7 @@ CCServer::~CCServer()
int CCServer::start()
{
if (!m_options) {
- return 0;
+ return EINVAL;
}
uv_signal_start(&m_signal, CCServer::onSignal, SIGHUP);
@@ -106,7 +106,9 @@ int CCServer::start()
Service::start();
m_httpd = new Httpd(m_options);
- m_httpd->start();
+ if (!m_httpd->start()) {
+ return EINVAL;
+ }
const int r = uv_run(uv_default_loop(), UV_RUN_DEFAULT);
uv_loop_close(uv_default_loop());
diff --git a/src/cc/ClientStatus.cpp b/src/cc/ClientStatus.cpp
index d98e2d6c..7005699f 100644
--- a/src/cc/ClientStatus.cpp
+++ b/src/cc/ClientStatus.cpp
@@ -51,6 +51,7 @@ ClientStatus::ClientStatus()
m_sharesGood(0),
m_sharesTotal(0),
m_hashesTotal(0),
+ m_uptime(0),
m_avgTime(0),
m_lastStatusUpdate(0)
{
@@ -321,6 +322,16 @@ std::time_t ClientStatus::getLastStatusUpdate() const
return m_lastStatusUpdate;
}
+uint64_t ClientStatus::getUptime() const
+{
+ return m_uptime;
+}
+
+void ClientStatus::setUptime(uint64_t uptime)
+{
+ m_uptime = uptime;
+}
+
bool ClientStatus::parseFromJson(const rapidjson::Document& document)
{
bool result = false;
@@ -433,6 +444,10 @@ bool ClientStatus::parseFromJson(const rapidjson::Document& document)
m_avgTime = clientStatus["avg_time"].GetUint();
}
+ if (clientStatus.HasMember("uptime")) {
+ m_uptime = clientStatus["uptime"].GetUint64();
+ }
+
auto time_point = std::chrono::system_clock::now();
m_lastStatusUpdate = std::chrono::system_clock::to_time_t(time_point);
@@ -481,6 +496,8 @@ rapidjson::Value ClientStatus::toJson(rapidjson::MemoryPoolAllocator(m_lastStatusUpdate), allocator);
return clientStatus;
diff --git a/src/cc/ClientStatus.h b/src/cc/ClientStatus.h
index 6aff3eb2..f6afc824 100644
--- a/src/cc/ClientStatus.h
+++ b/src/cc/ClientStatus.h
@@ -137,6 +137,9 @@ public:
std::time_t getLastStatusUpdate() const;
+ void setUptime(uint64_t uptime);
+ uint64_t getUptime() const;
+
std::string toJsonString();
rapidjson::Value toJson(rapidjson::MemoryPoolAllocator& allocator);
bool parseFromJson(const rapidjson::Document& document);
@@ -179,6 +182,7 @@ private:
uint64_t m_sharesGood;
uint64_t m_sharesTotal;
uint64_t m_hashesTotal;
+ uint64_t m_uptime;
uint32_t m_avgTime;
diff --git a/src/cc/Httpd.cpp b/src/cc/Httpd.cpp
index 35f9a139..561dd5c7 100644
--- a/src/cc/Httpd.cpp
+++ b/src/cc/Httpd.cpp
@@ -23,6 +23,8 @@
*/
#include
+#include
+#include
#include
#include
@@ -43,19 +45,54 @@ bool Httpd::start()
return false;
}
- m_daemon = MHD_start_daemon(MHD_USE_SELECT_INTERNALLY, static_cast(m_options->ccPort()), nullptr, nullptr, &Httpd::handler,
- this, MHD_OPTION_CONNECTION_TIMEOUT, (unsigned int) 30, MHD_OPTION_END);
+# ifndef XMRIG_NO_TLS
+ if (m_options->ccUseTls()) {
+
+ m_keyPem = readFile(m_options->ccKeyFile());
+ m_certPem = readFile(m_options->ccCertFile());
+
+ if (m_keyPem.empty() || m_certPem.empty()) {
+ LOG_ERR("HTTPS Daemon failed to start. Unable to load Key/Cert.");
+ return false;
+ }
+
+ m_daemon = MHD_start_daemon (MHD_USE_SELECT_INTERNALLY | MHD_USE_SSL,
+ static_cast(m_options->ccPort()), nullptr, nullptr, &Httpd::handler,
+ this, MHD_OPTION_CONNECTION_TIMEOUT, (unsigned int) 25,
+ MHD_OPTION_HTTPS_MEM_KEY, m_keyPem.c_str(),
+ MHD_OPTION_HTTPS_MEM_CERT, m_certPem.c_str(),
+ MHD_OPTION_END);
+ } else {
+# endif
+ m_daemon = MHD_start_daemon(MHD_USE_SELECT_INTERNALLY, static_cast(m_options->ccPort()), nullptr,
+ nullptr, &Httpd::handler,
+ this, MHD_OPTION_CONNECTION_TIMEOUT, (unsigned int) 25, MHD_OPTION_END);
+# ifndef XMRIG_NO_TLS
+ }
+# endif
if (!m_daemon) {
LOG_ERR("HTTP Daemon failed to start.");
return false;
} else {
- LOG_INFO("%s Server started on Port: %d", APP_NAME, m_options->ccPort());
+ LOG_INFO("%s Server started on Port: %d %s", APP_NAME, m_options->ccPort(), m_options->ccUseTls() ? "with TLS" : "");
}
return true;
}
+std::string Httpd::readFile(const std::string &fileName)
+{
+ std::stringstream data;
+ std::ifstream file(fileName);
+ if (file) {
+ data << file.rdbuf();
+ file.close();
+ }
+
+ return data.str();
+}
+
unsigned Httpd::tokenAuth(struct MHD_Connection* connection)
{
if (!m_options->ccToken()) {
diff --git a/src/cc/Httpd.h b/src/cc/Httpd.h
index 95d5ecc8..8d3ee6fe 100644
--- a/src/cc/Httpd.h
+++ b/src/cc/Httpd.h
@@ -58,9 +58,13 @@ private:
static int handleGET(const Httpd* httpd, MHD_Connection* connection, const char* url);
static int handlePOST(const Httpd* httpd, MHD_Connection* connection, const char* url, const char* upload_data, size_t* upload_data_size, void** con_cls);
- const Options* m_options;
+ static std::string readFile(const std::string &fileName);
+
+ const Options* m_options;
MHD_Daemon* m_daemon;
+ std::string m_keyPem;
+ std::string m_certPem;
};
#endif /* __HTTPD_H__ */
diff --git a/src/cc/Summary.cpp b/src/cc/Summary.cpp
index 4c3cc784..a1544e03 100644
--- a/src/cc/Summary.cpp
+++ b/src/cc/Summary.cpp
@@ -45,9 +45,8 @@ static void print_versions()
buf[0] = '\0';
# endif
-
- Log::i()->text(Options::i()->colors() ? "\x1B[01;32m * \x1B[01;37mVERSIONS: \x1B[01;36m%s/%s\x1B[01;37m libuv/%s%s" : " * VERSIONS: %s/%s libuv/%s%s",
- APP_NAME, APP_VERSION, uv_version_string(), buf);
+ Log::i()->text(Options::i()->colors() ? "\x1B[01;32m * \x1B[01;37mVERSIONS: \x1B[01;36m%s/%s\x1B[01;37m libuv/%s%s \x1B[01;36m(%s)" : " * VERSIONS: %s/%s libuv/%s%s (%s)",
+ APP_NAME, APP_VERSION, uv_version_string(), buf, BUILD_TYPE);
}
static void print_commands()
diff --git a/src/cc/XMRigd.cpp b/src/cc/XMRigd.cpp
index 34494148..2f08e612 100644
--- a/src/cc/XMRigd.cpp
+++ b/src/cc/XMRigd.cpp
@@ -36,16 +36,22 @@
#include
#endif
+#ifndef MINER_EXECUTABLE_NAME
+ #define MINER_EXECUTABLE_NAME xmrigMiner
+#endif
+#define VALUE_TO_STRING(x) #x
+#define VALUE(x) VALUE_TO_STRING(x)
+
int main(int argc, char **argv) {
std::string ownPath(argv[0]);
#if defined(_WIN32) || defined(WIN32)
int pos = ownPath.rfind('\\');
- std::string xmrigMiner("xmrigMiner.exe");
+ std::string xmrigMiner( VALUE(MINER_EXECUTABLE_NAME) ".exe");
#else
int pos = ownPath.rfind('/');
- std::string xmrigMiner("xmrigMiner");
+ std::string xmrigMiner( VALUE(MINER_EXECUTABLE_NAME) );
#endif
std::string xmrigMinerPath = ownPath.substr(0, pos+1) + xmrigMiner;
diff --git a/src/config.json b/src/config.json
index 30c58b47..02e53f37 100644
--- a/src/config.json
+++ b/src/config.json
@@ -26,6 +26,7 @@
"url": "", // URL of mining server
"user": "", // username for mining server
"pass": "x", // password for mining server
+ "use-tls" : false, // enable tls for pool communication (need pool support)
"keepalive": true, // send keepalived for prevent timeout (need pool support)
"nicehash": false // enable nicehash/xmrig-proxy support
}
@@ -37,6 +38,7 @@
},
"cc-client": {
"url": "localhost:3344", // url of the CC Server (ip:port)
+ "use-tls" : false, // enable tls for CC communication (needs to be enabled on CC Server too)
"access-token": "mySecret", // access token for CC Server (has to be the same in config_cc.json)
"worker-id": null, // custom worker-id for CC Server (otherwise hostname is used)
"update-interval-s": 10 // status update interval in seconds (default: 10 min: 1)
diff --git a/src/config_cc.json b/src/config_cc.json
index 3315d83c..2b716a0d 100644
--- a/src/config_cc.json
+++ b/src/config_cc.json
@@ -5,6 +5,9 @@
"syslog": false, // use system log for output messages
"cc-server": {
"port": 3344, // port the CC Server will listens on
+ "use-tls" : false, // use tls for CC communication (needs to be enabled on miners too)
+ "cert-file" : "server.pem", // when tls is turned on, use this to point to the right cert file
+ "key-file" : "server.key", // when tls is turned on, use this to point to the right key file
"access-token": "mySecret", // access token for CC Clients (should be set!!!)
"user": "admin", // admin user for access CC Dashboard
"pass": "pass", // admin pass for access CC Dashboard
diff --git a/src/default_config.json b/src/default_config.json
index 30c58b47..1964e364 100644
--- a/src/default_config.json
+++ b/src/default_config.json
@@ -1,10 +1,10 @@
{
"algo": "cryptonight", // cryptonight (default) or cryptonight-lite
"av": null, // DEPRECATED: algorithm variation, (0 auto,
- // 1 -> (aesni=1, multihash-factor=1),
- // 2 -> (aesni=1, multihash-factor=2),
- // 3 -> (aesni=2, multihash-factor=1),
- // 4 -> (aesni=2, multihash-factor=2))
+ // 1 -> (aesni=1, multihash-factor=1),
+ // 2 -> (aesni=1, multihash-factor=2),
+ // 3 -> (aesni=2, multihash-factor=1),
+ // 4 -> (aesni=2, multihash-factor=2))
"aesni": 0, // selection of AES-NI mode (0 auto, 1 on, 2 off)
"threads": 0, // number of miner threads (not set or 0 enables automatic selection of optimal thread count)
"multihash-factor": 0, // number of hash blocks to process at a time (not set or 0 enables automatic selection of optimal number of hash blocks)
@@ -26,6 +26,7 @@
"url": "", // URL of mining server
"user": "", // username for mining server
"pass": "x", // password for mining server
+ "use-tls" : false, // enable tls for pool communication (need pool support)
"keepalive": true, // send keepalived for prevent timeout (need pool support)
"nicehash": false // enable nicehash/xmrig-proxy support
}
@@ -37,6 +38,7 @@
},
"cc-client": {
"url": "localhost:3344", // url of the CC Server (ip:port)
+ "use-tls" : false, // enable tls for CC communication (needs to be enabled on CC Server too)
"access-token": "mySecret", // access token for CC Server (has to be the same in config_cc.json)
"worker-id": null, // custom worker-id for CC Server (otherwise hostname is used)
"update-interval-s": 10 // status update interval in seconds (default: 10 min: 1)
diff --git a/src/net/Client.cpp b/src/net/Client.cpp
index fb83acd2..86a1d2ea 100644
--- a/src/net/Client.cpp
+++ b/src/net/Client.cpp
@@ -5,6 +5,7 @@
* Copyright 2014-2016 Wolf9466
* Copyright 2016 Jay D Dee
* Copyright 2016-2017 XMRig
+ * Copyright 2018- BenDr0id
*
*
* This program is free software: you can redistribute it and/or modify
@@ -23,15 +24,13 @@
#include
#include
-#include
#include
#include
-
+#include
#include "interfaces/IClientListener.h"
#include "log/Log.h"
#include "net/Client.h"
-#include "net/Url.h"
#include "rapidjson/document.h"
#include "rapidjson/error/en.h"
#include "rapidjson/stringbuffer.h"
@@ -61,20 +60,8 @@ Client::Client(int id, const char *agent, IClientListener *listener) :
m_retryPause(5000),
m_failures(0),
m_recvBufPos(0),
- m_state(UnconnectedState),
- m_expire(0),
- m_stream(nullptr),
- m_socket(nullptr)
+ m_expire(0)
{
- memset(m_ip, 0, sizeof(m_ip));
- memset(&m_hints, 0, sizeof(m_hints));
-
- m_resolver.data = this;
-
- m_hints.ai_family = PF_INET;
- m_hints.ai_socktype = SOCK_STREAM;
- m_hints.ai_protocol = IPPROTO_TCP;
-
m_recvBuf.base = m_buf;
m_recvBuf.len = sizeof(m_buf);
@@ -87,13 +74,9 @@ Client::Client(int id, const char *agent, IClientListener *listener) :
Client::~Client()
{
- delete m_socket;
-}
-
-
-void Client::connect()
-{
- resolve(m_url.host());
+ if (m_net) {
+ net_free(m_net);
+ }
}
@@ -105,7 +88,7 @@ void Client::connect()
void Client::connect(const Url *url)
{
setUrl(url);
- resolve(m_url.host());
+ connect();
}
@@ -138,13 +121,11 @@ void Client::tick(uint64_t now)
return;
}
- if (m_state == ConnectedState) {
+ if (m_net) {
LOG_DEBUG_ERR("[%s:%u] timeout", m_url.host(), m_url.port());
- close();
+ reconnect();
}
-
-
- if (m_state == ConnectingState) {
+ else {
connect();
}
}
@@ -247,41 +228,15 @@ bool Client::parseLogin(const rapidjson::Value &result, int *code)
return parseJob(result["job"], code);
}
-
-int Client::resolve(const char *host)
-{
- setState(HostLookupState);
-
- m_expire = 0;
- m_recvBufPos = 0;
-
- if (m_failures == -1) {
- m_failures = 0;
- }
-
- const int r = uv_getaddrinfo(uv_default_loop(), &m_resolver, Client::onResolved, host, NULL, &m_hints);
- if (r) {
- if (!m_quiet) {
- LOG_ERR("[%s:%u] getaddrinfo error: \"%s\"", host, m_url.port(), uv_strerror(r));
- }
- return 1;
- }
-
- return 0;
-}
-
-
int64_t Client::send(size_t size)
{
- LOG_DEBUG("[%s:%u] send (%d bytes): \"%s\"", m_url.host(), m_url.port(), size, m_sendBuf);
- if (state() != ConnectedState || !uv_is_writable(m_stream)) {
- LOG_DEBUG_ERR("[%s:%u] send failed, invalid state: %d", m_url.host(), m_url.port(), m_state);
+ LOG_DEBUG("[%s:%u] send (%d bytes): \"%s\"", m_url.host(), m_url.port(), size, buf);
+ if (!m_net) {
+ LOG_DEBUG_ERR("[%s:%u] send failed", m_url.host(), m_url.port());
return -1;
}
- uv_buf_t buf = uv_buf_init(m_sendBuf, (unsigned int) size);
-
- if (uv_try_write(m_stream, &buf, 1) < 0) {
+ if (net_write2(m_net, m_sendBuf, static_cast(size)) < 0) {
close();
return -1;
}
@@ -293,42 +248,93 @@ int64_t Client::send(size_t size)
void Client::close()
{
- if (m_state == UnconnectedState || m_state == ClosingState || !m_socket) {
+ if (m_net) {
+ auto client = getClient(m_net->data);
+
+ net_free(m_net);
+
+ m_net = nullptr;
+
+ client->reconnect();
+ }
+}
+
+
+void Client::connect()
+{
+ m_net = net_new(const_cast(m_url.host()), m_url.port());
+ m_net->data = this;
+ m_net->conn_cb = Client::onConnect;
+ m_net->read_cb = Client::onRead;
+ m_net->error_cb = Client::onError;
+
+#ifndef XMRIG_NO_TLS
+ if (m_url.useTls()) {
+ tls_ctx* tls_ctx = tls_ctx_new();
+ net_set_tls(m_net, tls_ctx);
+ }
+#endif
+
+ net_connect(m_net);
+}
+
+void Client::onRead(net_t *net, size_t size, char *buf)
+{
+ auto client = getClient(net->data);
+
+ if (size == 0) {
+ if (size != UV_EOF && !client->m_quiet) {
+ LOG_ERR("[%s:%u] read error: \"%s\"", client->m_url.host(), client->m_url.port(), uv_strerror((int) size));
+ }
+
+ return client->close();
+ }
+
+ client->m_recvBufPos += size;
+
+ char* end;
+ char* start = buf;
+ size_t remaining = client->m_recvBufPos;
+
+ while ((end = static_cast(memchr(start, '\n', remaining))) != nullptr) {
+ end++;
+ size_t len = end - start;
+ client->parse(start, len);
+
+ remaining -= len;
+ start = end;
+ }
+
+ if (remaining == 0) {
+ client->m_recvBufPos = 0;
return;
}
- setState(ClosingState);
+ if (start == buf) {
+ return;
+ }
- if (uv_is_closing(reinterpret_cast(m_socket)) == 0) {
- uv_close(reinterpret_cast(m_socket), Client::onClose);
+ memcpy(buf, start, remaining);
+ client->m_recvBufPos = remaining;
+}
+
+void Client::onConnect(net_t *net) {
+ auto client = getClient(net->data);
+ client->login();
+}
+
+void Client::onError(net_t *net, int err, char *errStr)
+{
+ if (net) {
+ auto client = getClient(net->data);
+ if (!client->m_quiet) {
+ LOG_ERR("[%s:%u] error: \"%s\"", client->m_url.host(), client->m_url.port(), errStr);
+ }
+
+ client->close();
}
}
-
-void Client::connect(struct sockaddr *addr)
-{
- setState(ConnectingState);
-
- reinterpret_cast(addr)->sin_port = htons(m_url.port());
- delete m_socket;
-
- uv_connect_t *req = new uv_connect_t;
- req->data = this;
-
- m_socket = new uv_tcp_t;
- m_socket->data = this;
-
- uv_tcp_init(uv_default_loop(), m_socket);
- uv_tcp_nodelay(m_socket, 1);
-
-# ifndef WIN32
- uv_tcp_keepalive(m_socket, 1, 60);
-# endif
-
- uv_tcp_connect(req, m_socket, reinterpret_cast(addr), Client::onConnect);
-}
-
-
void Client::login()
{
m_results.clear();
@@ -480,9 +486,7 @@ void Client::ping()
}
-void Client::reconnect()
-{
- setState(ConnectingState);
+void Client::reconnect() {
# ifndef XMRIG_PROXY_PROJECT
if (m_url.isKeepAlive()) {
@@ -500,19 +504,6 @@ void Client::reconnect()
m_expire = uv_now(uv_default_loop()) + m_retryPause;
}
-
-void Client::setState(SocketState state)
-{
- LOG_DEBUG("[%s:%u] state: %d", m_url.host(), m_url.port(), state);
-
- if (m_state == state) {
- return;
- }
-
- m_state = state;
-}
-
-
void Client::startTimeout()
{
m_expire = 0;
@@ -525,127 +516,3 @@ void Client::startTimeout()
uv_timer_start(&m_keepAliveTimer, [](uv_timer_t *handle) { getClient(handle->data)->ping(); }, kKeepAliveTimeout, 0);
# endif
}
-
-
-void Client::onAllocBuffer(uv_handle_t *handle, size_t suggested_size, uv_buf_t *buf)
-{
- auto client = getClient(handle->data);
-
- buf->base = &client->m_recvBuf.base[client->m_recvBufPos];
- buf->len = client->m_recvBuf.len - (unsigned long)client->m_recvBufPos;
-}
-
-
-void Client::onClose(uv_handle_t *handle)
-{
- auto client = getClient(handle->data);
-
- delete client->m_socket;
-
- client->m_stream = nullptr;
- client->m_socket = nullptr;
- client->setState(UnconnectedState);
-
- client->reconnect();
-}
-
-
-void Client::onConnect(uv_connect_t *req, int status)
-{
- auto client = getClient(req->data);
- if (status < 0) {
- if (!client->m_quiet) {
- LOG_ERR("[%s:%u] connect error: \"%s\"", client->m_url.host(), client->m_url.port(), uv_strerror(status));
- }
-
- delete req;
- client->close();
- return;
- }
-
- client->m_stream = static_cast(req->handle);
- client->m_stream->data = req->data;
- client->setState(ConnectedState);
-
- uv_read_start(client->m_stream, Client::onAllocBuffer, Client::onRead);
- delete req;
-
- client->login();
-}
-
-
-void Client::onRead(uv_stream_t *stream, ssize_t nread, const uv_buf_t *buf)
-{
- auto client = getClient(stream->data);
- if (nread < 0) {
- if (nread != UV_EOF && !client->m_quiet) {
- LOG_ERR("[%s:%u] read error: \"%s\"", client->m_url.host(), client->m_url.port(), uv_strerror((int) nread));
- }
-
- return client->close();
- }
-
- if ((size_t) nread > (sizeof(m_buf) - 8 - client->m_recvBufPos)) {
- return client->close();
- }
-
- client->m_recvBufPos += nread;
-
- char* end;
- char* start = buf->base;
- size_t remaining = client->m_recvBufPos;
-
- while ((end = static_cast(memchr(start, '\n', remaining))) != nullptr) {
- end++;
- size_t len = end - start;
- client->parse(start, len);
-
- remaining -= len;
- start = end;
- }
-
- if (remaining == 0) {
- client->m_recvBufPos = 0;
- return;
- }
-
- if (start == buf->base) {
- return;
- }
-
- memcpy(buf->base, start, remaining);
- client->m_recvBufPos = remaining;
-}
-
-
-void Client::onResolved(uv_getaddrinfo_t *req, int status, struct addrinfo *res)
-{
- auto client = getClient(req->data);
- if (status < 0) {
- LOG_ERR("[%s:%u] DNS error: \"%s\"", client->m_url.host(), client->m_url.port(), uv_strerror(status));
- return client->reconnect();
- }
-
- addrinfo *ptr = res;
- std::vector ipv4;
-
- while (ptr != nullptr) {
- if (ptr->ai_family == AF_INET) {
- ipv4.push_back(ptr);
- }
-
- ptr = ptr->ai_next;
- }
-
- if (ipv4.empty()) {
- LOG_ERR("[%s:%u] DNS error: \"No IPv4 records found\"", client->m_url.host(), client->m_url.port());
- return client->reconnect();
- }
-
- ptr = ipv4[rand() % ipv4.size()];
-
- uv_ip4_name(reinterpret_cast(ptr->ai_addr), client->m_ip, 16);
-
- client->connect(ptr->ai_addr);
- uv_freeaddrinfo(res);
-}
diff --git a/src/net/Client.h b/src/net/Client.h
index 699f4903..b2b422f6 100644
--- a/src/net/Client.h
+++ b/src/net/Client.h
@@ -5,6 +5,7 @@
* Copyright 2014-2016 Wolf9466
* Copyright 2016 Jay D Dee
* Copyright 2016-2017 XMRig
+ * Copyright 2018- BenDr0id
*
*
* This program is free software: you can redistribute it and/or modify
@@ -27,6 +28,7 @@
#include