189 lines
4.4 KiB
C#
189 lines
4.4 KiB
C#
using System;
|
|
using System.Net.Sockets;
|
|
using System.Threading;
|
|
using System.IO;
|
|
using sharp.jsonrpc.net;
|
|
using Newtonsoft.Json.Linq;
|
|
using sharp.cryptonote;
|
|
|
|
namespace SharpMining
|
|
{
|
|
public class StratumConnection : JSONClient
|
|
{
|
|
delegate void threadsyncdelegate();
|
|
|
|
StratumListener listener;
|
|
Thread thread;
|
|
bool shouldExit;
|
|
|
|
public Guid UID { get; } = Guid.NewGuid();
|
|
|
|
public CryptoNoteAddress Wallet { get; set; }
|
|
public string WorkerID { get; set; }
|
|
public int FixedDiff { get; set; }
|
|
public string Agent { get; set; }
|
|
|
|
public MiningPool Pool { get; private set; }
|
|
|
|
public MiningJob CurrentJob { get; private set; }
|
|
public MiningJob LastJob { get; private set; }
|
|
|
|
public StratumConnection(StratumListener listener,Socket socket)
|
|
:base(socket)
|
|
{
|
|
this.listener = listener;
|
|
this.thread = new Thread(()=>run());
|
|
this.thread.Start();
|
|
}
|
|
|
|
public new void Close(){
|
|
Monitor.Enter(this);
|
|
if (shouldExit){
|
|
return;
|
|
}
|
|
shouldExit = true;
|
|
Monitor.Wait(this);
|
|
|
|
base.Close();
|
|
|
|
Monitor.Exit(this);
|
|
}
|
|
|
|
private void run(){
|
|
|
|
while (!ShouldExit){
|
|
try
|
|
{
|
|
JToken token = readJSON();
|
|
|
|
if (token["method"] != null)
|
|
{
|
|
methodCalled(token["method"].ToObject<string>(), token["id"].ToObject<UInt64>(), token["params"]);
|
|
}
|
|
} catch (IOException ioe){
|
|
Close();
|
|
} catch (Exception e){
|
|
Console.WriteLine("StratumConnection: [{0}] Exception: {1}",UID.ToString(),e.ToString());
|
|
}
|
|
|
|
}
|
|
|
|
if (Pool != null){
|
|
Pool.WorkManager.OnNewBlockAvailable -= WorkManager_OnNewBlockAvailable;
|
|
}
|
|
|
|
Monitor.Enter(this);
|
|
Monitor.PulseAll(this);
|
|
Monitor.Exit(this);
|
|
}
|
|
|
|
private bool ShouldExit { get { Monitor.Enter(this); bool se = this.shouldExit; Monitor.Exit(this); return se; } }
|
|
|
|
private new void writeJSON(JToken token){
|
|
Monitor.Enter(this);
|
|
base.writeJSON(token);
|
|
Monitor.Exit(this);
|
|
}
|
|
|
|
private void methodCalled(string method,UInt64 id,JToken args){
|
|
switch (method){
|
|
case "login":
|
|
rpcLogin(id,args);
|
|
break;
|
|
case "submit":
|
|
rpcSubmit(id, args);
|
|
break;
|
|
default:
|
|
writeJSONRPC(id, null, new JValue(String.Format("Method not implemented: {0}", method)));
|
|
break;
|
|
}
|
|
}
|
|
|
|
private string splitSuffix(char deli, ref string line)
|
|
{
|
|
return splitSuffix(deli, ref line, "");
|
|
}
|
|
private string splitSuffix(char deli, ref string line, string def){
|
|
string result = def;
|
|
int i = line.IndexOf(deli);
|
|
if (i >= 0){
|
|
result = line.Substring(i + 1);
|
|
line = line.Substring(0, i);
|
|
};
|
|
return result;
|
|
}
|
|
|
|
private void rpcLogin(UInt64 id,JToken args){
|
|
string username, passwd;
|
|
|
|
Agent = args["agent"].ToObject<string>();
|
|
|
|
username = args["login"].ToObject<string>();
|
|
passwd = args["pass"].ToObject<string>();
|
|
|
|
try {
|
|
FixedDiff = int.Parse(splitSuffix('@', ref username,"0"));
|
|
WorkerID = splitSuffix('.', ref username);
|
|
Wallet = new CryptoNoteAddress(username);
|
|
|
|
Pool = this.listener.getAssociatedPool(Wallet.CryptoNoteCoin);
|
|
|
|
if (Pool == null){
|
|
throw new Exception("No Pool for that coin available!");
|
|
}
|
|
|
|
MiningJob job = Pool.WorkManager.createJob();
|
|
assignJob(job, false);
|
|
|
|
Pool.WorkManager.OnNewBlockAvailable += WorkManager_OnNewBlockAvailable;
|
|
|
|
} catch (Exception e){
|
|
writeJSONRPC(id,null,new JValue(String.Format("An Exception occured ({0}: {1})",e.ToString(),e.Message)));
|
|
Close();
|
|
}
|
|
|
|
Console.WriteLine("Miner connected: [{3}] Wallet: {0} WorkerID: {1} FixedDiff: {2}", Wallet, WorkerID, FixedDiff, UID.ToString());
|
|
|
|
|
|
writeJSONRPC(id, new JObject(
|
|
new JProperty("id", "555"),
|
|
new JProperty("job", CurrentJob.toJSON(100))
|
|
), null);
|
|
}
|
|
|
|
private void rpcSubmit(UInt64 id,JToken args)
|
|
{
|
|
}
|
|
|
|
private bool assignJob(MiningJob job,bool transmit){
|
|
LastJob = CurrentJob;
|
|
CurrentJob = job;
|
|
|
|
if (transmit){
|
|
transmitCurrentJob();
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
public void transmitCurrentJob(){
|
|
writeJSON(new JObject(
|
|
new JProperty("jsonrpc", "2.0"),
|
|
new JProperty("method","job"),
|
|
new JProperty("params", CurrentJob.toJSON())
|
|
));
|
|
}
|
|
|
|
void WorkManager_OnNewBlockAvailable(WorkManager workmanager)
|
|
{
|
|
assignJob( this.Pool.WorkManager.createJob(), true );
|
|
}
|
|
|
|
public override string ToString()
|
|
{
|
|
return string.Format("[StratumConnection: [{4}] MinerWallet={0}, WorkerID={1}, FixedDiff={2}, Agent={3}]", Wallet, WorkerID, FixedDiff, Agent, UID.ToString());
|
|
}
|
|
|
|
}
|
|
}
|