diff --git a/components/stratum/include/stratum_api.h b/components/stratum/include/stratum_api.h index 7ce73ff2..86c3d5b5 100644 --- a/components/stratum/include/stratum_api.h +++ b/components/stratum/include/stratum_api.h @@ -75,12 +75,12 @@ void STRATUM_V1_free_mining_notify(mining_notify *params); int STRATUM_V1_authenticate(int socket, const char *username, const char *pass); -void STRATUM_V1_configure_version_rolling(int socket, uint32_t * version_mask); +int STRATUM_V1_configure_version_rolling(int socket, uint32_t * version_mask); int STRATUM_V1_suggest_difficulty(int socket, uint32_t difficulty); -void STRATUM_V1_submit_share(int socket, const char *username, const char *jobid, - const char *extranonce_2, const uint32_t ntime, const uint32_t nonce, - const uint32_t version); +int STRATUM_V1_submit_share(int socket, const char *username, const char *jobid, + const char *extranonce_2, const uint32_t ntime, const uint32_t nonce, + const uint32_t version); #endif // STRATUM_API_H \ No newline at end of file diff --git a/components/stratum/stratum_api.c b/components/stratum/stratum_api.c index 673564aa..81e734df 100644 --- a/components/stratum/stratum_api.c +++ b/components/stratum/stratum_api.c @@ -90,7 +90,7 @@ char * STRATUM_V1_receive_jsonrpc_line(int sockfd) memset(recv_buffer, 0, BUFFER_SIZE); nbytes = recv(sockfd, recv_buffer, BUFFER_SIZE - 1, 0); if (nbytes == -1) { - ESP_LOGI(TAG, "Error: recv"); + ESP_LOGI(TAG, "Error: recv (errno %d: %s)", errno, strerror(errno)); if (json_rpc_buffer) { free(json_rpc_buffer); json_rpc_buffer=0; @@ -314,9 +314,8 @@ int STRATUM_V1_subscribe(int socket, char * model) const char *version = app_desc->version; sprintf(subscribe_msg, "{\"id\": %d, \"method\": \"mining.subscribe\", \"params\": [\"bitaxe/%s/%s\"]}\n", send_uid++, model, version); debug_stratum_tx(subscribe_msg); - write(socket, subscribe_msg, strlen(subscribe_msg)); - return 1; + return write(socket, subscribe_msg, strlen(subscribe_msg)); } int STRATUM_V1_suggest_difficulty(int socket, uint32_t difficulty) @@ -324,9 +323,8 @@ int STRATUM_V1_suggest_difficulty(int socket, uint32_t difficulty) char difficulty_msg[BUFFER_SIZE]; sprintf(difficulty_msg, "{\"id\": %d, \"method\": \"mining.suggest_difficulty\", \"params\": [%ld]}\n", send_uid++, difficulty); debug_stratum_tx(difficulty_msg); - write(socket, difficulty_msg, strlen(difficulty_msg)); - return 1; + return write(socket, difficulty_msg, strlen(difficulty_msg)); } int STRATUM_V1_authenticate(int socket, const char * username, const char * pass) @@ -336,9 +334,7 @@ int STRATUM_V1_authenticate(int socket, const char * username, const char * pass pass); debug_stratum_tx(authorize_msg); - write(socket, authorize_msg, strlen(authorize_msg)); - - return 1; + return write(socket, authorize_msg, strlen(authorize_msg)); } /// @param socket Socket to write to @@ -347,7 +343,7 @@ int STRATUM_V1_authenticate(int socket, const char * username, const char * pass /// @param ntime The hex-encoded time value use in the block header. /// @param extranonce_2 The hex-encoded value of extra nonce 2. /// @param nonce The hex-encoded nonce value to use in the block header. -void STRATUM_V1_submit_share(int socket, const char * username, const char * jobid, const char * extranonce_2, const uint32_t ntime, +int STRATUM_V1_submit_share(int socket, const char * username, const char * jobid, const char * extranonce_2, const uint32_t ntime, const uint32_t nonce, const uint32_t version) { char submit_msg[BUFFER_SIZE]; @@ -355,10 +351,11 @@ void STRATUM_V1_submit_share(int socket, const char * username, const char * job "{\"id\": %d, \"method\": \"mining.submit\", \"params\": [\"%s\", \"%s\", \"%s\", \"%08lx\", \"%08lx\", \"%08lx\"]}\n", send_uid++, username, jobid, extranonce_2, ntime, nonce, version); debug_stratum_tx(submit_msg); - write(socket, submit_msg, strlen(submit_msg)); + + return write(socket, submit_msg, strlen(submit_msg)); } -void STRATUM_V1_configure_version_rolling(int socket, uint32_t * version_mask) +int STRATUM_V1_configure_version_rolling(int socket, uint32_t * version_mask) { char configure_msg[BUFFER_SIZE * 2]; sprintf(configure_msg, @@ -366,9 +363,8 @@ void STRATUM_V1_configure_version_rolling(int socket, uint32_t * version_mask) "\"ffffffff\"}]}\n", send_uid++); debug_stratum_tx(configure_msg); - write(socket, configure_msg, strlen(configure_msg)); - return; + return write(socket, configure_msg, strlen(configure_msg)); } static void debug_stratum_tx(const char * msg) diff --git a/main/Kconfig.projbuild b/main/Kconfig.projbuild index fbcfcc0f..0df8a289 100755 --- a/main/Kconfig.projbuild +++ b/main/Kconfig.projbuild @@ -29,6 +29,19 @@ menu "Stratum Configuration" help The stratum server port to connect to. + config FALLBACK_STRATUM_URL + string "Fallback Stratum Address" + default "solo.ckpool.org" + help + The example will connect to this Stratum pool address if the primary fails. + + config FALLBACK_STRATUM_PORT + int "Fallback Stratum Port" + range 0 65535 + default 3333 + help + The stratum server port to connect to if the primary fails. + config STRATUM_USER string "Stratum username" default "1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa.bitaxe" diff --git a/main/global_state.h b/main/global_state.h index 280e665b..e2b7e51c 100644 --- a/main/global_state.h +++ b/main/global_state.h @@ -68,9 +68,11 @@ typedef struct char ssid[32]; char wifi_status[20]; char * pool_url; + char * fallback_pool_url; uint16_t pool_port; + uint16_t fallback_pool_port; + bool is_using_fallback; uint16_t overheat_mode; - uint32_t lastClockSync; } SystemModule; diff --git a/main/http_server/axe-os/src/app/services/system.service.ts b/main/http_server/axe-os/src/app/services/system.service.ts index 3bf9f7dd..1a70a679 100644 --- a/main/http_server/axe-os/src/app/services/system.service.ts +++ b/main/http_server/axe-os/src/app/services/system.service.ts @@ -44,6 +44,8 @@ export class SystemService { ASICModel: eASICModel.BM1366, stratumURL: "public-pool.io", stratumPort: 21496, + fallbackStratumURL: "test.public-pool.io", + fallbackStratumPort: 21497, stratumUser: "bc1q99n3pu025yyu0jlywpmwzalyhm36tg5u37w20d.bitaxe-U1", frequency: 485, version: "2.0", diff --git a/main/http_server/axe-os/src/models/ISystemInfo.ts b/main/http_server/axe-os/src/models/ISystemInfo.ts index dde736c8..2121c691 100644 --- a/main/http_server/axe-os/src/models/ISystemInfo.ts +++ b/main/http_server/axe-os/src/models/ISystemInfo.ts @@ -25,6 +25,8 @@ export interface ISystemInfo { ASICModel: eASICModel, stratumURL: string, stratumPort: number, + fallbackStratumURL: string, + fallbackStratumPort: number, stratumUser: string, frequency: number, version: string, diff --git a/main/http_server/http_server.c b/main/http_server/http_server.c index 5f7ee49d..40231fae 100644 --- a/main/http_server/http_server.c +++ b/main/http_server/http_server.c @@ -272,6 +272,9 @@ static esp_err_t PATCH_update_settings(httpd_req_t * req) if ((item = cJSON_GetObjectItem(root, "stratumURL")) != NULL) { nvs_config_set_string(NVS_CONFIG_STRATUM_URL, item->valuestring); } + if ((item = cJSON_GetObjectItem(root, "fallbackStratumURL")) != NULL) { + nvs_config_set_string(NVS_CONFIG_FALLBACK_STRATUM_URL, item->valuestring); + } if ((item = cJSON_GetObjectItem(root, "stratumUser")) != NULL) { nvs_config_set_string(NVS_CONFIG_STRATUM_USER, item->valuestring); } @@ -281,6 +284,9 @@ static esp_err_t PATCH_update_settings(httpd_req_t * req) if ((item = cJSON_GetObjectItem(root, "stratumPort")) != NULL) { nvs_config_set_u16(NVS_CONFIG_STRATUM_PORT, item->valueint); } + if ((item = cJSON_GetObjectItem(root, "fallbackStratumPort")) != NULL) { + nvs_config_set_u16(NVS_CONFIG_FALLBACK_STRATUM_PORT, item->valueint); + } if ((item = cJSON_GetObjectItem(root, "ssid")) != NULL) { nvs_config_set_string(NVS_CONFIG_WIFI_SSID, item->valuestring); } @@ -368,6 +374,7 @@ static esp_err_t GET_system_info(httpd_req_t * req) char * ssid = nvs_config_get_string(NVS_CONFIG_WIFI_SSID, CONFIG_ESP_WIFI_SSID); char * hostname = nvs_config_get_string(NVS_CONFIG_HOSTNAME, CONFIG_LWIP_LOCAL_HOSTNAME); char * stratumURL = nvs_config_get_string(NVS_CONFIG_STRATUM_URL, CONFIG_STRATUM_URL); + char * fallbackStratumURL = nvs_config_get_string(NVS_CONFIG_FALLBACK_STRATUM_URL, CONFIG_FALLBACK_STRATUM_URL); char * stratumUser = nvs_config_get_string(NVS_CONFIG_STRATUM_USER, CONFIG_STRATUM_USER); char * board_version = nvs_config_get_string(NVS_CONFIG_BOARD_VERSION, "unknown"); @@ -414,7 +421,9 @@ static esp_err_t GET_system_info(httpd_req_t * req) cJSON_AddNumberToObject(root, "smallCoreCount", small_core_count); cJSON_AddStringToObject(root, "ASICModel", GLOBAL_STATE->asic_model_str); cJSON_AddStringToObject(root, "stratumURL", stratumURL); + cJSON_AddStringToObject(root, "fallbackStratumURL", fallbackStratumURL); cJSON_AddNumberToObject(root, "stratumPort", nvs_config_get_u16(NVS_CONFIG_STRATUM_PORT, CONFIG_STRATUM_PORT)); + cJSON_AddNumberToObject(root, "fallbackStratumPort", nvs_config_get_u16(NVS_CONFIG_FALLBACK_STRATUM_PORT, CONFIG_FALLBACK_STRATUM_PORT)); cJSON_AddStringToObject(root, "stratumUser", stratumUser); cJSON_AddStringToObject(root, "version", esp_app_get_description()->version); diff --git a/main/nvs_config.h b/main/nvs_config.h index c5f318d5..692bad5d 100644 --- a/main/nvs_config.h +++ b/main/nvs_config.h @@ -10,6 +10,8 @@ #define NVS_CONFIG_HOSTNAME "hostname" #define NVS_CONFIG_STRATUM_URL "stratumurl" #define NVS_CONFIG_STRATUM_PORT "stratumport" +#define NVS_CONFIG_FALLBACK_STRATUM_URL "fbstratumurl" +#define NVS_CONFIG_FALLBACK_STRATUM_PORT "fbstratumport" #define NVS_CONFIG_STRATUM_USER "stratumuser" #define NVS_CONFIG_STRATUM_PASS "stratumpass" #define NVS_CONFIG_ASIC_FREQ "asicfrequency" diff --git a/main/system.c b/main/system.c index a05f5447..6a7585e0 100644 --- a/main/system.c +++ b/main/system.c @@ -76,9 +76,14 @@ static void _init_system(GlobalState * GLOBAL_STATE) // set the pool url module->pool_url = nvs_config_get_string(NVS_CONFIG_STRATUM_URL, CONFIG_STRATUM_URL); + module->fallback_pool_url = nvs_config_get_string(NVS_CONFIG_FALLBACK_STRATUM_URL, CONFIG_FALLBACK_STRATUM_URL); //set the pool port module->pool_port = nvs_config_get_u16(NVS_CONFIG_STRATUM_PORT, CONFIG_STRATUM_PORT); + module->fallback_pool_port = nvs_config_get_u16(NVS_CONFIG_FALLBACK_STRATUM_PORT, CONFIG_FALLBACK_STRATUM_PORT); + + // set fallback to false. + module->is_using_fallback = false; // Initialize overheat_mode module->overheat_mode = nvs_config_get_u16(NVS_CONFIG_OVERHEAT_MODE, 0); diff --git a/main/tasks/asic_result_task.c b/main/tasks/asic_result_task.c index 6b9313ae..99dfd508 100644 --- a/main/tasks/asic_result_task.c +++ b/main/tasks/asic_result_task.c @@ -6,6 +6,8 @@ #include "esp_log.h" #include "nvs_config.h" #include "utils.h" +#include "stratum_task.h" +#include static const char *TAG = "asic_result"; @@ -17,7 +19,6 @@ void ASIC_result_task(void *pvParameters) while (1) { - task_result *asic_result = (*GLOBAL_STATE->ASIC_functions.receive_result_fn)(GLOBAL_STATE); if (asic_result == NULL) @@ -44,8 +45,7 @@ void ASIC_result_task(void *pvParameters) if (nonce_diff > GLOBAL_STATE->ASIC_TASK_MODULE.active_jobs[job_id]->pool_diff) { - - STRATUM_V1_submit_share( + int ret = STRATUM_V1_submit_share( GLOBAL_STATE->sock, user, GLOBAL_STATE->ASIC_TASK_MODULE.active_jobs[job_id]->jobid, @@ -54,6 +54,10 @@ void ASIC_result_task(void *pvParameters) asic_result->nonce, asic_result->rolled_version ^ GLOBAL_STATE->ASIC_TASK_MODULE.active_jobs[job_id]->version); + if (ret < 0) { + ESP_LOGI(TAG, "Unable to write share to socket. Closing connection. Ret: %d (errno %d: %s)", ret, errno, strerror(errno)); + stratum_close_connection(GLOBAL_STATE); + } } SYSTEM_notify_found_nonce(GLOBAL_STATE, nonce_diff, job_id); diff --git a/main/tasks/stratum_task.c b/main/tasks/stratum_task.c index d96305a8..c950622f 100644 --- a/main/tasks/stratum_task.c +++ b/main/tasks/stratum_task.c @@ -5,6 +5,7 @@ #include "system.h" #include "global_state.h" #include "lwip/dns.h" +#include #include "nvs_config.h" #include "stratum_task.h" #include "work_queue.h" @@ -15,31 +16,22 @@ #define PORT CONFIG_STRATUM_PORT #define STRATUM_URL CONFIG_STRATUM_URL +#define FALLBACK_PORT CONFIG_FALLBACK_STRATUM_PORT +#define FALLBACK_STRATUM_URL CONFIG_FALLBACK_STRATUM_URL + #define STRATUM_PW CONFIG_STRATUM_PW #define STRATUM_DIFFICULTY CONFIG_STRATUM_DIFFICULTY -#define BASE_DELAY_MS 5000 -#define MAX_RETRY_ATTEMPTS 5 +#define MAX_RETRY_ATTEMPTS 3 +#define MAX_CRITICAL_RETRY_ATTEMPTS 5 + static const char * TAG = "stratum_task"; -static ip_addr_t ip_Addr; -static bool bDNSFound = false; -static bool bDNSInvalid = false; static StratumApiV1Message stratum_api_v1_message = {}; - static SystemTaskModule SYSTEM_TASK_MODULE = {.stratum_difficulty = 8192}; -void dns_found_cb(const char * name, const ip_addr_t * ipaddr, void * callback_arg) -{ - if (ipaddr != NULL){ - ip4_addr_t ip4addr = ipaddr->u_addr.ip4; // Obtener la estructura ip4_addr_t - ESP_LOGI(TAG, "IP found : %d.%d.%d.%d", ip4_addr1(&ip4addr), ip4_addr2(&ip4addr), ip4_addr3(&ip4addr), ip4_addr4(&ip4addr)); - ip_Addr = *ipaddr; - } else { - bDNSInvalid = true; - } - bDNSFound = true; -} +static const char * primary_stratum_url; +static uint16_t primary_stratum_port; bool is_wifi_connected() { wifi_ap_record_t ap_info; @@ -63,176 +55,251 @@ void cleanQueue(GlobalState * GLOBAL_STATE) { pthread_mutex_unlock(&GLOBAL_STATE->valid_jobs_lock); } +void stratum_close_connection(GlobalState * GLOBAL_STATE) +{ + if (GLOBAL_STATE->sock < 0) { + ESP_LOGE(TAG, "Socket already shutdown, not shutting down again.."); + return; + } + + ESP_LOGE(TAG, "Shutting down socket and restarting..."); + shutdown(GLOBAL_STATE->sock, SHUT_RDWR); + close(GLOBAL_STATE->sock); + cleanQueue(GLOBAL_STATE); + vTaskDelay(1000 / portTICK_PERIOD_MS); +} + +void stratum_primary_heartbeat(void * pvParameters) +{ + GlobalState * GLOBAL_STATE = (GlobalState *) pvParameters; + + ESP_LOGI(TAG, "Starting heartbeat thread for primary endpoint: %s", primary_stratum_url); + vTaskDelay(10000 / portTICK_PERIOD_MS); + + int addr_family = AF_INET; + int ip_protocol = IPPROTO_IP; + + while (1) + { + if (GLOBAL_STATE->SYSTEM_MODULE.is_using_fallback == false) { + vTaskDelay(10000 / portTICK_PERIOD_MS); + continue; + } + + char host_ip[INET_ADDRSTRLEN]; + ESP_LOGD(TAG, "Running Heartbeat on: %s!", primary_stratum_url); + + if (!is_wifi_connected()) { + ESP_LOGD(TAG, "Heartbeat. Failed WiFi check!"); + vTaskDelay(10000 / portTICK_PERIOD_MS); + continue; + } + + struct hostent *primary_dns_addr = gethostbyname(primary_stratum_url); + if (primary_dns_addr == NULL) { + ESP_LOGD(TAG, "Heartbeat. Failed DNS check for: %s!", primary_stratum_url); + vTaskDelay(60000 / portTICK_PERIOD_MS); + continue; + } + inet_ntop(AF_INET, (void *)primary_dns_addr->h_addr_list[0], host_ip, sizeof(host_ip)); + + struct sockaddr_in dest_addr; + dest_addr.sin_addr.s_addr = inet_addr(host_ip); + dest_addr.sin_family = AF_INET; + dest_addr.sin_port = htons(primary_stratum_port); + + int sock = socket(addr_family, SOCK_STREAM, ip_protocol); + if (sock < 0) { + ESP_LOGD(TAG, "Heartbeat. Failed socket create check!"); + vTaskDelay(60000 / portTICK_PERIOD_MS); + close(sock); + continue; + } + + int err = connect(sock, (struct sockaddr *)&dest_addr, sizeof(struct sockaddr_in6)); + if (err != 0) + { + ESP_LOGD(TAG, "Heartbeat. Failed connect check: %s:%d (errno %d: %s)", host_ip, primary_stratum_port, errno, strerror(errno)); + close(sock); + vTaskDelay(60000 / portTICK_PERIOD_MS); + continue; + } + shutdown(sock, SHUT_RDWR); + close(sock); + + if (GLOBAL_STATE->SYSTEM_MODULE.is_using_fallback) { + ESP_LOGI(TAG, "Heartbeat successful and in fallback mode. Switching back to primary."); + GLOBAL_STATE->SYSTEM_MODULE.is_using_fallback = false; + stratum_close_connection(GLOBAL_STATE); + vTaskDelay(60000 / portTICK_PERIOD_MS); + continue; + } + vTaskDelay(60000 / portTICK_PERIOD_MS); + } +} + void stratum_task(void * pvParameters) { GlobalState * GLOBAL_STATE = (GlobalState *) pvParameters; + primary_stratum_url = GLOBAL_STATE->SYSTEM_MODULE.pool_url; + primary_stratum_port = GLOBAL_STATE->SYSTEM_MODULE.pool_port; + char * stratum_url = GLOBAL_STATE->SYSTEM_MODULE.pool_url; + uint16_t port = GLOBAL_STATE->SYSTEM_MODULE.pool_port; + STRATUM_V1_initialize_buffer(); char host_ip[20]; - int addr_family = 0; - int ip_protocol = 0; - int retry_attempts = 0; - int delay_ms = BASE_DELAY_MS; - + int addr_family = AF_INET; + int ip_protocol = IPPROTO_IP; + int retry_attempts = 0; + int retry_critical_attempts = 0; + struct timeval timeout = {}; + timeout.tv_sec = 5; + timeout.tv_usec = 0; - char *stratum_url = GLOBAL_STATE->SYSTEM_MODULE.pool_url; - uint16_t port = GLOBAL_STATE->SYSTEM_MODULE.pool_port; + xTaskCreate(stratum_primary_heartbeat, "stratum primary heartbeat", 4096, pvParameters, 1, NULL); + ESP_LOGI(TAG, "Trying to get IP for URL: %s", stratum_url); while (1) { - //clear flags used by the dns callback, dns_found_cb() - bDNSFound = false; - bDNSInvalid = false; - - // check to see if the STRATUM_URL is an ip address already - if (inet_pton(AF_INET, stratum_url, &ip_Addr) == 1) { - bDNSFound = true; + if (!is_wifi_connected()) { + ESP_LOGI(TAG, "WiFi disconnected, attempting to reconnect..."); + esp_wifi_connect(); + vTaskDelay(10000 / portTICK_PERIOD_MS); + continue; } - else + + if (retry_attempts >= MAX_RETRY_ATTEMPTS) { - ESP_LOGI(TAG, "Get IP for URL: %s", stratum_url); - dns_gethostbyname(stratum_url, &ip_Addr, dns_found_cb, NULL); - while (!bDNSFound); - - if (bDNSInvalid) { - ESP_LOGE(TAG, "DNS lookup failed for URL: %s", stratum_url); - //set ip_Addr to 0.0.0.0 so that connect() will fail - IP_ADDR4(&ip_Addr, 0, 0, 0, 0); - } + GLOBAL_STATE->SYSTEM_MODULE.is_using_fallback = !GLOBAL_STATE->SYSTEM_MODULE.is_using_fallback; + ESP_LOGI(TAG, "Switching target due to too many failures (retries: %d)...", retry_attempts); + retry_attempts = 0; + } + stratum_url = GLOBAL_STATE->SYSTEM_MODULE.is_using_fallback ? GLOBAL_STATE->SYSTEM_MODULE.fallback_pool_url : GLOBAL_STATE->SYSTEM_MODULE.pool_url; + port = GLOBAL_STATE->SYSTEM_MODULE.is_using_fallback ? GLOBAL_STATE->SYSTEM_MODULE.fallback_pool_port : GLOBAL_STATE->SYSTEM_MODULE.pool_port; + + struct hostent *dns_addr = gethostbyname(stratum_url); + if (dns_addr == NULL) { + retry_attempts++; + vTaskDelay(1000 / portTICK_PERIOD_MS); + continue; } + inet_ntop(AF_INET, (void *)dns_addr->h_addr_list[0], host_ip, sizeof(host_ip)); - // make IP address string from ip_Addr - snprintf(host_ip, sizeof(host_ip), "%d.%d.%d.%d", ip4_addr1(&ip_Addr.u_addr.ip4), ip4_addr2(&ip_Addr.u_addr.ip4), - ip4_addr3(&ip_Addr.u_addr.ip4), ip4_addr4(&ip_Addr.u_addr.ip4)); ESP_LOGI(TAG, "Connecting to: stratum+tcp://%s:%d (%s)", stratum_url, port, host_ip); - while (1) { - if (!is_wifi_connected()) { - ESP_LOGI(TAG, "WiFi disconnected, attempting to reconnect..."); - esp_wifi_connect(); - vTaskDelay(10000 / portTICK_PERIOD_MS); - //delay_ms *= 2; // Increase delay exponentially - continue; - } + struct sockaddr_in dest_addr; + dest_addr.sin_addr.s_addr = inet_addr(host_ip); + dest_addr.sin_family = AF_INET; + dest_addr.sin_port = htons(port); - struct sockaddr_in dest_addr; - dest_addr.sin_addr.s_addr = inet_addr(host_ip); - dest_addr.sin_family = AF_INET; - dest_addr.sin_port = htons(port); - addr_family = AF_INET; - ip_protocol = IPPROTO_IP; - - GLOBAL_STATE->sock = socket(addr_family, SOCK_STREAM, ip_protocol); - if (GLOBAL_STATE->sock < 0) { - ESP_LOGE(TAG, "Unable to create socket: errno %d", errno); - if (++retry_attempts > MAX_RETRY_ATTEMPTS) { - ESP_LOGE(TAG, "Max retry attempts reached, restarting..."); - esp_restart(); - } - vTaskDelay(5000 / portTICK_PERIOD_MS); - continue; - } - ESP_LOGI(TAG, "Socket created, connecting to %s:%d", host_ip, port); - retry_attempts = 0; - int err = connect(GLOBAL_STATE->sock, (struct sockaddr *)&dest_addr, sizeof(struct sockaddr_in6)); - if (err != 0) - { - ESP_LOGE(TAG, "Socket unable to connect to %s:%d (errno %d)", stratum_url, port, errno); - // close the socket - shutdown(GLOBAL_STATE->sock, SHUT_RDWR); - close(GLOBAL_STATE->sock); - // instead of restarting, retry this every 5 seconds - vTaskDelay(5000 / portTICK_PERIOD_MS); - continue; + GLOBAL_STATE->sock = socket(addr_family, SOCK_STREAM, ip_protocol); + if (GLOBAL_STATE->sock < 0) { + ESP_LOGE(TAG, "Unable to create socket: errno %d", errno); + if (++retry_critical_attempts > MAX_CRITICAL_RETRY_ATTEMPTS) { + ESP_LOGE(TAG, "Max retry attempts reached, restarting..."); + esp_restart(); } + vTaskDelay(5000 / portTICK_PERIOD_MS); + continue; + } + retry_critical_attempts = 0; + + ESP_LOGI(TAG, "Socket created, connecting to %s:%d", host_ip, port); + int err = connect(GLOBAL_STATE->sock, (struct sockaddr *)&dest_addr, sizeof(struct sockaddr_in6)); + if (err != 0) + { + retry_attempts++; + ESP_LOGE(TAG, "Socket unable to connect to %s:%d (errno %d: %s)", stratum_url, port, errno, strerror(errno)); + // close the socket + shutdown(GLOBAL_STATE->sock, SHUT_RDWR); + close(GLOBAL_STATE->sock); + // instead of restarting, retry this every 5 seconds + vTaskDelay(5000 / portTICK_PERIOD_MS); + continue; + } + retry_attempts = 0; + + if (setsockopt(GLOBAL_STATE->sock, SOL_SOCKET, SO_SNDTIMEO, &timeout, sizeof(timeout)) != 0) { + ESP_LOGE(TAG, "Fail to setsockopt SO_SNDTIMEO"); + } - STRATUM_V1_reset_uid(); - cleanQueue(GLOBAL_STATE); + STRATUM_V1_reset_uid(); + cleanQueue(GLOBAL_STATE); - ///// Start Stratum Action - // mining.subscribe - ID: 1 - STRATUM_V1_subscribe(GLOBAL_STATE->sock, GLOBAL_STATE->asic_model_str); + ///// Start Stratum Action + // mining.subscribe - ID: 1 + STRATUM_V1_subscribe(GLOBAL_STATE->sock, GLOBAL_STATE->asic_model_str); - // mining.configure - ID: 2 - STRATUM_V1_configure_version_rolling(GLOBAL_STATE->sock, &GLOBAL_STATE->version_mask); + // mining.configure - ID: 2 + STRATUM_V1_configure_version_rolling(GLOBAL_STATE->sock, &GLOBAL_STATE->version_mask); - //mining.suggest_difficulty - ID: 3 - STRATUM_V1_suggest_difficulty(GLOBAL_STATE->sock, STRATUM_DIFFICULTY); + //mining.suggest_difficulty - ID: 3 + STRATUM_V1_suggest_difficulty(GLOBAL_STATE->sock, STRATUM_DIFFICULTY); - char * username = nvs_config_get_string(NVS_CONFIG_STRATUM_USER, STRATUM_USER); - char * password = nvs_config_get_string(NVS_CONFIG_STRATUM_PASS, STRATUM_PW); + char * username = nvs_config_get_string(NVS_CONFIG_STRATUM_USER, STRATUM_USER); + char * password = nvs_config_get_string(NVS_CONFIG_STRATUM_PASS, STRATUM_PW); - //mining.authorize - ID: 4 - STRATUM_V1_authenticate(GLOBAL_STATE->sock, username, password); - free(password); - free(username); + //mining.authorize - ID: 4 + STRATUM_V1_authenticate(GLOBAL_STATE->sock, username, password); + free(password); + free(username); - while (1) { - char * line = STRATUM_V1_receive_jsonrpc_line(GLOBAL_STATE->sock); - if (!line) { - ESP_LOGE(TAG, "Failed to receive JSON-RPC line, reconnecting..."); - shutdown(GLOBAL_STATE->sock, SHUT_RDWR); - close(GLOBAL_STATE->sock); - vTaskDelay(1000 / portTICK_PERIOD_MS); // Delay before attempting to reconnect - break; + while (1) { + char * line = STRATUM_V1_receive_jsonrpc_line(GLOBAL_STATE->sock); + if (!line) { + ESP_LOGE(TAG, "Failed to receive JSON-RPC line, reconnecting..."); + stratum_close_connection(GLOBAL_STATE); + break; + } + ESP_LOGI(TAG, "rx: %s", line); // debug incoming stratum messages + STRATUM_V1_parse(&stratum_api_v1_message, line); + free(line); + + if (stratum_api_v1_message.method == MINING_NOTIFY) { + SYSTEM_notify_new_ntime(GLOBAL_STATE, stratum_api_v1_message.mining_notification->ntime); + if (stratum_api_v1_message.should_abandon_work && + (GLOBAL_STATE->stratum_queue.count > 0 || GLOBAL_STATE->ASIC_jobs_queue.count > 0)) { + cleanQueue(GLOBAL_STATE); } - ESP_LOGI(TAG, "rx: %s", line); // debug incoming stratum messages - STRATUM_V1_parse(&stratum_api_v1_message, line); - free(line); - - if (stratum_api_v1_message.method == MINING_NOTIFY) { - SYSTEM_notify_new_ntime(GLOBAL_STATE, stratum_api_v1_message.mining_notification->ntime); - if (stratum_api_v1_message.should_abandon_work && - (GLOBAL_STATE->stratum_queue.count > 0 || GLOBAL_STATE->ASIC_jobs_queue.count > 0)) { - cleanQueue(GLOBAL_STATE); - } - if (GLOBAL_STATE->stratum_queue.count == QUEUE_SIZE) { - mining_notify * next_notify_json_str = (mining_notify *) queue_dequeue(&GLOBAL_STATE->stratum_queue); - STRATUM_V1_free_mining_notify(next_notify_json_str); - } - - stratum_api_v1_message.mining_notification->difficulty = SYSTEM_TASK_MODULE.stratum_difficulty; - queue_enqueue(&GLOBAL_STATE->stratum_queue, stratum_api_v1_message.mining_notification); - } else if (stratum_api_v1_message.method == MINING_SET_DIFFICULTY) { - if (stratum_api_v1_message.new_difficulty != SYSTEM_TASK_MODULE.stratum_difficulty) { - SYSTEM_TASK_MODULE.stratum_difficulty = stratum_api_v1_message.new_difficulty; - ESP_LOGI(TAG, "Set stratum difficulty: %ld", SYSTEM_TASK_MODULE.stratum_difficulty); - } - } else if (stratum_api_v1_message.method == MINING_SET_VERSION_MASK || - stratum_api_v1_message.method == STRATUM_RESULT_VERSION_MASK) { - // 1fffe000 - ESP_LOGI(TAG, "Set version mask: %08lx", stratum_api_v1_message.version_mask); - GLOBAL_STATE->version_mask = stratum_api_v1_message.version_mask; - } else if (stratum_api_v1_message.method == STRATUM_RESULT_SUBSCRIBE) { - GLOBAL_STATE->extranonce_str = stratum_api_v1_message.extranonce_str; - GLOBAL_STATE->extranonce_2_len = stratum_api_v1_message.extranonce_2_len; - } else if (stratum_api_v1_message.method == CLIENT_RECONNECT) { - ESP_LOGE(TAG, "Pool requested client reconnect..."); - shutdown(GLOBAL_STATE->sock, SHUT_RDWR); - close(GLOBAL_STATE->sock); - vTaskDelay(1000 / portTICK_PERIOD_MS); // Delay before attempting to reconnect - break; - } else if (stratum_api_v1_message.method == STRATUM_RESULT) { - if (stratum_api_v1_message.response_success) { - ESP_LOGI(TAG, "message result accepted"); - SYSTEM_notify_accepted_share(GLOBAL_STATE); - } else { - ESP_LOGW(TAG, "message result rejected"); - SYSTEM_notify_rejected_share(GLOBAL_STATE); - } - } else if (stratum_api_v1_message.method == STRATUM_RESULT_SETUP) { - if (stratum_api_v1_message.response_success) { - ESP_LOGI(TAG, "setup message accepted"); - } else { - ESP_LOGE(TAG, "setup message rejected"); - } + if (GLOBAL_STATE->stratum_queue.count == QUEUE_SIZE) { + mining_notify * next_notify_json_str = (mining_notify *) queue_dequeue(&GLOBAL_STATE->stratum_queue); + STRATUM_V1_free_mining_notify(next_notify_json_str); } - } - if (GLOBAL_STATE->sock != -1) { - ESP_LOGE(TAG, "Shutting down socket and restarting..."); - shutdown(GLOBAL_STATE->sock, 0); - close(GLOBAL_STATE->sock); + stratum_api_v1_message.mining_notification->difficulty = SYSTEM_TASK_MODULE.stratum_difficulty; + queue_enqueue(&GLOBAL_STATE->stratum_queue, stratum_api_v1_message.mining_notification); + } else if (stratum_api_v1_message.method == MINING_SET_DIFFICULTY) { + if (stratum_api_v1_message.new_difficulty != SYSTEM_TASK_MODULE.stratum_difficulty) { + SYSTEM_TASK_MODULE.stratum_difficulty = stratum_api_v1_message.new_difficulty; + ESP_LOGI(TAG, "Set stratum difficulty: %ld", SYSTEM_TASK_MODULE.stratum_difficulty); + } + } else if (stratum_api_v1_message.method == MINING_SET_VERSION_MASK || + stratum_api_v1_message.method == STRATUM_RESULT_VERSION_MASK) { + // 1fffe000 + ESP_LOGI(TAG, "Set version mask: %08lx", stratum_api_v1_message.version_mask); + GLOBAL_STATE->version_mask = stratum_api_v1_message.version_mask; + } else if (stratum_api_v1_message.method == STRATUM_RESULT_SUBSCRIBE) { + GLOBAL_STATE->extranonce_str = stratum_api_v1_message.extranonce_str; + GLOBAL_STATE->extranonce_2_len = stratum_api_v1_message.extranonce_2_len; + } else if (stratum_api_v1_message.method == CLIENT_RECONNECT) { + ESP_LOGE(TAG, "Pool requested client reconnect..."); + stratum_close_connection(GLOBAL_STATE); + break; + } else if (stratum_api_v1_message.method == STRATUM_RESULT) { + if (stratum_api_v1_message.response_success) { + ESP_LOGI(TAG, "message result accepted"); + SYSTEM_notify_accepted_share(GLOBAL_STATE); + } else { + ESP_LOGW(TAG, "message result rejected"); + SYSTEM_notify_rejected_share(GLOBAL_STATE); + } + } else if (stratum_api_v1_message.method == STRATUM_RESULT_SETUP) { + if (stratum_api_v1_message.response_success) { + ESP_LOGI(TAG, "setup message accepted"); + } else { + ESP_LOGE(TAG, "setup message rejected"); + } } } } diff --git a/main/tasks/stratum_task.h b/main/tasks/stratum_task.h index 82fce62b..0827f589 100644 --- a/main/tasks/stratum_task.h +++ b/main/tasks/stratum_task.h @@ -7,5 +7,6 @@ typedef struct } SystemTaskModule; void stratum_task(void *pvParameters); +void stratum_close_connection(GlobalState * GLOBAL_STATE); #endif \ No newline at end of file