From b8cc1136a4dae5a842f52bba9a21358868c72bb9 Mon Sep 17 00:00:00 2001
From: XMRig <support@xmrig.com>
Date: Wed, 7 Jun 2017 02:46:52 +0300
Subject: [PATCH] More flexible pools configuration.

---
 src/App.cpp         |  1 -
 src/Options.cpp     |  2 +-
 src/Options.h       |  9 +++++----
 src/donate.h        | 16 +++++++++++++++-
 src/net/Client.cpp  | 37 +++++++++++++++++++------------------
 src/net/Client.h    |  7 +++++--
 src/net/Network.cpp | 39 +++++++++++++++++++++++++++++----------
 src/net/Network.h   | 12 +++++++++---
 8 files changed, 83 insertions(+), 40 deletions(-)

diff --git a/src/App.cpp b/src/App.cpp
index ce9d2b2cd..a82eb88cd 100644
--- a/src/App.cpp
+++ b/src/App.cpp
@@ -48,7 +48,6 @@ App::App(int argc, char **argv)
 {
     Console::init();
     m_options = Options::parse(argc, argv);
-
     m_network = new Network(m_options);
 }
 
diff --git a/src/Options.cpp b/src/Options.cpp
index 5a8551c41..331db8434 100644
--- a/src/Options.cpp
+++ b/src/Options.cpp
@@ -128,7 +128,7 @@ Options::Options(int argc, char **argv) :
     m_user(nullptr),
     m_algo(0),
     m_algoVariant(0),
-    m_donateLevel(DONATE_LEVEL),
+    m_donateLevel(kDonateLevel),
     m_maxCpuUsage(75),
     m_retries(5),
     m_retryPause(5),
diff --git a/src/Options.h b/src/Options.h
index eccfbcff3..421d19f4c 100644
--- a/src/Options.h
+++ b/src/Options.h
@@ -51,10 +51,11 @@ public:
     static inline Options* i() { return m_self; }
     static Options *parse(int argc, char **argv);
 
-    inline bool isReady() const     { return m_ready; }
-    inline const char *pass() const { return m_pass; }
-    inline const char *user() const { return m_user; }
-    inline Url *url() const         { return m_url; }
+    inline bool isReady() const         { return m_ready; }
+    inline const char *pass() const     { return m_pass; }
+    inline const char *user() const     { return m_user; }
+    inline const Url *backupUrl() const { return m_backupUrl; }
+    inline const Url *url() const       { return m_url; }
 
 private:
     Options(int argc, char **argv);
diff --git a/src/donate.h b/src/donate.h
index 4fc607872..3a0009486 100644
--- a/src/donate.h
+++ b/src/donate.h
@@ -24,6 +24,20 @@
 #ifndef __DONATE_H__
 #define __DONATE_H__
 
-#define DONATE_LEVEL 5
+
+/*
+ * Dev donation.
+ *
+ * Percentage of your hashing power that you want to donate to the developer, can be 0 if you don't want to do that.
+ * Example of how it works for the default setting of 1:
+ * You miner will mine into your usual pool for 99 minutes, then switch to the developer's pool for 1 minute.
+ * Switching is instant, and only happens after a successful connection, so you never loose any hashes.
+ *
+ * If you plan on changing this setting to 0 please consider making a one off donation to my wallet:
+ * XMR: 48edfHu7V9Z84YzzMa6fUueoELZ9ZRXq9VetWzYGzKt52XU5xvqgzYnDK9URnRoJMk1j8nLwEVsaSWJ4fhdUyZijBGUicoD
+ * BTC: 1P7ujsXeX7GxQwHNnJsRMgAdNkFZmNVqJT
+ */
+constexpr const int kDonateLevel = 5;
+
 
 #endif /* __DONATE_H__ */
diff --git a/src/net/Client.cpp b/src/net/Client.cpp
index 296acf64e..a8a4f5d57 100644
--- a/src/net/Client.cpp
+++ b/src/net/Client.cpp
@@ -28,9 +28,10 @@
 #include "net/Url.h"
 
 
-Client::Client(IClientListener *listener) :
+Client::Client(int id, IClientListener *listener) :
     m_host(nullptr),
     m_listener(listener),
+    m_id(id),
     m_retries(0),
     m_sequence(1),
     m_recvBufPos(0),
@@ -59,20 +60,9 @@ Client::~Client()
 }
 
 
-/**
- * @brief Connect to server.
- *
- * @param host
- * @param port
- */
-void Client::connect(const char *host, uint16_t port)
+void Client::connect()
 {
-    m_host = strdup(host);
-    m_port = port;
-
-    LOG_DEBUG("[%s:%u] connect", m_host, m_port);
-
-    resolve(host);
+    resolve(m_host);
 }
 
 
@@ -83,7 +73,8 @@ void Client::connect(const char *host, uint16_t port)
  */
 void Client::connect(const Url *url)
 {
-    connect(url->host(), url->port());
+    setUrl(url);
+    resolve(m_host);
 }
 
 
@@ -136,6 +127,14 @@ void Client::send(char *data)
 }
 
 
+void Client::setUrl(const Url *url)
+{
+    free(m_host);
+    m_host = strdup(url->host());
+    m_port = url->port();
+}
+
+
 bool Client::parseJob(const json_t *params, int *code)
 {
     if (!json_is_object(params)) {
@@ -335,6 +334,8 @@ void Client::onClose(uv_handle_t *handle)
     client->m_stream = nullptr;
     client->m_socket = nullptr;
     client->setState(UnconnectedState);
+
+    LOG_NOTICE("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
 }
 
 
@@ -344,6 +345,7 @@ void Client::onConnect(uv_connect_t *req, int status)
     if (status < 0) {
         LOG_ERR("[%s:%u] connect error: \"%s\"", client->m_host, client->m_port, uv_strerror(status));
         free(req);
+        client->close();
         return;
     }
 
@@ -366,8 +368,7 @@ void Client::onRead(uv_stream_t *stream, ssize_t nread, const uv_buf_t *buf)
             LOG_ERR("[%s:%u] read error: \"%s\"", client->m_host, client->m_port, uv_strerror(nread));
         }
 
-        client->close();
-        return;
+        return client->close();;
     }
 
     client->m_recvBufPos += nread;
@@ -404,7 +405,7 @@ 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_host, client->m_port, uv_strerror(status));
-        return;
+        return client->close();;
     }
 
     client->connect(res->ai_addr);
diff --git a/src/net/Client.h b/src/net/Client.h
index 309078ded..8df215599 100644
--- a/src/net/Client.h
+++ b/src/net/Client.h
@@ -47,15 +47,17 @@ public:
         ClosingState
     };
 
-    Client(IClientListener *listener);
+    Client(int id, IClientListener *listener);
     ~Client();
 
-    void connect(const char *host, uint16_t port);
+    void connect();
     void connect(const Url *url);
     void disconnect();
     void login(const char *user, const char *pass, const char *agent);
     void send(char *data);
+    void setUrl(const Url *url);
 
+    inline int id() const            { return m_id; }
     inline SocketState state() const { return m_state; }
 
 private:
@@ -82,6 +84,7 @@ private:
     char *m_host;
     char m_rpcId[64];
     IClientListener *m_listener;
+    int m_id;
     int64_t m_retries;
     int64_t m_sequence;
     Job m_job;
diff --git a/src/net/Network.cpp b/src/net/Network.cpp
index f87c41d57..1f0a55e95 100644
--- a/src/net/Network.cpp
+++ b/src/net/Network.cpp
@@ -23,30 +23,37 @@
 
 
 #include <uv.h>
+#include <memory>
 
 
 #include "Console.h"
 #include "net/Client.h"
 #include "net/Network.h"
+#include "net/Url.h"
 #include "Options.h"
 
 
 Network::Network(const Options *options) :
-    m_backupPool(nullptr),
-    m_donatePool(nullptr),
-    m_pool(nullptr),
-    m_options(options)
+    m_donate(false),
+    m_options(options),
+    m_pool(1)
 {
+    m_pools.reserve(2);
     m_agent = userAgent();
-    m_pool = new Client(this);
+
+    std::unique_ptr<Url> url(new Url("donate.xmrig.com", 443));
+
+    addPool(url.get());
+    addPool(m_options->url());
+    addPool(m_options->backupUrl());
 }
 
 
 Network::~Network()
 {
-    delete m_pool;
-    delete m_donatePool;
-    delete m_backupPool;
+    for (auto client : m_pools) {
+        delete client;
+    }
 
     free(m_agent);
 }
@@ -54,8 +61,7 @@ Network::~Network()
 
 void Network::connect()
 {
-    m_pool->connect(m_options->url());
-//    LOG_DEBUG("XX %s", m_options->url());
+    m_pools.at(m_pool)->connect();
 }
 
 
@@ -74,3 +80,16 @@ void Network::onLoginCredentialsRequired(Client *client)
 void Network::onLoginSuccess(Client *client)
 {
 }
+
+
+void Network::addPool(const Url *url)
+{
+    if (!url) {
+        return;
+    }
+
+    Client *client = new Client(m_pools.size(), this);
+    client->setUrl(url);
+
+    m_pools.push_back(client);
+}
diff --git a/src/net/Network.h b/src/net/Network.h
index 87e319090..2b7cf2082 100644
--- a/src/net/Network.h
+++ b/src/net/Network.h
@@ -25,10 +25,14 @@
 #define __NETWORK_H__
 
 
+#include <vector>
+
+
 #include "interfaces/IClientListener.h"
 
 
 class Options;
+class Url;
 
 
 class Network : public IClientListener
@@ -47,11 +51,13 @@ protected:
   void onLoginSuccess(Client *client) override;
 
 private:
+  void addPool(const Url *url);
+
+  bool m_donate;
   char *m_agent;
-  Client *m_backupPool;
-  Client *m_donatePool;
-  Client *m_pool;
   const Options *m_options;
+  int m_pool;
+  std::vector<Client*> m_pools;
 };