diff --git a/sgminer.c b/sgminer.c index 40c02da4..bdd95844 100644 --- a/sgminer.c +++ b/sgminer.c @@ -5572,6 +5572,18 @@ static bool parse_stratum_response(struct pool *pool, char *s) goto out; } + json_t *status = json_object_get(res_val, "status"); + + if (status && pool->algorithm.type == ALGO_CRYPTONIGHT) { + const char *s = json_string_value(status); + + if (s && !strcmp(s, "KEEPALIVED")) { + applog(LOG_NOTICE, "Keepalived from %s received", get_pool_name(pool)); + ret = true; + goto out; + } + } + id = json_integer_value(id_val); mutex_lock(&sshare_lock); @@ -5595,22 +5607,25 @@ static bool parse_stratum_response(struct pool *pool, char *s) //for cryptonight, the result contains the "status" object which should = "OK" on accept if (pool->algorithm.type == ALGO_CRYPTONIGHT) { json_t *res_id, *res_job; - + //check if the result contains an id... if so then we need to process as first job, not share response if ((res_id = json_object_get(res_val, "id"))) { cg_wlock(&pool->data_lock); strcpy(pool->XMRAuthID, json_string_value(res_id)); cg_wunlock(&pool->data_lock); - + //get the job object and send to parse notify if ((res_job = json_object_get(res_val, "job"))) { ret = parse_notify_cn(pool, res_job); } - + goto out; } - - if (json_is_null(err_val) && !strcmp(json_string_value(json_object_get(res_val, "status")), "OK")) { + + json_t *status = json_object_get(res_val, "status"); + const char *s = json_string_value(status); + + if (json_is_null(err_val) && status && !strcmp(s, "OK")) { success = true; } else { @@ -5810,6 +5825,7 @@ static void *stratum_rthread(void *userdata) while (42) { struct timeval timeout; + struct timeval timeout_keep_alive; int sel_ret; fd_set rd; char *s; @@ -5843,6 +5859,21 @@ static void *stratum_rthread(void *userdata) FD_SET(pool->sock, &rd); timeout.tv_sec = 90; timeout.tv_usec = 0; + + + if (pool->algorithm.type == ALGO_CRYPTONIGHT) { + timeout_keep_alive.tv_sec = 60; + timeout_keep_alive.tv_usec = 0; + + if (!sock_full(pool) && (sel_ret = select(pool->sock + 1, &rd, NULL, NULL, &timeout_keep_alive)) < 1) { + if (sock_keepalived(pool, pool->XMRAuthID, swork_id++)) { + applog(LOG_NOTICE, "Stratum %s keepalived sent, id: %d", get_pool_name(pool), swork_id - 1); + } + + FD_ZERO(&rd); + FD_SET(pool->sock, &rd); + } + } /* The protocol specifies that notify messages should be sent * every minute so if we fail to receive any for 90 seconds we @@ -5853,6 +5884,7 @@ static void *stratum_rthread(void *userdata) s = NULL; } else s = recv_line(pool); + if (!s) { applog(LOG_NOTICE, "Stratum connection to %s interrupted", get_pool_name(pool)); pool->getfail_occasions++; diff --git a/util.c b/util.c index 26747b86..70cb1902 100644 --- a/util.c +++ b/util.c @@ -1359,6 +1359,31 @@ bool sock_full(struct pool *pool) return (socket_full(pool, 0)); } +bool sock_keepalived(struct pool *pool, const char *rpc2_id, int work_id) +{ + json_t *val = NULL, *res_val, *err_val; + char *s = NULL, *sret; + json_error_t err; + bool ret = false; + + if (pool->algorithm.type == ALGO_CRYPTONIGHT) { + s = malloc(300 + strlen(rpc2_id) + 10); + snprintf(s, 128, "{\"method\": \"keepalived\", \"params\": {\"id\": \"%s\"}, \"id\":%d}", rpc2_id, work_id); + } else { + return true; + } + + if (stratum_send(pool, s, strlen(s))) { + ret = true; + } + + if (s) { + free(s); + } + + return ret; +} + static void clear_sockbuf(struct pool *pool) { strcpy(pool->sockbuf, ""); diff --git a/util.h b/util.h index 2904af2b..140c0859 100644 --- a/util.h +++ b/util.h @@ -133,6 +133,7 @@ int ms_tdiff(struct timeval *end, struct timeval *start); double tdiff(struct timeval *end, struct timeval *start); bool stratum_send(struct pool *pool, char *s, ssize_t len); bool sock_full(struct pool *pool); +bool sock_keepalived(struct pool *pool, const char *rpc2_id, int work_id); char *recv_line(struct pool *pool); bool parse_method(struct pool *pool, char *s); bool parse_notify_cn(struct pool *pool, json_t *val);