Browse Source

tabs to spaces in server

pull/123/head
notgiven688 2 years ago
parent
commit
c3be98318d
11 changed files with 628 additions and 629 deletions
  1. +26
    -26
      server/Server/AlgorithmHelper.cs
  2. +3
    -4
      server/Server/CConsole.cs
  3. +141
    -141
      server/Server/EmptyWebsocket.cs
  4. +5
    -5
      server/Server/Extensions.cs
  5. +84
    -84
      server/Server/Firewall.cs
  6. +18
    -18
      server/Server/Helper.cs
  7. +15
    -15
      server/Server/JSONParser.cs
  8. +253
    -253
      server/Server/PoolConnection.cs
  9. +46
    -46
      server/Server/PoolList.cs
  10. +14
    -14
      server/Server/Program.cs
  11. +23
    -23
      server/Server/Random2.cs

+ 26
- 26
server/Server/AlgorithmHelper.cs View File

@ -26,12 +26,12 @@ using JsonData = System.Collections.Generic.Dictionary;
namespace Server {
public class AlgorithmHelper {
public class AlgorithmHelper {
// quite a mess
// https://github.com/xmrig/xmrig-proxy/blob/dev/doc/STRATUM_EXT.md#mining-algorithm-negotiation
// quite a mess
// https://github.com/xmrig/xmrig-proxy/blob/dev/doc/STRATUM_EXT.md#mining-algorithm-negotiation
private static Dictionary<string, Tuple<string, int>> lookup = new Dictionary<string, Tuple<string, int>>
private static Dictionary<string, Tuple<string, int>> lookup = new Dictionary<string, Tuple<string, int>>
{
{ "cryptonight/0", new Tuple<string, int>("cn", 0) },
{ "cryptonight/1", new Tuple<string, int>("cn", 1) },
@ -39,7 +39,7 @@ namespace Server {
{ "cryptonight-lite/0", new Tuple<string, int>("cn-lite", 0) },
{ "cryptonight-lite/1", new Tuple<string, int>("cn-lite", 1) },
{ "cryptonight-lite/2", new Tuple<string, int>("cn-lite", 2) },
{ "cn/0", new Tuple<string, int>("cn", 0) },
{ "cn/0", new Tuple<string, int>("cn", 0) },
{ "cn/1", new Tuple<string, int>("cn", 1) },
{ "cn/2", new Tuple<string, int>("cn", 2) },
{ "cn-lite/0", new Tuple<string, int>("cn-lite", 0) },
@ -47,9 +47,9 @@ namespace Server {
{ "cn-lite/2", new Tuple<string, int>("cn-lite", 2) }
};
public static bool NormalizeAlgorithmAndVariant (JsonData job) {
public static bool NormalizeAlgorithmAndVariant (JsonData job) {
string algo = job["algo"].GetString().ToLower();
string algo = job["algo"].GetString().ToLower();
if (algo == "cn" || algo == "cryptonight")
job["algo"] = "cn";
@ -67,23 +67,23 @@ namespace Server {
}
/*if (lookup.ContainsKey(algo))
{
var tuple = lookup[algo];
job["algo"] = tuple.Item1;
job["variant"] = tuple.Item2;
}
else
{
if (algo == "cn" || algo == "cryptonight")
job["algo"] = "cn";
else if (algo == "cn-lite" || algo == "cryptonight-lite")
job["algo"] = "cn-lite";
else return false;
}*/
return true;
}
}
/*if (lookup.ContainsKey(algo))
{
var tuple = lookup[algo];
job["algo"] = tuple.Item1;
job["variant"] = tuple.Item2;
}
else
{
if (algo == "cn" || algo == "cryptonight")
job["algo"] = "cn";
else if (algo == "cn-lite" || algo == "cryptonight-lite")
job["algo"] = "cn-lite";
else return false;
}*/
return true;
}
}
}

+ 3
- 4
server/Server/CConsole.cs View File

@ -29,9 +29,8 @@ namespace Server {
public static class CConsole {
// Info, Alert, Warning
private static object locker = new object ();
private static bool enabled = true;
private static readonly object locker = new object ();
private static readonly bool enabled = true;
static CConsole () {
try {
@ -39,7 +38,7 @@ namespace Server {
Console.ForegroundColor = ConsoleColor.Black;
Console.ResetColor ();
} catch {
// ArgumentException, SecurityException, IOException .
// ArgumentException, SecurityException, IOException.
enabled = false;
}
}

+ 141
- 141
server/Server/EmptyWebsocket.cs View File

@ -25,149 +25,149 @@ using Fleck;
namespace Server {
public class EmptyConnectionInfo : IWebSocketConnectionInfo {
#region IWebSocketConnectionInfo implementation
public string SubProtocol {
get {
throw new NotImplementedException ();
}
}
public string Origin {
get {
throw new NotImplementedException ();
}
}
public string Host {
get {
throw new NotImplementedException ();
}
}
public string Path {
get {
throw new NotImplementedException ();
}
}
public string ClientIpAddress {
get {
return "127.0.0.1";
}
}
public int ClientPort {
get {
throw new NotImplementedException ();
}
}
public IDictionary<string, string> Cookies {
get {
throw new NotImplementedException ();
}
}
public IDictionary<string, string> Headers {
get {
throw new NotImplementedException ();
}
}
public Guid Id {
get {
return Guid.Empty;
}
}
public string NegotiatedSubProtocol {
get {
throw new NotImplementedException ();
}
}
#endregion
}
public class EmptyConnectionInfo : IWebSocketConnectionInfo {
#region IWebSocketConnectionInfo implementation
public string SubProtocol {
get {
throw new NotImplementedException ();
}
}
public string Origin {
get {
throw new NotImplementedException ();
}
}
public string Host {
get {
throw new NotImplementedException ();
}
}
public string Path {
get {
throw new NotImplementedException ();
}
}
public string ClientIpAddress {
get {
return "127.0.0.1";
}
}
public int ClientPort {
get {
throw new NotImplementedException ();
}
}
public IDictionary<string, string> Cookies {
get {
throw new NotImplementedException ();
}
}
public IDictionary<string, string> Headers {
get {
throw new NotImplementedException ();
}
}
public Guid Id {
get {
return Guid.Empty;
}
}
public string NegotiatedSubProtocol {
get {
throw new NotImplementedException ();
}
}
#endregion
}
public class EmptyWebsocket : IWebSocketConnection {
private static EmptyConnectionInfo eci =
new EmptyConnectionInfo ();
public class EmptyWebsocket : IWebSocketConnection {
private static EmptyConnectionInfo eci =
new EmptyConnectionInfo ();
#region IWebSocketConnection implementation
public System.Threading.Tasks.Task Send (string message) {
//throw new NotImplementedException ();
return null;
}
public System.Threading.Tasks.Task Send (byte[] message) {
throw new NotImplementedException ();
}
public System.Threading.Tasks.Task SendPing (byte[] message) {
throw new NotImplementedException ();
}
public System.Threading.Tasks.Task SendPong (byte[] message) {
throw new NotImplementedException ();
}
public void Close () {
#region IWebSocketConnection implementation
public System.Threading.Tasks.Task Send (string message) {
//throw new NotImplementedException ();
return null;
}
public System.Threading.Tasks.Task Send (byte[] message) {
throw new NotImplementedException ();
}
public System.Threading.Tasks.Task SendPing (byte[] message) {
throw new NotImplementedException ();
}
public System.Threading.Tasks.Task SendPong (byte[] message) {
throw new NotImplementedException ();
}
public void Close () {
}
public Action OnOpen {
get {
throw new NotImplementedException ();
}
set {
throw new NotImplementedException ();
}
}
public Action OnClose {
get {
throw new NotImplementedException ();
}
set {
throw new NotImplementedException ();
}
}
public Action<string> OnMessage {
get {
throw new NotImplementedException ();
}
set {
throw new NotImplementedException ();
}
}
public Action<byte[]> OnBinary {
get {
throw new NotImplementedException ();
}
set {
throw new NotImplementedException ();
}
}
public Action<byte[]> OnPing {
get {
throw new NotImplementedException ();
}
set {
throw new NotImplementedException ();
}
}
public Action<byte[]> OnPong {
get {
throw new NotImplementedException ();
}
set {
throw new NotImplementedException ();
}
}
public Action<Exception> OnError {
get {
throw new NotImplementedException ();
}
set {
throw new NotImplementedException ();
}
}
public IWebSocketConnectionInfo ConnectionInfo {
get {
return EmptyWebsocket.eci;
}
}
public bool IsAvailable {
get {
return false;
}
}
#endregion
}
}
public Action OnOpen {
get {
throw new NotImplementedException ();
}
set {
throw new NotImplementedException ();
}
}
public Action OnClose {
get {
throw new NotImplementedException ();
}
set {
throw new NotImplementedException ();
}
}
public Action<string> OnMessage {
get {
throw new NotImplementedException ();
}
set {
throw new NotImplementedException ();
}
}
public Action<byte[]> OnBinary {
get {
throw new NotImplementedException ();
}
set {
throw new NotImplementedException ();
}
}
public Action<byte[]> OnPing {
get {
throw new NotImplementedException ();
}
set {
throw new NotImplementedException ();
}
}
public Action<byte[]> OnPong {
get {
throw new NotImplementedException ();
}
set {
throw new NotImplementedException ();
}
}
public Action<Exception> OnError {
get {
throw new NotImplementedException ();
}
set {
throw new NotImplementedException ();
}
}
public IWebSocketConnectionInfo ConnectionInfo {
get {
return EmptyWebsocket.eci;
}
}
public bool IsAvailable {
get {
return false;
}
}
#endregion
}
}

+ 5
- 5
server/Server/Extensions.cs View File

@ -21,10 +21,10 @@
namespace System {
public static class ObjectExtensionClass {
public static string GetString (this object input) {
return input == null ? string.Empty : input.ToString ();
}
}
public static class ObjectExtensionClass {
public static string GetString (this object input) {
return input == null ? string.Empty : input.ToString ();
}
}
}

+ 84
- 84
server/Server/Firewall.cs View File

@ -27,88 +27,88 @@ using System.Text;
using System.Threading.Tasks;
namespace Server {
public static class Firewall {
public enum UpdateEntry {
SolvedJob,
AuthSuccess,
AuthFailure,
WrongHash,
Handshake
}
private class Entry {
public string Address;
public Entry (string adr) {
Address = adr;
}
public int SolvedJobs = 0;
public int WrongHash = 0;
public int AuthSuccess = 0;
public int AuthFailure = 0;
public int Handshake = 0;
public DateTime FirstSeen = DateTime.Now;
}
private static CcDictionary<string, Entry> entries = new CcDictionary<string, Entry> ();
public const int CheckTimeInHeartbeats = 6 * 10; // every 10min
private static void AddToIpTables (Entry entry, int rule) {
Helper.WriteTextAsyncWrapper ("ip_list", entry.Address + Environment.NewLine);
CConsole.ColorWarning(() => Console.WriteLine ("Added {0} to ip_list (rule #{1})", entry.Address, rule.ToString ()));
entries.TryRemove (entry.Address);
}
public static void Update (string ip, UpdateEntry update) {
Entry entry = null;
if (entries.TryGetValue (ip, out entry)) {
if (update == UpdateEntry.SolvedJob)
entry.SolvedJobs++;
else if (update == UpdateEntry.AuthFailure)
entry.AuthFailure++;
else if (update == UpdateEntry.AuthSuccess)
entry.AuthSuccess++;
else if (update == UpdateEntry.WrongHash)
entry.WrongHash++;
else if (update == UpdateEntry.Handshake)
entry.Handshake++;
} else {
entries.TryAdd (ip, new Entry (ip));
}
}
public static void Heartbeat (int heartBeats) {
List<Entry> entrylst = new List<Entry> (entries.Values);
foreach (Entry entry in entrylst) {
// decide here...
if (entry.AuthSuccess == 0 && entry.SolvedJobs == 0 &&
entry.AuthFailure > 20) {
AddToIpTables (entry, 1);
} else if (entry.AuthFailure > 500 && entry.AuthSuccess < 500) {
AddToIpTables (entry, 2);
} else if (entry.AuthSuccess + entry.AuthFailure > 1000 && entry.SolvedJobs < 3) {
AddToIpTables (entry, 3);
} else if (entry.AuthSuccess + entry.AuthFailure > 4000) {
AddToIpTables (entry, 4);
} else if (entry.WrongHash > 0 && entry.AuthSuccess < 5) {
AddToIpTables (entry, 5);
} else if (entry.AuthSuccess + entry.AuthFailure > 2000 && entry.Handshake < 1) {
AddToIpTables (entry, 6);
}
}
if ((heartBeats % CheckTimeInHeartbeats) == 0) {
entries.Clear ();
}
}
}
public static class Firewall {
public enum UpdateEntry {
SolvedJob,
AuthSuccess,
AuthFailure,
WrongHash,
Handshake
}
private class Entry {
public string Address;
public Entry (string adr) {
Address = adr;
}
public int SolvedJobs = 0;
public int WrongHash = 0;
public int AuthSuccess = 0;
public int AuthFailure = 0;
public int Handshake = 0;
public DateTime FirstSeen = DateTime.Now;
}
private static CcDictionary<string, Entry> entries = new CcDictionary<string, Entry> ();
public const int CheckTimeInHeartbeats = 6 * 10; // every 10min
private static void AddToIpTables (Entry entry, int rule) {
Helper.WriteTextAsyncWrapper ("ip_list", entry.Address + Environment.NewLine);
CConsole.ColorWarning(() => Console.WriteLine ("Added {0} to ip_list (rule #{1})", entry.Address, rule.ToString ()));
entries.TryRemove (entry.Address);
}
public static void Update (string ip, UpdateEntry update) {
Entry entry = null;
if (entries.TryGetValue (ip, out entry)) {
if (update == UpdateEntry.SolvedJob)
entry.SolvedJobs++;
else if (update == UpdateEntry.AuthFailure)
entry.AuthFailure++;
else if (update == UpdateEntry.AuthSuccess)
entry.AuthSuccess++;
else if (update == UpdateEntry.WrongHash)
entry.WrongHash++;
else if (update == UpdateEntry.Handshake)
entry.Handshake++;
} else {
entries.TryAdd (ip, new Entry (ip));
}
}
public static void Heartbeat (int heartBeats) {
List<Entry> entrylst = new List<Entry> (entries.Values);
foreach (Entry entry in entrylst) {
// decide here...
if (entry.AuthSuccess == 0 && entry.SolvedJobs == 0 &&
entry.AuthFailure > 20) {
AddToIpTables (entry, 1);
} else if (entry.AuthFailure > 500 && entry.AuthSuccess < 500) {
AddToIpTables (entry, 2);
} else if (entry.AuthSuccess + entry.AuthFailure > 1000 && entry.SolvedJobs < 3) {
AddToIpTables (entry, 3);
} else if (entry.AuthSuccess + entry.AuthFailure > 4000) {
AddToIpTables (entry, 4);
} else if (entry.WrongHash > 0 && entry.AuthSuccess < 5) {
AddToIpTables (entry, 5);
} else if (entry.AuthSuccess + entry.AuthFailure > 2000 && entry.Handshake < 1) {
AddToIpTables (entry, 6);
}
}
if ((heartBeats % CheckTimeInHeartbeats) == 0) {
entries.Clear ();
}
}
}
}

+ 18
- 18
server/Server/Helper.cs View File

@ -26,22 +26,22 @@ using System.Threading.Tasks;
namespace Server {
public class Helper {
public static void WriteTextAsyncWrapper (string filePath, string text, FileMode fileMode = FileMode.Append) {
#pragma warning disable 4014
WriteTextAsync (filePath, text, fileMode);
#pragma warning restore 4014
}
public static async Task WriteTextAsync (string filePath, string text, FileMode fileMode = FileMode.Append) {
byte[] encodedText = Encoding.ASCII.GetBytes (text);
using (FileStream sourceStream = new FileStream (filePath,
fileMode, FileAccess.Write, FileShare.None,
bufferSize : 4096, useAsync : true)) {
await sourceStream.WriteAsync (encodedText, 0, encodedText.Length);
};
}
}
public class Helper {
public static void WriteTextAsyncWrapper (string filePath, string text, FileMode fileMode = FileMode.Append) {
#pragma warning disable 4014
WriteTextAsync (filePath, text, fileMode);
#pragma warning restore 4014
}
public static async Task WriteTextAsync (string filePath, string text, FileMode fileMode = FileMode.Append) {
byte[] encodedText = Encoding.ASCII.GetBytes (text);
using (FileStream sourceStream = new FileStream (filePath,
fileMode, FileAccess.Write, FileShare.None,
bufferSize : 4096, useAsync : true)) {
await sourceStream.WriteAsync (encodedText, 0, encodedText.Length);
};
}
}
}

+ 15
- 15
server/Server/JSONParser.cs View File

@ -147,19 +147,19 @@ namespace TinyJson {
string str = json.Substring (1, json.Length - 2);
return str.Replace ("\\\\", "\"\"").Replace ("\\", string.Empty).Replace ("\"\"", "\\");
}
if (type == typeof (int)) {
int result;
int.TryParse (json, out result);
if (type == typeof (int))
{
int.TryParse(json, out int result);
return result;
}
if (type == typeof (float)) {
float result;
float.TryParse (json, out result);
if (type == typeof (float))
{
float.TryParse(json, out float result);
return result;
}
if (type == typeof (double)) {
double result;
double.TryParse (json, out result);
if (type == typeof (double))
{
double.TryParse(json, out double result);
return result;
}
if (type == typeof (bool)) {
@ -254,13 +254,13 @@ namespace TinyJson {
return str.Replace ("\\", string.Empty);
}
if (char.IsDigit (json[0]) || json[0] == '-') {
if (json.Contains (".")) {
double result;
double.TryParse (json, out result);
if (json.Contains ("."))
{
double.TryParse(json, out double result);
return result;
} else {
int result;
int.TryParse (json, out result);
} else
{
int.TryParse(json, out int result);
return result;
}
}

+ 253
- 253
server/Server/PoolConnection.cs View File

@ -34,384 +34,384 @@ using Fleck;
namespace Server {
public class PoolConnection {
public TcpClient TcpClient;
public class PoolConnection {
public TcpClient TcpClient;
public byte[] ReceiveBuffer;
public byte[] ReceiveBuffer;
public string Login;
public string Password;
public int Port;
public string Url;
public bool Closed;
public string Login;
public string Password;
public int Port;
public string Url;
public bool Closed;
public string PoolId;
public string Credentials;
public string PoolId;
public string Credentials;
public long Hashes = 0;
public long Hashes = 0;
public Client LastSender;
public JsonData LastJob;
public DateTime LastInteraction = DateTime.Now;
public CcHashset<string> LastSolved;
public Client LastSender;
public JsonData LastJob;
public DateTime LastInteraction = DateTime.Now;
public CcHashset<string> LastSolved;
public string DefaultAlgorithm = "cn";
public int DefaultVariant = -1;
public string DefaultAlgorithm = "cn";
public int DefaultVariant = -1;
public CcHashset<Client> WebClients = new CcHashset<Client> ();
public CcHashset<Client> WebClients = new CcHashset<Client> ();
public void Send (Client client, string msg) {
try {
Byte[] bytesSent = Encoding.ASCII.GetBytes (msg);
TcpClient.GetStream ().BeginWrite (bytesSent, 0, bytesSent.Length, SendCallback, null);
this.LastSender = client;
} catch { }
}
public void Send (Client client, string msg) {
try {
Byte[] bytesSent = Encoding.ASCII.GetBytes (msg);
TcpClient.GetStream ().BeginWrite (bytesSent, 0, bytesSent.Length, SendCallback, null);
this.LastSender = client;
} catch { }
}
private void SendCallback (IAsyncResult result) {
if (!TcpClient.Connected) return;
private void SendCallback (IAsyncResult result) {
if (!TcpClient.Connected) return;
try {
NetworkStream networkStream = TcpClient.GetStream ();
networkStream.EndWrite (result);
} catch { }
}
try {
NetworkStream networkStream = TcpClient.GetStream ();
networkStream.EndWrite (result);
} catch { }
}
}
public class PoolConnectionFactory {
public delegate void ReceiveJobDelegate (Client client, JsonData json, CcHashset<string> hashset);
public delegate void ReceiveErrorDelegate (Client client, JsonData json);
public delegate void DisconnectedDelegate (Client client, string reason);
}
public class PoolConnectionFactory {
public delegate void ReceiveJobDelegate (Client client, JsonData json, CcHashset<string> hashset);
public delegate void ReceiveErrorDelegate (Client client, JsonData json);
public delegate void DisconnectedDelegate (Client client, string reason);
private static ReceiveErrorDelegate ReceiveError;
private static ReceiveJobDelegate ReceiveJob;
private static DisconnectedDelegate Disconnect;
private static ReceiveErrorDelegate ReceiveError;
private static ReceiveJobDelegate ReceiveJob;
private static DisconnectedDelegate Disconnect;
public static CcDictionary<string, PoolConnection> Connections = new CcDictionary<string, PoolConnection> ();
public static CcDictionary<string, PoolConnection> Connections = new CcDictionary<string, PoolConnection> ();
private static bool VerifyJob (JsonData data) {
if (data == null) return false;
private static bool VerifyJob (JsonData data) {
if (data == null) return false;
if (!data.ContainsKey ("job_id")) return false;
if (!data.ContainsKey ("blob")) return false;
if (!data.ContainsKey ("target")) return false;
if (!data.ContainsKey ("job_id")) return false;
if (!data.ContainsKey ("blob")) return false;
if (!data.ContainsKey ("target")) return false;
string blob = data["blob"].GetString ();
string target = data["target"].GetString ();
string blob = data["blob"].GetString ();
string target = data["target"].GetString ();
if (blob.Length < 152 || blob.Length > 180) return false;
if (target.Length != 8) return false;
if (target.Length != 8) return false;
if (!Regex.IsMatch (blob, MainClass.RegexIsHex)) return false;
if (!Regex.IsMatch (target, MainClass.RegexIsHex)) return false;
if (!Regex.IsMatch (blob, MainClass.RegexIsHex)) return false;
if (!Regex.IsMatch (target, MainClass.RegexIsHex)) return false;
return true;
}
return true;
}
private static void ReceiveCallback (IAsyncResult result) {
private static void ReceiveCallback (IAsyncResult result) {
PoolConnection mypc = result.AsyncState as PoolConnection;
TcpClient client = mypc.TcpClient;
PoolConnection mypc = result.AsyncState as PoolConnection;
TcpClient client = mypc.TcpClient;
if (mypc.Closed || !client.Connected) return;
if (mypc.Closed || !client.Connected) return;
NetworkStream networkStream;
NetworkStream networkStream;
try { networkStream = client.GetStream (); } catch { return; }
try { networkStream = client.GetStream (); } catch { return; }
int bytesread = 0;
int bytesread = 0;
try { bytesread = networkStream.EndRead (result); } catch { return; }
try { bytesread = networkStream.EndRead (result); } catch { return; }
string json = string.Empty;
string json = string.Empty;
try {
if (bytesread == 0) // disconnected
{
try {
if (bytesread == 0) // disconnected
{
// slow that down a bit to avoid negative feedback loop
// slow that down a bit to avoid negative feedback loop
Task.Run (async delegate {
await Task.Delay (TimeSpan.FromSeconds (4));
Task.Run (async delegate {
await Task.Delay (TimeSpan.FromSeconds (4));
List<Client> cllist = new List<Client> (mypc.WebClients.Values);
foreach (Client ev in cllist) Disconnect (ev, "lost pool connection.");
});
List<Client> cllist = new List<Client> (mypc.WebClients.Values);
foreach (Client ev in cllist) Disconnect (ev, "lost pool connection.");
});
return;
}
return;
}
json = Encoding.ASCII.GetString (mypc.ReceiveBuffer, 0, bytesread);
json = Encoding.ASCII.GetString (mypc.ReceiveBuffer, 0, bytesread);
networkStream.BeginRead (mypc.ReceiveBuffer, 0, mypc.ReceiveBuffer.Length, new AsyncCallback (ReceiveCallback), mypc);
networkStream.BeginRead (mypc.ReceiveBuffer, 0, mypc.ReceiveBuffer.Length, new AsyncCallback (ReceiveCallback), mypc);
} catch { return; }
} catch { return; }
if (bytesread == 0 || string.IsNullOrEmpty (json)) return; //?!
if (bytesread == 0 || string.IsNullOrEmpty (json)) return; //?!
var msg = json.FromJson<JsonData> ();
if (msg == null) return;
var msg = json.FromJson<JsonData> ();
if (msg == null) return;
if (string.IsNullOrEmpty (mypc.PoolId)) {
if (string.IsNullOrEmpty (mypc.PoolId)) {
// this "protocol" is strange
if (!msg.ContainsKey ("result")) {
// this "protocol" is strange
if (!msg.ContainsKey ("result")) {
string additionalInfo = "none";
string additionalInfo = "none";
// try to get the error
if (msg.ContainsKey ("error")) {
msg = msg["error"] as JsonData;
// try to get the error
if (msg.ContainsKey ("error")) {
msg = msg["error"] as JsonData;
if (msg != null && msg.ContainsKey ("message"))
additionalInfo = msg["message"].GetString ();
}
if (msg != null && msg.ContainsKey ("message"))
additionalInfo = msg["message"].GetString ();
}
List<Client> cllist = new List<Client> (mypc.WebClients.Values);
foreach (Client ev in cllist)
Disconnect (ev, "can not connect. additional information: " + additionalInfo);
List<Client> cllist = new List<Client> (mypc.WebClients.Values);
foreach (Client ev in cllist)
Disconnect (ev, "can not connect. additional information: " + additionalInfo);
return;
}
return;
}
msg = msg["result"] as JsonData;
msg = msg["result"] as JsonData;
if (msg == null)
return;
if (!msg.ContainsKey ("id"))
return;
if (!msg.ContainsKey ("job"))
return;
if (msg == null)
return;
if (!msg.ContainsKey ("id"))
return;
if (!msg.ContainsKey ("job"))
return;
mypc.PoolId = msg["id"].GetString ();
mypc.PoolId = msg["id"].GetString ();
var lastjob = msg["job"] as JsonData;
var lastjob = msg["job"] as JsonData;
if (!VerifyJob (lastjob)) {
CConsole.ColorWarning(() =>
Console.WriteLine ("Failed to verify job: {0}", json));
return;
}
if (!VerifyJob (lastjob)) {
CConsole.ColorWarning(() =>
Console.WriteLine ("Failed to verify job: {0}", json));
return;
}
// extended stratum
if(!lastjob.ContainsKey("variant")) lastjob.Add("variant",mypc.DefaultVariant);
if(!lastjob.ContainsKey("algo")) lastjob.Add("algo",mypc.DefaultAlgorithm);
AlgorithmHelper.NormalizeAlgorithmAndVariant(lastjob);
// extended stratum
if(!lastjob.ContainsKey("variant")) lastjob.Add("variant",mypc.DefaultVariant);
if(!lastjob.ContainsKey("algo")) lastjob.Add("algo",mypc.DefaultAlgorithm);
AlgorithmHelper.NormalizeAlgorithmAndVariant(lastjob);
mypc.LastJob = lastjob;
mypc.LastInteraction = DateTime.Now;
mypc.LastJob = lastjob;
mypc.LastInteraction = DateTime.Now;
mypc.LastSolved = new CcHashset<string> ();
mypc.LastSolved = new CcHashset<string> ();
List<Client> cllist2 = new List<Client> (mypc.WebClients.Values);
foreach (Client ev in cllist2) {
ReceiveJob (ev, mypc.LastJob, mypc.LastSolved);
}
List<Client> cllist2 = new List<Client> (mypc.WebClients.Values);
foreach (Client ev in cllist2) {
ReceiveJob (ev, mypc.LastJob, mypc.LastSolved);
}
} else if (msg.ContainsKey ("method") && msg["method"].GetString () == "job") {
if (!msg.ContainsKey ("params"))
return;
} else if (msg.ContainsKey ("method") && msg["method"].GetString () == "job") {
if (!msg.ContainsKey ("params"))
return;
var lastjob = msg["params"] as JsonData;
var lastjob = msg["params"] as JsonData;
if (!VerifyJob (lastjob)) {
CConsole.ColorWarning(() =>
Console.WriteLine ("Failed to verify job: {0}", json));
return;
}
if (!VerifyJob (lastjob)) {
CConsole.ColorWarning(() =>
Console.WriteLine ("Failed to verify job: {0}", json));
return;
}
// extended stratum
// extended stratum
if (!lastjob.ContainsKey("variant")) lastjob.Add("variant", mypc.DefaultVariant);
if (!lastjob.ContainsKey("algo")) lastjob.Add("algo", mypc.DefaultAlgorithm);
AlgorithmHelper.NormalizeAlgorithmAndVariant(lastjob);
AlgorithmHelper.NormalizeAlgorithmAndVariant(lastjob);
mypc.LastJob = lastjob;
mypc.LastInteraction = DateTime.Now;
mypc.LastSolved = new CcHashset<string> ();
mypc.LastJob = lastjob;
mypc.LastInteraction = DateTime.Now;
mypc.LastSolved = new CcHashset<string> ();
List<Client> cllist2 = new List<Client> (mypc.WebClients.Values);
List<Client> cllist2 = new List<Client> (mypc.WebClients.Values);
Console.WriteLine ("Sending job to {0} client(s)!", cllist2.Count);
Console.WriteLine ("Sending job to {0} client(s)!", cllist2.Count);
foreach (Client ev in cllist2) {
ReceiveJob (ev, mypc.LastJob, mypc.LastSolved);
}
foreach (Client ev in cllist2) {
ReceiveJob (ev, mypc.LastJob, mypc.LastSolved);
}
} else {
if (msg.ContainsKey ("error")) {
// who knows?
ReceiveError (mypc.LastSender, msg);
} else {
if (msg.ContainsKey ("error")) {
// who knows?
ReceiveError (mypc.LastSender, msg);
} else {
CConsole.ColorWarning(() =>
Console.WriteLine ("Pool is sending nonsense."));
}
}
}
} else {
CConsole.ColorWarning(() =>
Console.WriteLine ("Pool is sending nonsense."));
}
}
}
private static void ConnectCallback (IAsyncResult result) {
private static void ConnectCallback (IAsyncResult result) {
PoolConnection mypc = result.AsyncState as PoolConnection;
TcpClient client = mypc.TcpClient;
PoolConnection mypc = result.AsyncState as PoolConnection;
TcpClient client = mypc.TcpClient;
if (!mypc.Closed && client.Connected) {
if (!mypc.Closed && client.Connected) {
try {
NetworkStream networkStream = client.GetStream ();
mypc.ReceiveBuffer = new byte[client.ReceiveBufferSize];
try {
NetworkStream networkStream = client.GetStream ();
mypc.ReceiveBuffer = new byte[client.ReceiveBufferSize];
networkStream.BeginRead (mypc.ReceiveBuffer, 0, mypc.ReceiveBuffer.Length, new AsyncCallback (ReceiveCallback), mypc);
networkStream.BeginRead (mypc.ReceiveBuffer, 0, mypc.ReceiveBuffer.Length, new AsyncCallback (ReceiveCallback), mypc);
// keep things stupid and simple
// keep things stupid and simple
// https://github.com/xmrig/xmrig-proxy/blob/dev/doc/STRATUM_EXT.md#mining-algorithm-negotiation
string msg0 = "{\"method\":\"login\",\"params\":{\"login\":\"";
string msg1 = "\",\"pass\":\"";
string msg2 = "\",\"agent\":\"webminerpool.com\",\"algo\": [\"cn/0\",\"cn/1\",\"cn/2\",\"cn-lite/0\",\"cn-lite/1\",\"cn-lite/2\"]}, \"id\":1}";
string msg = msg0 + mypc.Login + msg1 + mypc.Password + msg2 + "\n";
string msg0 = "{\"method\":\"login\",\"params\":{\"login\":\"";
string msg1 = "\",\"pass\":\"";
string msg2 = "\",\"agent\":\"webminerpool.com\",\"algo\": [\"cn/0\",\"cn/1\",\"cn/2\",\"cn-lite/0\",\"cn-lite/1\",\"cn-lite/2\"]}, \"id\":1}";
string msg = msg0 + mypc.Login + msg1 + mypc.Password + msg2 + "\n";
mypc.Send (mypc.LastSender, msg);
} catch { return; }
} else {
mypc.Send (mypc.LastSender, msg);
} catch { return; }
} else {
// slow that down a bit
// slow that down a bit
Task.Run (async delegate {
await Task.Delay (TimeSpan.FromSeconds (4));
Task.Run (async delegate {
await Task.Delay (TimeSpan.FromSeconds (4));
List<Client> cllist = new List<Client> (mypc.WebClients.Values);
foreach (Client ev in cllist)
Disconnect (ev, "can not connect to pool.");
});
List<Client> cllist = new List<Client> (mypc.WebClients.Values);
foreach (Client ev in cllist)
Disconnect (ev, "can not connect to pool.");
});
}
}
}
}
public static void Close (Client client) {
PoolConnection connection = client.PoolConnection;
public static void Close (Client client) {
PoolConnection connection = client.PoolConnection;
connection.WebClients.TryRemove (client);
connection.WebClients.TryRemove (client);
if (connection.WebClients.Count == 0) {
if (connection.WebClients.Count == 0) {
connection.Closed = true;
connection.Closed = true;
try {
var networkStream = connection.TcpClient.GetStream ();
networkStream.EndRead (null);
} catch { }
try {
var networkStream = connection.TcpClient.GetStream ();
networkStream.EndRead (null);
} catch { }
try { connection.TcpClient.Close ();} catch { }
try { connection.TcpClient.Client.Close ();} catch { }
try { connection.ReceiveBuffer = null;} catch { }
try { connection.TcpClient.Close ();} catch { }
try { connection.TcpClient.Client.Close ();} catch { }
try { connection.ReceiveBuffer = null;} catch { }
Connections.TryRemove(connection.Credentials);
Connections.TryRemove(connection.Credentials);
Console.WriteLine ("{0}: closed a pool connection.", client.WebSocket.ConnectionInfo.Id);
Console.WriteLine ("{0}: closed a pool connection.", client.WebSocket.ConnectionInfo.Id);
}
}
}
}
public static void RegisterCallbacks (ReceiveJobDelegate receiveJob, ReceiveErrorDelegate receiveError, DisconnectedDelegate disconnect) {
PoolConnectionFactory.ReceiveJob = receiveJob;
PoolConnectionFactory.ReceiveError = receiveError;
PoolConnectionFactory.Disconnect = disconnect;
}
public static void RegisterCallbacks (ReceiveJobDelegate receiveJob, ReceiveErrorDelegate receiveError, DisconnectedDelegate disconnect) {
PoolConnectionFactory.ReceiveJob = receiveJob;
PoolConnectionFactory.ReceiveError = receiveError;
PoolConnectionFactory.Disconnect = disconnect;
}
public static void CheckPoolConnection (PoolConnection connection) {
public static void CheckPoolConnection (PoolConnection connection) {
if (connection.Closed) return;
if (connection.Closed) return;
if ((DateTime.Now - connection.LastInteraction).TotalMinutes < 10)
return;
if ((DateTime.Now - connection.LastInteraction).TotalMinutes < 10)
return;
CConsole.ColorWarning(() => Console.WriteLine ("Initiating reconnect! {0}:{1}", connection.Url, connection.Login));
CConsole.ColorWarning(() => Console.WriteLine ("Initiating reconnect! {0}:{1}", connection.Url, connection.Login));
try {
var networkStream = connection.TcpClient.GetStream ();
networkStream.EndRead (null);
} catch { }
try {
var networkStream = connection.TcpClient.GetStream ();
networkStream.EndRead (null);
} catch { }
try { connection.TcpClient.Close (); } catch { }
try { connection.TcpClient.Client.Close (); } catch { }
connection.ReceiveBuffer = null;
try { connection.TcpClient.Close (); } catch { }
try { connection.TcpClient.Client.Close (); } catch { }
connection.ReceiveBuffer = null;
connection.LastInteraction = DateTime.Now;
connection.LastInteraction = DateTime.Now;
connection.PoolId = "";
connection.LastJob = null;
connection.PoolId = "";
connection.LastJob = null;
connection.TcpClient = new TcpClient ();
connection.TcpClient = new TcpClient ();
Fleck.SocketExtensions.SetKeepAlive (connection.TcpClient.Client, 60000, 1000);
connection.TcpClient.Client.ReceiveBufferSize = 4096 * 2;
Fleck.SocketExtensions.SetKeepAlive (connection.TcpClient.Client, 60000, 1000);
connection.TcpClient.Client.ReceiveBufferSize = 4096 * 2;
try { connection.TcpClient.BeginConnect (connection.Url, connection.Port, new AsyncCallback (ConnectCallback), connection); } catch { }
try { connection.TcpClient.BeginConnect (connection.Url, connection.Port, new AsyncCallback (ConnectCallback), connection); } catch { }
}
}
public static PoolConnection CreatePoolConnection (Client client, string url, int port, string login, string password) {
public static PoolConnection CreatePoolConnection (Client client, string url, int port, string login, string password) {
string credential = url + port.ToString () + login + password;
string credential = url + port.ToString () + login + password;
PoolConnection lpc, mypc = null;
PoolConnection lpc, mypc = null;
int batchCounter = 0;
int batchCounter = 0;
while (Connections.TryGetValue (credential+batchCounter.ToString(), out lpc)) {
if (lpc.WebClients.Count > MainClass.BatchSize) batchCounter++;
else { mypc = lpc; break; }
}
while (Connections.TryGetValue (credential+batchCounter.ToString(), out lpc)) {
if (lpc.WebClients.Count > MainClass.BatchSize) batchCounter++;
else { mypc = lpc; break; }
}
credential += batchCounter.ToString ();
credential += batchCounter.ToString ();
if (mypc == null) {
if (mypc == null) {
CConsole.ColorInfo( () => {
Console.WriteLine ("{0}: initiated new pool connection",client.WebSocket.ConnectionInfo.Id);
Console.WriteLine ("{0} {1} {2}", login, password, url);
});
CConsole.ColorInfo( () => {
Console.WriteLine ("{0}: initiated new pool connection",client.WebSocket.ConnectionInfo.Id);
Console.WriteLine ("{0} {1} {2}", login, password, url);
});
mypc = new PoolConnection ();
mypc.Credentials = credential;
mypc.LastSender = client;
mypc = new PoolConnection ();
mypc.Credentials = credential;
mypc.LastSender = client;
mypc.TcpClient = new TcpClient ();
mypc.TcpClient = new TcpClient ();
Fleck.SocketExtensions.SetKeepAlive (mypc.TcpClient.Client, 60000, 1000);
mypc.TcpClient.Client.ReceiveBufferSize = 4096 * 2;
Fleck.SocketExtensions.SetKeepAlive (mypc.TcpClient.Client, 60000, 1000);
mypc.TcpClient.Client.ReceiveBufferSize = 4096 * 2;
mypc.Login = login;
mypc.Password = password;
mypc.Port = port;
mypc.Url = url;
mypc.Login = login;
mypc.Password = password;
mypc.Port = port;
mypc.Url = url;
mypc.WebClients.TryAdd (client);
mypc.WebClients.TryAdd (client);
Connections.TryAdd (credential, mypc);
Connections.TryAdd (credential, mypc);
try { mypc.TcpClient.Client.BeginConnect (url, port, new AsyncCallback (ConnectCallback), mypc); } catch { }
try { mypc.TcpClient.Client.BeginConnect (url, port, new AsyncCallback (ConnectCallback), mypc); } catch { }
} else {
} else {
Console.WriteLine ("{0}: reusing pool connection", client.WebSocket.ConnectionInfo.Id);
Console.WriteLine ("{0}: reusing pool connection", client.WebSocket.ConnectionInfo.Id);
mypc.WebClients.TryAdd (client);
mypc.WebClients.TryAdd (client);
if (mypc.LastJob != null) ReceiveJob (client, mypc.LastJob, mypc.LastSolved);
else Console.WriteLine ("{0} no job yet.", client.WebSocket.ConnectionInfo.Id);
if (mypc.LastJob != null) ReceiveJob (client, mypc.LastJob, mypc.LastSolved);
else Console.WriteLine ("{0} no job yet.", client.WebSocket.ConnectionInfo.Id);
}
}
client.PoolConnection = mypc;
client.PoolConnection = mypc;
return mypc;
return mypc;
}
}
}
}
}

+ 46
- 46
server/Server/PoolList.cs View File

@ -30,72 +30,72 @@ using JsonData = System.Collections.Generic.Dictionary;
namespace Server {
public struct PoolInfo {
public int Port;
public string Url;
// some pools require a non-empty password
public string EmptyPassword;
public string DefaultAlgorithm;
public int DefaultVariant;
public struct PoolInfo {
public int Port;
public string Url;
// some pools require a non-empty password
public string EmptyPassword;
public string DefaultAlgorithm;
public int DefaultVariant;
public PoolInfo (string url, int port, string emptypw = "", string algo = "cn", int variant = -1) { Port = port; Url = url; EmptyPassword = emptypw; DefaultAlgorithm = algo; DefaultVariant = variant; }
}
public PoolInfo (string url, int port, string emptypw = "", string algo = "cn", int variant = -1) { Port = port; Url = url; EmptyPassword = emptypw; DefaultAlgorithm = algo; DefaultVariant = variant; }
}
public class PoolList {
public class PoolList {
private Dictionary<string, PoolInfo> pools;
private PoolList () { }
private Dictionary<string, PoolInfo> pools;
private PoolList () { }
public string JsonPools { private set; get; }
public string JsonPools { private set; get; }
public bool TryGetPool (string pool, out PoolInfo info) {
return pools.TryGetValue (pool, out info);
}
public bool TryGetPool (string pool, out PoolInfo info) {
return pools.TryGetValue (pool, out info);
}
public int Count { get { return pools.Count; } }
public int Count { get { return pools.Count; } }
public static PoolList LoadFromFile (string filename) {
PoolList pl = new PoolList ();
pl.pools = new Dictionary<string, PoolInfo> ();
public static PoolList LoadFromFile (string filename) {
PoolList pl = new PoolList ();
pl.pools = new Dictionary<string, PoolInfo> ();
string json = File.ReadAllText (filename);
string json = File.ReadAllText (filename);
JsonData data = json.FromJson<JsonData> ();
JsonData data = json.FromJson<JsonData> ();
foreach (string pool in data.Keys) {
foreach (string pool in data.Keys) {
JsonData jinfo = data[pool] as JsonData;
PoolInfo pi = new PoolInfo ();
JsonData jinfo = data[pool] as JsonData;
PoolInfo pi = new PoolInfo ();
if (!(jinfo.ContainsKey ("url") && jinfo.ContainsKey ("port") &&
jinfo.ContainsKey ("emptypassword") && jinfo.ContainsKey ("algorithm") &&
jinfo.ContainsKey ("variant")))
throw new Exception ("Invalid entry.");
if (!(jinfo.ContainsKey ("url") && jinfo.ContainsKey ("port") &&
jinfo.ContainsKey ("emptypassword") && jinfo.ContainsKey ("algorithm") &&
jinfo.ContainsKey ("variant")))
throw new Exception ("Invalid entry.");
pi.Url = jinfo["url"].GetString ();
pi.EmptyPassword = jinfo["emptypassword"].GetString ();
pi.DefaultAlgorithm = jinfo["algorithm"].GetString ();
pi.DefaultVariant = int.Parse (jinfo["variant"].GetString ());
pi.Port = int.Parse (jinfo["port"].GetString ());
pi.Url = jinfo["url"].GetString ();
pi.EmptyPassword = jinfo["emptypassword"].GetString ();
pi.DefaultAlgorithm = jinfo["algorithm"].GetString ();
pi.DefaultVariant = int.Parse (jinfo["variant"].GetString ());
pi.Port = int.Parse (jinfo["port"].GetString ());
pl.pools.Add (pool, pi);
pl.pools.Add (pool, pi);
}
}
int counter = 0;
int counter = 0;
pl.JsonPools = "{\"identifier\":\"" + "poolinfo";
pl.JsonPools = "{\"identifier\":\"" + "poolinfo";
foreach (string pool in pl.pools.Keys) {
counter++;
pl.JsonPools += "\",\"pool" + counter.ToString () + "\":\"" + pool;
}
foreach (string pool in pl.pools.Keys) {
counter++;
pl.JsonPools += "\",\"pool" + counter.ToString () + "\":\"" + pool;
}
pl.JsonPools += "\"}\n";
pl.JsonPools += "\"}\n";
return pl;
}
return pl;
}
}
}
}

+ 14
- 14
server/Server/Program.cs View File

@ -96,7 +96,7 @@ namespace Server {
private static bool libHashAvailable = false;
private static PoolList PoolList;
private static PoolList PoolList;
// time to connect to a pool in seconds
private const int GraceConnectionTime = 16;
@ -507,15 +507,15 @@ namespace Server {
Console.WriteLine ();
});
try {
PoolList = PoolList.LoadFromFile ("pools.json");
}
catch(Exception ex) {
CConsole.ColorAlert (() => Console.WriteLine("Could not load pool list from pools.json: {0}", ex.Message));
return;
}
try {
PoolList = PoolList.LoadFromFile ("pools.json");
}
catch(Exception ex) {
CConsole.ColorAlert (() => Console.WriteLine("Could not load pool list from pools.json: {0}", ex.Message));
return;
}
CConsole.ColorInfo (() => Console.WriteLine ("Loaded {0} pools from pools.json.", PoolList.Count));
CConsole.ColorInfo (() => Console.WriteLine ("Loaded {0} pools from pools.json.", PoolList.Count));
Exception exception = null;
@ -533,7 +533,7 @@ namespace Server {
// cn_v2
libHashAvailable &= CheckLibHash("5468697320697320612074657374205468697320697320612074657374205468697320697320612074657374",
"353fdc068fd47b03c04b9431e005e00b68c2168a3cc7335c8b9b308156591a4f",
"353fdc068fd47b03c04b9431e005e00b68c2168a3cc7335c8b9b308156591a4f",
0, 2, out exception);
// cn_lite
@ -548,7 +548,7 @@ namespace Server {
// cn_lite_v2 (speculative)
libHashAvailable &= CheckLibHash("5468697320697320612074657374205468697320697320612074657374205468697320697320612074657374",
"49c95241af3bd74e78f473936ac36214bbc386a36869f9406b5da16aa0ee4b06",
"49c95241af3bd74e78f473936ac36214bbc386a36869f9406b5da16aa0ee4b06",
1, 2, out exception);
if (!libHashAvailable) CConsole.ColorWarning (() =>
@ -790,7 +790,7 @@ namespace Server {