@@ -85,6 +85,13 @@ char * STRATUM_V1_receive_jsonrpc_line(int sockfd)
8585 json_rpc_buffer = 0 ;
8686 }
8787 return 0 ;
88+ } else if (nbytes == 0 ) {
89+ // Pool closed the connection gracefully
90+ ESP_LOGI (TAG , "Connection closed by remote host" );
91+ if (json_rpc_buffer ) {
92+ memset (json_rpc_buffer , 0 , json_rpc_buffer_size );
93+ }
94+ return 0 ;
8895 }
8996
9097 realloc_json_buffer (nbytes );
@@ -96,14 +103,23 @@ char * STRATUM_V1_receive_jsonrpc_line(int sockfd)
96103 line = strdup (tok );
97104 int len = strlen (line );
98105 if (buflen > len + 1 )
99- memmove (json_rpc_buffer , json_rpc_buffer + len + 1 , buflen - len + 1 );
106+ {
107+ size_t remaining = buflen - len - 1 ;
108+ memmove (json_rpc_buffer , json_rpc_buffer + len + 1 , remaining );
109+ json_rpc_buffer [remaining ] = '\0' ;
110+ }
100111 else
101112 strcpy (json_rpc_buffer , "" );
102113 return line ;
103114}
104115
105116void STRATUM_V1_parse (StratumApiV1Message * message , const char * stratum_json )
106117{
118+ if (message -> error_str ) {
119+ free (message -> error_str );
120+ message -> error_str = NULL ;
121+ }
122+
107123 cJSON * json = cJSON_Parse (stratum_json );
108124
109125 cJSON * id_json = cJSON_GetObjectItem (json , "id" );
@@ -145,21 +161,22 @@ void STRATUM_V1_parse(StratumApiV1Message * message, const char * stratum_json)
145161 // if it's an error, then it's a fail
146162 } else if (!cJSON_IsNull (error_json )) {
147163 message -> response_success = false;
148- message -> error_str = strdup ("unknown" );
149164 if (parsed_id < 5 ) {
150165 result = STRATUM_RESULT_SETUP ;
151166 } else {
152167 result = STRATUM_RESULT ;
153168 }
169+ const char * err_str = "unknown" ;
154170 if (cJSON_IsArray (error_json )) {
155171 int len = cJSON_GetArraySize (error_json );
156172 if (len >= 2 ) {
157173 cJSON * error_msg = cJSON_GetArrayItem (error_json , 1 );
158174 if (cJSON_IsString (error_msg )) {
159- message -> error_str = strdup ( cJSON_GetStringValue (error_msg ) );
175+ err_str = cJSON_GetStringValue (error_msg );
160176 }
161177 }
162178 }
179+ message -> error_str = strdup (err_str );
163180
164181 // if the result is a boolean, then parse it
165182 } else if (cJSON_IsBool (result_json )) {
@@ -172,10 +189,11 @@ void STRATUM_V1_parse(StratumApiV1Message * message, const char * stratum_json)
172189 message -> response_success = true;
173190 } else {
174191 message -> response_success = false;
175- message -> error_str = strdup ( "unknown" ) ;
192+ const char * reject_str = "unknown" ;
176193 if (cJSON_IsString (reject_reason_json )) {
177- message -> error_str = strdup (cJSON_GetStringValue (reject_reason_json ));
178- }
194+ reject_str = cJSON_GetStringValue (reject_reason_json );
195+ }
196+ message -> error_str = strdup (reject_str );
179197 }
180198
181199 //if the id is STRATUM_ID_SUBSCRIBE parse it
@@ -224,45 +242,70 @@ void STRATUM_V1_parse(StratumApiV1Message * message, const char * stratum_json)
224242
225243 if (message -> method == MINING_NOTIFY ) {
226244
227- mining_notify * new_work = malloc (sizeof (mining_notify ));
228- // new_work->difficulty = difficulty;
229245 cJSON * params = cJSON_GetObjectItem (json , "params" );
230- new_work -> job_id = strdup (cJSON_GetArrayItem (params , 0 )-> valuestring );
231- new_work -> prev_block_hash = strdup (cJSON_GetArrayItem (params , 1 )-> valuestring );
232- new_work -> coinbase_1 = strdup (cJSON_GetArrayItem (params , 2 )-> valuestring );
233- new_work -> coinbase_2 = strdup (cJSON_GetArrayItem (params , 3 )-> valuestring );
246+ cJSON * p0 = params ? cJSON_GetArrayItem (params , 0 ) : NULL ;
247+ cJSON * p1 = params ? cJSON_GetArrayItem (params , 1 ) : NULL ;
248+ cJSON * p2 = params ? cJSON_GetArrayItem (params , 2 ) : NULL ;
249+ cJSON * p3 = params ? cJSON_GetArrayItem (params , 3 ) : NULL ;
250+ cJSON * p4 = params ? cJSON_GetArrayItem (params , 4 ) : NULL ;
251+ cJSON * p5 = params ? cJSON_GetArrayItem (params , 5 ) : NULL ;
252+ cJSON * p6 = params ? cJSON_GetArrayItem (params , 6 ) : NULL ;
253+ cJSON * p7 = params ? cJSON_GetArrayItem (params , 7 ) : NULL ;
254+ if (!p0 || !p1 || !p2 || !p3 || !p4 || !p5 || !p6 || !p7 ) {
255+ ESP_LOGE (TAG , "MINING_NOTIFY: malformed params: %s" , stratum_json );
256+ goto done ;
257+ }
258+
259+ mining_notify * new_work = malloc (sizeof (mining_notify ));
260+ new_work -> job_id = strdup (p0 -> valuestring );
261+ new_work -> prev_block_hash = strdup (p1 -> valuestring );
262+ new_work -> coinbase_1 = strdup (p2 -> valuestring );
263+ new_work -> coinbase_2 = strdup (p3 -> valuestring );
234264
235- cJSON * merkle_branch = cJSON_GetArrayItem (params , 4 );
236- new_work -> n_merkle_branches = cJSON_GetArraySize (merkle_branch );
265+ new_work -> n_merkle_branches = cJSON_GetArraySize (p4 );
237266 if (new_work -> n_merkle_branches > MAX_MERKLE_BRANCHES ) {
238- printf ("Too many Merkle branches.\n" );
239- abort ();
267+ ESP_LOGE (TAG , "Too many Merkle branches: %d" , new_work -> n_merkle_branches );
268+ free (new_work -> job_id );
269+ free (new_work -> prev_block_hash );
270+ free (new_work -> coinbase_1 );
271+ free (new_work -> coinbase_2 );
272+ free (new_work );
273+ goto done ;
240274 }
241275 new_work -> merkle_branches = malloc (HASH_SIZE * new_work -> n_merkle_branches );
242276 for (size_t i = 0 ; i < new_work -> n_merkle_branches ; i ++ ) {
243- hex2bin (cJSON_GetArrayItem (merkle_branch , i )-> valuestring , new_work -> merkle_branches + HASH_SIZE * i , HASH_SIZE );
277+ cJSON * branch = cJSON_GetArrayItem (p4 , i );
278+ if (branch ) {
279+ hex2bin (branch -> valuestring , new_work -> merkle_branches + HASH_SIZE * i , HASH_SIZE );
280+ }
244281 }
245282
246- new_work -> version = strtoul (cJSON_GetArrayItem ( params , 5 ) -> valuestring , NULL , 16 );
247- new_work -> target = strtoul (cJSON_GetArrayItem ( params , 6 ) -> valuestring , NULL , 16 );
248- new_work -> ntime = strtoul (cJSON_GetArrayItem ( params , 7 ) -> valuestring , NULL , 16 );
283+ new_work -> version = strtoul (p5 -> valuestring , NULL , 16 );
284+ new_work -> target = strtoul (p6 -> valuestring , NULL , 16 );
285+ new_work -> ntime = strtoul (p7 -> valuestring , NULL , 16 );
249286
250287 message -> mining_notification = new_work ;
251288
252- // params can be varible length
289+ // params can be variable length
253290 int paramsLength = cJSON_GetArraySize (params );
254- int value = cJSON_IsTrue ( cJSON_GetArrayItem (params , paramsLength - 1 ) );
255- message -> should_abandon_work = value ;
291+ cJSON * lastParam = cJSON_GetArrayItem (params , paramsLength - 1 );
292+ message -> should_abandon_work = lastParam ? cJSON_IsTrue ( lastParam ) : false ;
256293 } else if (message -> method == MINING_SET_DIFFICULTY ) {
257294 cJSON * params = cJSON_GetObjectItem (json , "params" );
258- uint32_t difficulty = cJSON_GetArrayItem (params , 0 )-> valueint ;
259-
260- message -> new_difficulty = difficulty ;
295+ cJSON * p0 = params ? cJSON_GetArrayItem (params , 0 ) : NULL ;
296+ if (p0 == NULL ) {
297+ ESP_LOGE (TAG , "MINING_SET_DIFFICULTY: missing params" );
298+ goto done ;
299+ }
300+ message -> new_difficulty = p0 -> valueint ;
261301 } else if (message -> method == MINING_SET_VERSION_MASK ) {
262-
263302 cJSON * params = cJSON_GetObjectItem (json , "params" );
264- uint32_t version_mask = strtoul (cJSON_GetArrayItem (params , 0 )-> valuestring , NULL , 16 );
265- message -> version_mask = version_mask ;
303+ cJSON * p0 = params ? cJSON_GetArrayItem (params , 0 ) : NULL ;
304+ if (p0 == NULL ) {
305+ ESP_LOGE (TAG , "MINING_SET_VERSION_MASK: missing params" );
306+ goto done ;
307+ }
308+ message -> version_mask = strtoul (p0 -> valuestring , NULL , 16 );
266309 }
267310 done :
268311 cJSON_Delete (json );
@@ -317,7 +360,7 @@ int STRATUM_V1_subscribe(int socket, int send_uid, char * model)
317360 char subscribe_msg [BUFFER_SIZE ];
318361 const esp_app_desc_t * app_desc = esp_app_get_description ();
319362 const char * version = app_desc -> version ;
320- sprintf (subscribe_msg , "{\"id\": %d, \"method\": \"mining.subscribe\", \"params\": [\"bitforge/%s/%s\"]}\n" , send_uid , model , version );
363+ snprintf (subscribe_msg , sizeof ( subscribe_msg ) , "{\"id\": %d, \"method\": \"mining.subscribe\", \"params\": [\"bitforge/%s/%s\"]}\n" , send_uid , model , version );
321364 debug_stratum_tx (subscribe_msg );
322365
323366 return write (socket , subscribe_msg , strlen (subscribe_msg ));
@@ -326,16 +369,26 @@ int STRATUM_V1_subscribe(int socket, int send_uid, char * model)
326369int STRATUM_V1_suggest_difficulty (int socket , int send_uid , uint32_t difficulty )
327370{
328371 char difficulty_msg [BUFFER_SIZE ];
329- sprintf (difficulty_msg , "{\"id\": %d, \"method\": \"mining.suggest_difficulty\", \"params\": [%ld]}\n" , send_uid , difficulty );
372+ snprintf (difficulty_msg , sizeof ( difficulty_msg ) , "{\"id\": %d, \"method\": \"mining.suggest_difficulty\", \"params\": [%ld]}\n" , send_uid , difficulty );
330373 debug_stratum_tx (difficulty_msg );
331374
332375 return write (socket , difficulty_msg , strlen (difficulty_msg ));
333376}
334377
378+ int STRATUM_V1_extranonce_subscribe (int socket , int send_uid )
379+ {
380+ char msg [BUFFER_SIZE ];
381+ snprintf (msg , sizeof (msg ), "{\"id\": %d, \"method\": \"mining.extranonce.subscribe\", \"params\": []}\n" , send_uid );
382+ debug_stratum_tx (msg );
383+
384+ return write (socket , msg , strlen (msg ));
385+ }
386+
387+
335388int STRATUM_V1_authenticate (int socket , int send_uid , const char * username , const char * pass )
336389{
337390 char authorize_msg [BUFFER_SIZE ];
338- sprintf (authorize_msg , "{\"id\": %d, \"method\": \"mining.authorize\", \"params\": [\"%s\", \"%s\"]}\n" , send_uid , username ,
391+ snprintf (authorize_msg , sizeof ( authorize_msg ) , "{\"id\": %d, \"method\": \"mining.authorize\", \"params\": [\"%s\", \"%s\"]}\n" , send_uid , username ,
339392 pass );
340393 debug_stratum_tx (authorize_msg );
341394
@@ -353,7 +406,7 @@ int STRATUM_V1_submit_share(int socket, int send_uid, const char * username, con
353406 const uint32_t nonce , const uint32_t version )
354407{
355408 char submit_msg [BUFFER_SIZE ];
356- sprintf (submit_msg ,
409+ snprintf (submit_msg , sizeof ( submit_msg ) ,
357410 "{\"id\": %d, \"method\": \"mining.submit\", \"params\": [\"%s\", \"%s\", \"%s\", \"%08lx\", \"%08lx\", \"%08lx\"]}\n" ,
358411 send_uid , username , jobid , extranonce_2 , ntime , nonce , version );
359412 debug_stratum_tx (submit_msg );
0 commit comments