gupaxx/src/xmrig.rs

423 lines
16 KiB
Rust
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// Gupax - GUI Uniting P2Pool And XMRig
//
// Copyright (c) 2022-2023 hinto-janai
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
use crate::{
Regexes,
constants::*,
disk::*,
Process,
PubXmrigApi,
macros::*,
};
use egui::{
TextEdit,SelectableLabel,ComboBox,Label,Button,RichText,Slider,Checkbox,
TextStyle::*,
};
use std::{
sync::{Arc,Mutex},
};
use regex::Regex;
use log::*;
use crate::regex::{
REGEXES,
};
impl crate::disk::Xmrig {
#[inline(always)]
pub fn show(&mut self, pool_vec: &mut Vec<(String, Pool)>, process: &Arc<Mutex<Process>>, api: &Arc<Mutex<PubXmrigApi>>, buffer: &mut String, width: f32, height: f32, _ctx: &egui::Context, ui: &mut egui::Ui) {
let text_edit = height / 25.0;
//---------------------------------------------------------------------------------------------------- [Simple] Console
debug!("XMRig Tab | Rendering [Console]");
ui.group(|ui| {
if self.simple {
let height = height / 1.5;
let width = width - SPACE;
egui::Frame::none().fill(DARK_GRAY).show(ui, |ui| {
ui.style_mut().override_text_style = Some(Name("MonospaceSmall".into()));
egui::ScrollArea::vertical().stick_to_bottom(true).max_width(width).max_height(height).auto_shrink([false; 2]).show_viewport(ui, |ui, _| {
ui.add_sized([width, height], TextEdit::multiline(&mut lock!(api).output.as_str()));
});
});
//---------------------------------------------------------------------------------------------------- [Advanced] Console
} else {
let height = height / 2.8;
let width = width - SPACE;
egui::Frame::none().fill(DARK_GRAY).show(ui, |ui| {
ui.style_mut().override_text_style = Some(Name("MonospaceSmall".into()));
egui::ScrollArea::vertical().stick_to_bottom(true).max_width(width).max_height(height).auto_shrink([false; 2]).show_viewport(ui, |ui, _| {
ui.add_sized([width, height], TextEdit::multiline(&mut lock!(api).output.as_str()));
});
});
ui.separator();
let response = ui.add_sized([width, text_edit], TextEdit::hint_text(TextEdit::singleline(buffer), r#"Commands: [h]ashrate, [p]ause, [r]esume, re[s]ults, [c]onnection"#)).on_hover_text(XMRIG_INPUT);
// If the user pressed enter, dump buffer contents into the process STDIN
if response.lost_focus() && ui.input().key_pressed(egui::Key::Enter) {
response.request_focus(); // Get focus back
let buffer = std::mem::take(buffer); // Take buffer
let mut process = lock!(process); // Lock
if process.is_alive() { process.input.push(buffer); } // Push only if alive
}
}
});
//---------------------------------------------------------------------------------------------------- Arguments
if !self.simple {
debug!("XMRig Tab | Rendering [Arguments]");
ui.group(|ui| { ui.horizontal(|ui| {
let width = (width/10.0) - SPACE;
ui.add_sized([width, text_edit], Label::new("Command arguments:"));
ui.add_sized([ui.available_width(), text_edit], TextEdit::hint_text(TextEdit::singleline(&mut self.arguments), r#"--url <...> --user <...> --config <...>"#)).on_hover_text(XMRIG_ARGUMENTS);
self.arguments.truncate(1024);
})});
ui.set_enabled(self.arguments.is_empty());
//---------------------------------------------------------------------------------------------------- Address
debug!("XMRig Tab | Rendering [Address]");
ui.group(|ui| {
let width = width - SPACE;
ui.spacing_mut().text_edit_width = (width)-(SPACE*3.0);
let text;
let color;
let len = format!("{:02}", self.address.len());
if self.address.is_empty() {
text = format!("Monero Address [{}/95] ", len);
color = LIGHT_GRAY;
} else if Regexes::addr_ok(&self.address) {
text = format!("Monero Address [{}/95] ✔", len);
color = GREEN;
} else {
text = format!("Monero Address [{}/95] ❌", len);
color = RED;
}
ui.add_sized([width, text_edit], Label::new(RichText::new(text).color(color)));
ui.add_sized([width, text_edit], TextEdit::hint_text(TextEdit::singleline(&mut self.address), "4...")).on_hover_text(XMRIG_ADDRESS);
self.address.truncate(95);
});
}
//---------------------------------------------------------------------------------------------------- Threads
if self.simple { ui.add_space(SPACE); }
debug!("XMRig Tab | Rendering [Threads]");
ui.vertical(|ui| {
let width = width/10.0;
ui.spacing_mut().icon_width = width / 25.0;
ui.horizontal(|ui| {
ui.spacing_mut().slider_width = width*8.35;
ui.add_sized([width, text_edit], Label::new(format!("Threads [1-{}]:", self.max_threads)));
ui.add_sized([width, text_edit], Slider::new(&mut self.current_threads, 1..=self.max_threads)).on_hover_text(XMRIG_THREADS);
});
#[cfg(not(target_os = "linux"))] // Pause on active isn't supported on Linux
ui.horizontal(|ui| {
ui.spacing_mut().slider_width = width*7.7;
ui.add_sized([width, text_edit], Label::new(format!("Pause on active [0-255]:")));
ui.add_sized([width, text_edit], Slider::new(&mut self.pause, 0..=255)).on_hover_text(format!("{} [{}] seconds.", XMRIG_PAUSE, self.pause));
});
});
//---------------------------------------------------------------------------------------------------- Simple
if self.simple {
// ui.group(|ui|
// });
} else {
debug!("XMRig Tab | Rendering [Pool List] elements");
let width = ui.available_width() - 10.0;
let mut incorrect_input = false; // This will disable [Add/Delete] on bad input
// [Pool IP/Port]
ui.horizontal(|ui| {
ui.group(|ui| {
let width = width/10.0;
ui.vertical(|ui| {
ui.spacing_mut().text_edit_width = width*3.32;
ui.horizontal(|ui| {
let text;
let color;
let len = format!("{:02}", self.name.len());
if self.name.is_empty() {
text = format!("Name [ {}/30 ]", len);
color = LIGHT_GRAY;
incorrect_input = true;
} else if REGEXES.name.is_match(&self.name) {
text = format!("Name [ {}/30 ]✔", len);
color = GREEN;
} else {
text = format!("Name [ {}/30 ]❌", len);
color = RED;
incorrect_input = true;
}
ui.add_sized([width, text_edit], Label::new(RichText::new(text).color(color)));
ui.text_edit_singleline(&mut self.name).on_hover_text(XMRIG_NAME);
self.name.truncate(30);
});
ui.horizontal(|ui| {
let text;
let color;
let len = format!("{:03}", self.ip.len());
if self.ip.is_empty() {
text = format!(" IP [{}/255]", len);
color = LIGHT_GRAY;
incorrect_input = true;
} else if self.ip == "localhost" || REGEXES.ipv4.is_match(&self.ip) || REGEXES.domain.is_match(&self.ip) {
text = format!(" IP [{}/255]✔", len);
color = GREEN;
} else {
text = format!(" IP [{}/255]❌", len);
color = RED;
incorrect_input = true;
}
ui.add_sized([width, text_edit], Label::new(RichText::new(text).color(color)));
ui.text_edit_singleline(&mut self.ip).on_hover_text(XMRIG_IP);
self.ip.truncate(255);
});
ui.horizontal(|ui| {
let text;
let color;
let len = self.port.len();
if self.port.is_empty() {
text = format!("Port [ {}/5 ]", len);
color = LIGHT_GRAY;
incorrect_input = true;
} else if REGEXES.port.is_match(&self.port) {
text = format!("Port [ {}/5 ]✔", len);
color = GREEN;
} else {
text = format!("Port [ {}/5 ]❌", len);
color = RED;
incorrect_input = true;
}
ui.add_sized([width, text_edit], Label::new(RichText::new(text).color(color)));
ui.text_edit_singleline(&mut self.port).on_hover_text(XMRIG_PORT);
self.port.truncate(5);
});
ui.horizontal(|ui| {
let text;
let color;
let len = format!("{:02}", self.rig.len());
if self.rig.is_empty() {
text = format!(" Rig [ {}/30 ]", len);
color = LIGHT_GRAY;
} else if REGEXES.name.is_match(&self.rig) {
text = format!(" Rig [ {}/30 ]✔", len);
color = GREEN;
} else {
text = format!(" Rig [ {}/30 ]❌", len);
color = RED;
incorrect_input = true;
}
ui.add_sized([width, text_edit], Label::new(RichText::new(text).color(color)));
ui.text_edit_singleline(&mut self.rig).on_hover_text(XMRIG_RIG);
self.rig.truncate(30);
});
});
ui.vertical(|ui| {
let width = ui.available_width();
ui.add_space(1.0);
// [Manual node selection]
ui.spacing_mut().slider_width = width - 8.0;
ui.spacing_mut().icon_width = width / 25.0;
// [Node List]
debug!("XMRig Tab | Rendering [Node List] ComboBox");
let text = RichText::new(format!("{}. {}", self.selected_index+1, self.selected_name));
ComboBox::from_id_source("manual_pool").selected_text(text).show_ui(ui, |ui| {
let mut n = 0;
for (name, pool) in pool_vec.iter() {
let text = format!("{}. {}\n IP: {}\n Port: {}\n Rig: {}", n+1, name, pool.ip, pool.port, pool.rig);
if ui.add(SelectableLabel::new(self.selected_name == *name, text)).clicked() {
self.selected_index = n;
let pool = pool.clone();
self.selected_name = name.clone();
self.selected_rig = pool.rig.clone();
self.selected_ip = pool.ip.clone();
self.selected_port = pool.port.clone();
self.name = name.clone();
self.rig = pool.rig;
self.ip = pool.ip;
self.port = pool.port;
}
n += 1;
}
});
// [Add/Save]
let pool_vec_len = pool_vec.len();
let mut exists = false;
let mut save_diff = true;
let mut existing_index = 0;
for (name, pool) in pool_vec.iter() {
if *name == self.name {
exists = true;
if self.rig == pool.rig && self.ip == pool.ip && self.port == pool.port {
save_diff = false;
}
break
}
existing_index += 1;
}
ui.horizontal(|ui| {
let text = if exists { LIST_SAVE } else { LIST_ADD };
let text = format!("{}\n Currently selected pool: {}. {}\n Current amount of pools: {}/1000", text, self.selected_index+1, self.selected_name, pool_vec_len);
// If the pool already exists, show [Save] and mutate the already existing pool
if exists {
ui.set_enabled(!incorrect_input && save_diff);
if ui.add_sized([width, text_edit], Button::new("Save")).on_hover_text(text).clicked() {
let pool = Pool {
rig: self.rig.clone(),
ip: self.ip.clone(),
port: self.port.clone(),
};
pool_vec[existing_index].1 = pool;
self.selected_name = self.name.clone();
self.selected_rig = self.rig.clone();
self.selected_ip = self.ip.clone();
self.selected_port = self.port.clone();
info!("Node | S | [index: {}, name: \"{}\", ip: \"{}\", port: {}, rig: \"{}\"]", existing_index+1, self.name, self.ip, self.port, self.rig);
}
// Else, add to the list
} else {
ui.set_enabled(!incorrect_input && pool_vec_len < 1000);
if ui.add_sized([width, text_edit], Button::new("Add")).on_hover_text(text).clicked() {
let pool = Pool {
rig: self.rig.clone(),
ip: self.ip.clone(),
port: self.port.clone(),
};
pool_vec.push((self.name.clone(), pool));
self.selected_index = pool_vec_len;
self.selected_name = self.name.clone();
self.selected_rig = self.rig.clone();
self.selected_ip = self.ip.clone();
self.selected_port = self.port.clone();
info!("Node | A | [index: {}, name: \"{}\", ip: \"{}\", port: {}, rig: \"{}\"]", pool_vec_len, self.name, self.ip, self.port, self.rig);
}
}
});
// [Delete]
ui.horizontal(|ui| {
ui.set_enabled(pool_vec_len > 1);
let text = format!("{}\n Currently selected pool: {}. {}\n Current amount of pools: {}/1000", LIST_DELETE, self.selected_index+1, self.selected_name, pool_vec_len);
if ui.add_sized([width, text_edit], Button::new("Delete")).on_hover_text(text).clicked() {
let new_name;
let new_pool;
match self.selected_index {
0 => {
new_name = pool_vec[1].0.clone();
new_pool = pool_vec[1].1.clone();
pool_vec.remove(0);
}
_ => {
pool_vec.remove(self.selected_index);
self.selected_index -= 1;
new_name = pool_vec[self.selected_index].0.clone();
new_pool = pool_vec[self.selected_index].1.clone();
}
};
self.selected_name = new_name.clone();
self.selected_rig = new_pool.rig.clone();
self.selected_ip = new_pool.ip.clone();
self.selected_port = new_pool.port.clone();
self.name = new_name;
self.rig = new_pool.rig;
self.ip = new_pool.ip;
self.port = new_pool.port;
info!("Node | D | [index: {}, name: \"{}\", ip: \"{}\", port: {}, rig\"{}\"]", self.selected_index, self.selected_name, self.selected_ip, self.selected_port, self.selected_rig);
}
});
ui.horizontal(|ui| {
ui.set_enabled(!self.name.is_empty() || !self.ip.is_empty() || !self.port.is_empty());
if ui.add_sized([width, text_edit], Button::new("Clear")).on_hover_text(LIST_CLEAR).clicked() {
self.name.clear();
self.rig.clear();
self.ip.clear();
self.port.clear();
}
});
});
});
});
ui.add_space(5.0);
debug!("XMRig Tab | Rendering [API] TextEdits");
// [HTTP API IP/Port]
ui.group(|ui| { ui.horizontal(|ui| {
ui.vertical(|ui| {
let width = width/10.0;
ui.spacing_mut().text_edit_width = width*2.39;
// HTTP API
ui.horizontal(|ui| {
let text;
let color;
let len = format!("{:03}", self.api_ip.len());
if self.api_ip.is_empty() {
text = format!("HTTP API IP [{}/255]", len);
color = LIGHT_GRAY;
incorrect_input = true;
} else if self.api_ip == "localhost" || REGEXES.ipv4.is_match(&self.api_ip) || REGEXES.domain.is_match(&self.api_ip) {
text = format!("HTTP API IP [{}/255]✔", len);
color = GREEN;
} else {
text = format!("HTTP API IP [{}/255]❌", len);
color = RED;
incorrect_input = true;
}
ui.add_sized([width, text_edit], Label::new(RichText::new(text).color(color)));
ui.text_edit_singleline(&mut self.api_ip).on_hover_text(XMRIG_API_IP);
self.api_ip.truncate(255);
});
ui.horizontal(|ui| {
let text;
let color;
let len = self.api_port.len();
if self.api_port.is_empty() {
text = format!("HTTP API Port [ {}/5 ]", len);
color = LIGHT_GRAY;
incorrect_input = true;
} else if REGEXES.port.is_match(&self.api_port) {
text = format!("HTTP API Port [ {}/5 ]✔", len);
color = GREEN;
} else {
text = format!("HTTP API Port [ {}/5 ]❌", len);
color = RED;
incorrect_input = true;
}
ui.add_sized([width, text_edit], Label::new(RichText::new(text).color(color)));
ui.text_edit_singleline(&mut self.api_port).on_hover_text(XMRIG_API_PORT);
self.api_port.truncate(5);
});
});
ui.separator();
debug!("XMRig Tab | Rendering [TLS/Keepalive] buttons");
ui.vertical(|ui| {
// TLS/Keepalive
ui.horizontal(|ui| {
let width = (ui.available_width()/2.0)-11.0;
let height = text_edit*2.0;
// let mut style = (*ctx.style()).clone();
// style.spacing.icon_width_inner = width / 8.0;
// style.spacing.icon_width = width / 6.0;
// style.spacing.icon_spacing = 20.0;
// ctx.set_style(style);
ui.add_sized([width, height], Checkbox::new(&mut self.tls, "TLS Connection")).on_hover_text(XMRIG_TLS);
ui.separator();
ui.add_sized([width, height], Checkbox::new(&mut self.keepalive, "Keepalive")).on_hover_text(XMRIG_KEEPALIVE);
});
});
});
});
}
}
}