| 
						
						
							
								
							
						
						
					 | 
					 | 
					@ -524,6 +524,7 @@ static void clear_workbase(workbase_t *wb) | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						free(wb); | 
					 | 
					 | 
					 | 
						free(wb); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					} | 
					 | 
					 | 
					 | 
					} | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					/* Remove all shares with a workbase id less than wb_id for block changes */ | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					static void purge_share_hashtable(sdata_t *sdata, int64_t wb_id) | 
					 | 
					 | 
					 | 
					static void purge_share_hashtable(sdata_t *sdata, int64_t wb_id) | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					{ | 
					 | 
					 | 
					 | 
					{ | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						share_t *share, *tmp; | 
					 | 
					 | 
					 | 
						share_t *share, *tmp; | 
				
			
			
		
	
	
		
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
					 | 
					@ -543,6 +544,26 @@ static void purge_share_hashtable(sdata_t *sdata, int64_t wb_id) | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
							LOGINFO("Cleared %d shares from share hashtable", purged); | 
					 | 
					 | 
					 | 
							LOGINFO("Cleared %d shares from share hashtable", purged); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					} | 
					 | 
					 | 
					 | 
					} | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					/* Remove all shares with a workbase id == wb_id being discarded */ | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					static void age_share_hashtable(sdata_t *sdata, int64_t wb_id) | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					{ | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
						share_t *share, *tmp; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
						int aged = 0; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
						ck_wlock(&sdata->share_lock); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
						HASH_ITER(hh, sdata->shares, share, tmp) { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
							if (share->workbase_id == wb_id) { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
								HASH_DEL(sdata->shares, share); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
								dealloc(share); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
								aged++; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
							} | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
						} | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
						ck_wunlock(&sdata->share_lock); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
						if (aged) | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
							LOGINFO("Aged %d shares from share hashtable", aged); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					} | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					static char *status_chars = "|/-\\"; | 
					 | 
					 | 
					 | 
					static char *status_chars = "|/-\\"; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					/* Absorbs the json and generates a ckdb json message, logs it to the ckdb
 | 
					 | 
					 | 
					 | 
					/* Absorbs the json and generates a ckdb json message, logs it to the ckdb
 | 
				
			
			
		
	
	
		
		
			
				
					| 
						
							
								
							
						
						
							
								
							
						
						
					 | 
					 | 
					@ -692,6 +713,8 @@ static void add_base(ckpool_t *ckp, workbase_t *wb, bool *new_block) | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						HASH_ITER(hh, sdata->workbases, tmp, tmpa) { | 
					 | 
					 | 
					 | 
						HASH_ITER(hh, sdata->workbases, tmp, tmpa) { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
							if (HASH_COUNT(sdata->workbases) < 3) | 
					 | 
					 | 
					 | 
							if (HASH_COUNT(sdata->workbases) < 3) | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
								break; | 
					 | 
					 | 
					 | 
								break; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
							if (wb == tmp) | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
								continue; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
							/*  Age old workbases older than 10 minutes old */ | 
					 | 
					 | 
					 | 
							/*  Age old workbases older than 10 minutes old */ | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
							if (tmp->gentime.tv_sec < wb->gentime.tv_sec - 600) { | 
					 | 
					 | 
					 | 
							if (tmp->gentime.tv_sec < wb->gentime.tv_sec - 600) { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
								HASH_DEL(sdata->workbases, tmp); | 
					 | 
					 | 
					 | 
								HASH_DEL(sdata->workbases, tmp); | 
				
			
			
		
	
	
		
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
					 | 
					@ -712,6 +735,7 @@ static void add_base(ckpool_t *ckp, workbase_t *wb, bool *new_block) | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						 * to prevent taking recursive locks */ | 
					 | 
					 | 
					 | 
						 * to prevent taking recursive locks */ | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						if (aged) { | 
					 | 
					 | 
					 | 
						if (aged) { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
							send_ageworkinfo(ckp, aged->id); | 
					 | 
					 | 
					 | 
							send_ageworkinfo(ckp, aged->id); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
							age_share_hashtable(sdata, aged->id); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
							clear_workbase(aged); | 
					 | 
					 | 
					 | 
							clear_workbase(aged); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						} | 
					 | 
					 | 
					 | 
						} | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					} | 
					 | 
					 | 
					 | 
					} | 
				
			
			
		
	
	
		
		
			
				
					| 
						
							
								
							
						
						
							
								
							
						
						
					 | 
					 | 
					@ -873,7 +897,7 @@ static void update_base(ckpool_t *ckp, int prio) | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					static void __add_dead(sdata_t *sdata, stratum_instance_t *client) | 
					 | 
					 | 
					 | 
					static void __add_dead(sdata_t *sdata, stratum_instance_t *client) | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					{ | 
					 | 
					 | 
					 | 
					{ | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						LOGDEBUG("Adding dead instance %ld", client->id); | 
					 | 
					 | 
					 | 
						LOGDEBUG("Adding dead instance %ld", client->id); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						LL_PREPEND(sdata->dead_instances, client); | 
					 | 
					 | 
					 | 
						DL_APPEND(sdata->dead_instances, client); | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						sdata->stats.dead++; | 
					 | 
					 | 
					 | 
						sdata->stats.dead++; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						sdata->dead_generated++; | 
					 | 
					 | 
					 | 
						sdata->dead_generated++; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					} | 
					 | 
					 | 
					 | 
					} | 
				
			
			
		
	
	
		
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
					 | 
					@ -881,7 +905,7 @@ static void __add_dead(sdata_t *sdata, stratum_instance_t *client) | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					static void __del_dead(sdata_t *sdata, stratum_instance_t *client) | 
					 | 
					 | 
					 | 
					static void __del_dead(sdata_t *sdata, stratum_instance_t *client) | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					{ | 
					 | 
					 | 
					 | 
					{ | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						LOGDEBUG("Deleting dead instance %ld", client->id); | 
					 | 
					 | 
					 | 
						LOGDEBUG("Deleting dead instance %ld", client->id); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						LL_DELETE(sdata->dead_instances, client); | 
					 | 
					 | 
					 | 
						DL_DELETE_INIT(sdata->dead_instances, client); | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						sdata->stats.dead--; | 
					 | 
					 | 
					 | 
						sdata->stats.dead--; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					} | 
					 | 
					 | 
					 | 
					} | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
	
		
		
			
				
					| 
						
							
								
							
						
						
							
								
							
						
						
					 | 
					 | 
					@ -1036,7 +1060,7 @@ static void stratum_send_diff(sdata_t *sdata, stratum_instance_t *client); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					static void update_diff(ckpool_t *ckp) | 
					 | 
					 | 
					 | 
					static void update_diff(ckpool_t *ckp) | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					{ | 
					 | 
					 | 
					 | 
					{ | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						stratum_instance_t *client; | 
					 | 
					 | 
					 | 
						stratum_instance_t *client, *tmp; | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						sdata_t *sdata = ckp->data; | 
					 | 
					 | 
					 | 
						sdata_t *sdata = ckp->data; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						double old_diff, diff; | 
					 | 
					 | 
					 | 
						double old_diff, diff; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						json_t *val; | 
					 | 
					 | 
					 | 
						json_t *val; | 
				
			
			
		
	
	
		
		
			
				
					| 
						
							
								
							
						
						
							
								
							
						
						
					 | 
					 | 
					@ -1075,7 +1099,7 @@ static void update_diff(ckpool_t *ckp) | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						/* If the diff has dropped, iterate over all the clients and check
 | 
					 | 
					 | 
					 | 
						/* If the diff has dropped, iterate over all the clients and check
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						 * they're at or below the new diff, and update it if not. */ | 
					 | 
					 | 
					 | 
						 * they're at or below the new diff, and update it if not. */ | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						ck_rlock(&sdata->instance_lock); | 
					 | 
					 | 
					 | 
						ck_rlock(&sdata->instance_lock); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						for (client = sdata->stratum_instances; client != NULL; client = client->hh.next) { | 
					 | 
					 | 
					 | 
						HASH_ITER(hh, sdata->stratum_instances, client, tmp) { | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
							if (client->diff > diff) { | 
					 | 
					 | 
					 | 
							if (client->diff > diff) { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
								client->diff = diff; | 
					 | 
					 | 
					 | 
								client->diff = diff; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
								stratum_send_diff(sdata, client); | 
					 | 
					 | 
					 | 
								stratum_send_diff(sdata, client); | 
				
			
			
		
	
	
		
		
			
				
					| 
						
							
								
							
						
						
							
								
							
						
						
					 | 
					 | 
					@ -1122,7 +1146,7 @@ static void __drop_client(sdata_t *sdata, stratum_instance_t *client, user_insta | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						HASH_DEL(sdata->stratum_instances, client); | 
					 | 
					 | 
					 | 
						HASH_DEL(sdata->stratum_instances, client); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						if (instance) | 
					 | 
					 | 
					 | 
						if (instance) | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
							DL_DELETE(instance->instances, client); | 
					 | 
					 | 
					 | 
							DL_DELETE_INIT(instance->instances, client); | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						HASH_FIND(hh, sdata->disconnected_instances, &client->enonce1_64, sizeof(uint64_t), old_client); | 
					 | 
					 | 
					 | 
						HASH_FIND(hh, sdata->disconnected_instances, &client->enonce1_64, sizeof(uint64_t), old_client); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						/* Only keep around one copy of the old client in server mode */ | 
					 | 
					 | 
					 | 
						/* Only keep around one copy of the old client in server mode */ | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						if (!client->ckp->proxy && !old_client && client->enonce1_64 && client->authorised) { | 
					 | 
					 | 
					 | 
						if (!client->ckp->proxy && !old_client && client->enonce1_64 && client->authorised) { | 
				
			
			
		
	
	
		
		
			
				
					| 
						
							
								
							
						
						
							
								
							
						
						
					 | 
					 | 
					@ -1308,6 +1332,7 @@ static void drop_client(sdata_t *sdata, int64_t id) | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						if (client) { | 
					 | 
					 | 
					 | 
						if (client) { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
							instance = client->user_instance; | 
					 | 
					 | 
					 | 
							instance = client->user_instance; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
							if (client->authorised) { | 
					 | 
					 | 
					 | 
							if (client->authorised) { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
								client->authorised = false; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
								dec = true; | 
					 | 
					 | 
					 | 
								dec = true; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
								ckp = client->ckp; | 
					 | 
					 | 
					 | 
								ckp = client->ckp; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
							} | 
					 | 
					 | 
					 | 
							} | 
				
			
			
		
	
	
		
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
					 | 
					@ -1333,7 +1358,7 @@ static void drop_client(sdata_t *sdata, int64_t id) | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						/* Cull old unused clients lazily when there are no more reference
 | 
					 | 
					 | 
					 | 
						/* Cull old unused clients lazily when there are no more reference
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						 * counts for them. */ | 
					 | 
					 | 
					 | 
						 * counts for them. */ | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						LL_FOREACH_SAFE(sdata->dead_instances, client, tmp) { | 
					 | 
					 | 
					 | 
						DL_FOREACH_SAFE(sdata->dead_instances, client, tmp) { | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
							if (!client->ref) { | 
					 | 
					 | 
					 | 
							if (!client->ref) { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
								LOGINFO("Stratifier discarding dead instance %ld", client->id); | 
					 | 
					 | 
					 | 
								LOGINFO("Stratifier discarding dead instance %ld", client->id); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
								__del_dead(sdata, client); | 
					 | 
					 | 
					 | 
								__del_dead(sdata, client); | 
				
			
			
		
	
	
		
		
			
				
					| 
						
							
								
							
						
						
							
								
							
						
						
					 | 
					 | 
					@ -1431,7 +1456,7 @@ static void block_solve(ckpool_t *ckp, const char *blockhash) | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
							if (!strcmp(solvehash, blockhash)) { | 
					 | 
					 | 
					 | 
							if (!strcmp(solvehash, blockhash)) { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
								dealloc(solvehash); | 
					 | 
					 | 
					 | 
								dealloc(solvehash); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
								found = block; | 
					 | 
					 | 
					 | 
								found = block; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
								DL_DELETE(sdata->block_solves, block); | 
					 | 
					 | 
					 | 
								DL_DELETE_INIT(sdata->block_solves, block); | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
								break; | 
					 | 
					 | 
					 | 
								break; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
							} | 
					 | 
					 | 
					 | 
							} | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
							dealloc(solvehash); | 
					 | 
					 | 
					 | 
							dealloc(solvehash); | 
				
			
			
		
	
	
		
		
			
				
					| 
						
							
								
							
						
						
							
								
							
						
						
					 | 
					 | 
					@ -1478,7 +1503,7 @@ static void block_reject(sdata_t *sdata, const char *blockhash) | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
							if (!strcmp(solvehash, blockhash)) { | 
					 | 
					 | 
					 | 
							if (!strcmp(solvehash, blockhash)) { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
								dealloc(solvehash); | 
					 | 
					 | 
					 | 
								dealloc(solvehash); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
								found = block; | 
					 | 
					 | 
					 | 
								found = block; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
								DL_DELETE(sdata->block_solves, block); | 
					 | 
					 | 
					 | 
								DL_DELETE_INIT(sdata->block_solves, block); | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
								break; | 
					 | 
					 | 
					 | 
								break; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
							} | 
					 | 
					 | 
					 | 
							} | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
							dealloc(solvehash); | 
					 | 
					 | 
					 | 
							dealloc(solvehash); | 
				
			
			
		
	
	
		
		
			
				
					| 
						
							
								
							
						
						
							
								
							
						
						
					 | 
					 | 
					@ -1512,8 +1537,6 @@ static void broadcast_ping(sdata_t *sdata) | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						stratum_broadcast(sdata, json_msg); | 
					 | 
					 | 
					 | 
						stratum_broadcast(sdata, json_msg); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					} | 
					 | 
					 | 
					 | 
					} | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					#define SAFE_HASH_OVERHEAD(HASHLIST) (HASHLIST ? HASH_OVERHEAD(hh, HASHLIST) : 0) | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					static void ckmsgq_stats(ckmsgq_t *ckmsgq, int size, json_t **val) | 
					 | 
					 | 
					 | 
					static void ckmsgq_stats(ckmsgq_t *ckmsgq, int size, json_t **val) | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					{ | 
					 | 
					 | 
					 | 
					{ | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						int objects, generated; | 
					 | 
					 | 
					 | 
						int objects, generated; | 
				
			
			
		
	
	
		
		
			
				
					| 
						
							
								
							
						
						
							
								
							
						
						
					 | 
					 | 
					@ -1741,7 +1764,8 @@ static void *blockupdate(void *arg) | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						return NULL; | 
					 | 
					 | 
					 | 
						return NULL; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					} | 
					 | 
					 | 
					 | 
					} | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					static inline bool enonce1_free(sdata_t *sdata, uint64_t enonce1) | 
					 | 
					 | 
					 | 
					/* Enter holding instance_lock */ | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					static bool __enonce1_free(sdata_t *sdata, uint64_t enonce1) | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					{ | 
					 | 
					 | 
					 | 
					{ | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						stratum_instance_t *client, *tmp; | 
					 | 
					 | 
					 | 
						stratum_instance_t *client, *tmp; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						bool ret = true; | 
					 | 
					 | 
					 | 
						bool ret = true; | 
				
			
			
		
	
	
		
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
					 | 
					@ -1751,14 +1775,12 @@ static inline bool enonce1_free(sdata_t *sdata, uint64_t enonce1) | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
							goto out; | 
					 | 
					 | 
					 | 
							goto out; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						} | 
					 | 
					 | 
					 | 
						} | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						ck_rlock(&sdata->instance_lock); | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						HASH_ITER(hh, sdata->stratum_instances, client, tmp) { | 
					 | 
					 | 
					 | 
						HASH_ITER(hh, sdata->stratum_instances, client, tmp) { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
							if (client->enonce1_64 == enonce1) { | 
					 | 
					 | 
					 | 
							if (client->enonce1_64 == enonce1) { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
								ret = false; | 
					 | 
					 | 
					 | 
								ret = false; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
								break; | 
					 | 
					 | 
					 | 
								break; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
							} | 
					 | 
					 | 
					 | 
							} | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						} | 
					 | 
					 | 
					 | 
						} | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						ck_runlock(&sdata->instance_lock); | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					out: | 
					 | 
					 | 
					 | 
					out: | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						return ret; | 
					 | 
					 | 
					 | 
						return ret; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					} | 
					 | 
					 | 
					 | 
					} | 
				
			
			
		
	
	
		
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
					 | 
					@ -1781,13 +1803,19 @@ static void __fill_enonce1data(workbase_t *wb, stratum_instance_t *client) | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					static bool new_enonce1(stratum_instance_t *client) | 
					 | 
					 | 
					 | 
					static bool new_enonce1(stratum_instance_t *client) | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					{ | 
					 | 
					 | 
					 | 
					{ | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						sdata_t *sdata = client->ckp->data; | 
					 | 
					 | 
					 | 
						sdata_t *sdata = client->ckp->data; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
						int enonce1varlen, i; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						bool ret = false; | 
					 | 
					 | 
					 | 
						bool ret = false; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						workbase_t *wb; | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						int i; | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						ck_wlock(&sdata->workbase_lock); | 
					 | 
					 | 
					 | 
						/* Extract the enonce1varlen from the current workbase which may be
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						wb = sdata->current_workbase; | 
					 | 
					 | 
					 | 
						 * a different workbase to when we __fill_enonce1data but the value | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						switch(wb->enonce1varlen) { | 
					 | 
					 | 
					 | 
						 * will not change and this avoids grabbing recursive locks */ | 
				
			
			
				
				
			
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
						ck_rlock(&sdata->workbase_lock); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
						enonce1varlen = sdata->current_workbase->enonce1varlen; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
						ck_runlock(&sdata->workbase_lock); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
						/* instance_lock protects sdata->enonce1u */ | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
						ck_wlock(&sdata->instance_lock); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
						switch(enonce1varlen) { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
							case 8: | 
					 | 
					 | 
					 | 
							case 8: | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
								sdata->enonce1u.u64++; | 
					 | 
					 | 
					 | 
								sdata->enonce1u.u64++; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
								ret = true; | 
					 | 
					 | 
					 | 
								ret = true; | 
				
			
			
		
	
	
		
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
					 | 
					@ -1803,7 +1831,7 @@ static bool new_enonce1(stratum_instance_t *client) | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
							case 2: | 
					 | 
					 | 
					 | 
							case 2: | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
								for (i = 0; i < 65536; i++) { | 
					 | 
					 | 
					 | 
								for (i = 0; i < 65536; i++) { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
									sdata->enonce1u.u16++; | 
					 | 
					 | 
					 | 
									sdata->enonce1u.u16++; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
									ret = enonce1_free(sdata, sdata->enonce1u.u64); | 
					 | 
					 | 
					 | 
									ret = __enonce1_free(sdata, sdata->enonce1u.u64); | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
									if (ret) | 
					 | 
					 | 
					 | 
									if (ret) | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
										break; | 
					 | 
					 | 
					 | 
										break; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
								} | 
					 | 
					 | 
					 | 
								} | 
				
			
			
		
	
	
		
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
					 | 
					@ -1811,18 +1839,21 @@ static bool new_enonce1(stratum_instance_t *client) | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
							case 1: | 
					 | 
					 | 
					 | 
							case 1: | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
								for (i = 0; i < 256; i++) { | 
					 | 
					 | 
					 | 
								for (i = 0; i < 256; i++) { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
									sdata->enonce1u.u8++; | 
					 | 
					 | 
					 | 
									sdata->enonce1u.u8++; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
									ret = enonce1_free(sdata, sdata->enonce1u.u64); | 
					 | 
					 | 
					 | 
									ret = __enonce1_free(sdata, sdata->enonce1u.u64); | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
									if (ret) | 
					 | 
					 | 
					 | 
									if (ret) | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
										break; | 
					 | 
					 | 
					 | 
										break; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
								} | 
					 | 
					 | 
					 | 
								} | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
								break; | 
					 | 
					 | 
					 | 
								break; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
							default: | 
					 | 
					 | 
					 | 
							default: | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
								quit(0, "Invalid enonce1varlen %d", wb->enonce1varlen); | 
					 | 
					 | 
					 | 
								quit(0, "Invalid enonce1varlen %d", enonce1varlen); | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						} | 
					 | 
					 | 
					 | 
						} | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						if (ret) | 
					 | 
					 | 
					 | 
						if (ret) | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
							client->enonce1_64 = sdata->enonce1u.u64; | 
					 | 
					 | 
					 | 
							client->enonce1_64 = sdata->enonce1u.u64; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						__fill_enonce1data(wb, client); | 
					 | 
					 | 
					 | 
						ck_wunlock(&sdata->instance_lock); | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						ck_wunlock(&sdata->workbase_lock); | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
						ck_rlock(&sdata->workbase_lock); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
						__fill_enonce1data(sdata->current_workbase, client); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
						ck_runlock(&sdata->workbase_lock); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						if (unlikely(!ret)) | 
					 | 
					 | 
					 | 
						if (unlikely(!ret)) | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
							LOGWARNING("Enonce1 space exhausted! Proxy rejecting clients"); | 
					 | 
					 | 
					 | 
							LOGWARNING("Enonce1 space exhausted! Proxy rejecting clients"); | 
				
			
			
		
	
	
		
		
			
				
					| 
						
							
								
							
						
						
							
								
							
						
						
					 | 
					 | 
					@ -2624,24 +2655,26 @@ static double submission_diff(stratum_instance_t *client, workbase_t *wb, const | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						return ret; | 
					 | 
					 | 
					 | 
						return ret; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					} | 
					 | 
					 | 
					 | 
					} | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					/* Optimised for the common case where shares are new */ | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					static bool new_share(sdata_t *sdata, const uchar *hash, int64_t  wb_id) | 
					 | 
					 | 
					 | 
					static bool new_share(sdata_t *sdata, const uchar *hash, int64_t  wb_id) | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					{ | 
					 | 
					 | 
					 | 
					{ | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						share_t *share, *match = NULL; | 
					 | 
					 | 
					 | 
						share_t *share = ckzalloc(sizeof(share_t)), *match = NULL; | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						bool ret = false; | 
					 | 
					 | 
					 | 
						bool ret = true; | 
				
			
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						ck_wlock(&sdata->share_lock); | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						HASH_FIND(hh, sdata->shares, hash, 32, match); | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						if (match) | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
							goto out_unlock; | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						share = ckzalloc(sizeof(share_t)); | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						memcpy(share->hash, hash, 32); | 
					 | 
					 | 
					 | 
						memcpy(share->hash, hash, 32); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						share->workbase_id = wb_id; | 
					 | 
					 | 
					 | 
						share->workbase_id = wb_id; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
						ck_wlock(&sdata->share_lock); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						sdata->shares_generated++; | 
					 | 
					 | 
					 | 
						sdata->shares_generated++; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
						HASH_FIND(hh, sdata->shares, hash, 32, match); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
						if (likely(!match)) | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
							HASH_ADD(hh, sdata->shares, hash, 32, share); | 
					 | 
					 | 
					 | 
							HASH_ADD(hh, sdata->shares, hash, 32, share); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						ret = true; | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					out_unlock: | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						ck_wunlock(&sdata->share_lock); | 
					 | 
					 | 
					 | 
						ck_wunlock(&sdata->share_lock); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
						if (unlikely(match)) { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
							dealloc(share); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
							ret = false; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
						} | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						return ret; | 
					 | 
					 | 
					 | 
						return ret; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					} | 
					 | 
					 | 
					 | 
					} | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
	
		
		
			
				
					| 
						
							
								
							
						
						
							
								
							
						
						
					 | 
					 | 
					@ -2857,7 +2890,7 @@ out_unlock: | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						json_set_double(val, "sdiff", sdiff); | 
					 | 
					 | 
					 | 
						json_set_double(val, "sdiff", sdiff); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						json_set_string(val, "hash", hexhash); | 
					 | 
					 | 
					 | 
						json_set_string(val, "hash", hexhash); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						json_set_bool(val, "result", result); | 
					 | 
					 | 
					 | 
						json_set_bool(val, "result", result); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						json_object_set(val, "reject-reason", json_object_dup(json_msg, "reject-reason")); | 
					 | 
					 | 
					 | 
						json_object_set(val, "reject-reason", json_object_get(json_msg, "reject-reason")); | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						json_object_set(val, "error", *err_val); | 
					 | 
					 | 
					 | 
						json_object_set(val, "error", *err_val); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						json_set_int(val, "errn", err); | 
					 | 
					 | 
					 | 
						json_set_int(val, "errn", err); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						json_set_string(val, "createdate", cdfield); | 
					 | 
					 | 
					 | 
						json_set_string(val, "createdate", cdfield); | 
				
			
			
		
	
	
		
		
			
				
					| 
						
							
								
							
						
						
							
								
							
						
						
					 | 
					 | 
					@ -3095,24 +3128,18 @@ static void suggest_diff(stratum_instance_t *client, const char *method, json_t | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						stratum_send_diff(sdata, client); | 
					 | 
					 | 
					 | 
						stratum_send_diff(sdata, client); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					} | 
					 | 
					 | 
					 | 
					} | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					static void parse_method(sdata_t *sdata, const int64_t client_id, json_t *id_val, | 
					 | 
					 | 
					 | 
					/* Enter with client holding ref count */ | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
								 json_t *method_val, json_t *params_val, char *address) | 
					 | 
					 | 
					 | 
					static void parse_method(sdata_t *sdata, stratum_instance_t *client, const int64_t client_id, | 
				
			
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
								 json_t *id_val, json_t *method_val, json_t *params_val, char *address) | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					{ | 
					 | 
					 | 
					 | 
					{ | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						stratum_instance_t *client; | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						const char *method; | 
					 | 
					 | 
					 | 
						const char *method; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						char buf[256]; | 
					 | 
					 | 
					 | 
						char buf[256]; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						client = ref_instance_by_id(sdata, client_id); | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						if (unlikely(!client)) { | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
							LOGINFO("Failed to find client id %ld in hashtable!", client_id); | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
							return; | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						} | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						if (unlikely(client->reject == 2)) { | 
					 | 
					 | 
					 | 
						if (unlikely(client->reject == 2)) { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
							LOGINFO("Dropping client %"PRId64" tagged for lazy invalidation", client_id); | 
					 | 
					 | 
					 | 
							LOGINFO("Dropping client %"PRId64" tagged for lazy invalidation", client_id); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
							snprintf(buf, 255, "dropclient=%ld", client->id); | 
					 | 
					 | 
					 | 
							snprintf(buf, 255, "dropclient=%ld", client_id); | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
							send_proc(client->ckp->connector, buf); | 
					 | 
					 | 
					 | 
							send_proc(client->ckp->connector, buf); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
							goto out; | 
					 | 
					 | 
					 | 
							return; | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						} | 
					 | 
					 | 
					 | 
						} | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						/* Random broken clients send something not an integer as the id so we copy
 | 
					 | 
					 | 
					 | 
						/* Random broken clients send something not an integer as the id so we copy
 | 
				
			
			
		
	
	
		
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
					 | 
					@ -3124,7 +3151,7 @@ static void parse_method(sdata_t *sdata, const int64_t client_id, json_t *id_val | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
							/* Shouldn't happen, sanity check */ | 
					 | 
					 | 
					 | 
							/* Shouldn't happen, sanity check */ | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
							if (unlikely(!result_val)) { | 
					 | 
					 | 
					 | 
							if (unlikely(!result_val)) { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
								LOGWARNING("parse_subscribe returned NULL result_val"); | 
					 | 
					 | 
					 | 
								LOGWARNING("parse_subscribe returned NULL result_val"); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
								goto out; | 
					 | 
					 | 
					 | 
								return; | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
							} | 
					 | 
					 | 
					 | 
							} | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
							val = json_object(); | 
					 | 
					 | 
					 | 
							val = json_object(); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
							json_object_set_new_nocheck(val, "result", result_val); | 
					 | 
					 | 
					 | 
							json_object_set_new_nocheck(val, "result", result_val); | 
				
			
			
		
	
	
		
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
					 | 
					@ -3133,10 +3160,11 @@ static void parse_method(sdata_t *sdata, const int64_t client_id, json_t *id_val | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
							stratum_add_send(sdata, val, client_id); | 
					 | 
					 | 
					 | 
							stratum_add_send(sdata, val, client_id); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
							if (likely(client->subscribed)) | 
					 | 
					 | 
					 | 
							if (likely(client->subscribed)) | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
								update_client(sdata, client, client_id); | 
					 | 
					 | 
					 | 
								update_client(sdata, client, client_id); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
							goto out; | 
					 | 
					 | 
					 | 
							return; | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						} | 
					 | 
					 | 
					 | 
						} | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						if (unlikely(cmdmatch(method, "mining.passthrough"))) { | 
					 | 
					 | 
					 | 
						if (unlikely(cmdmatch(method, "mining.passthrough"))) { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
							LOGNOTICE("Adding passthrough client %ld", client_id); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
							/* We need to inform the connector process that this client
 | 
					 | 
					 | 
					 | 
							/* We need to inform the connector process that this client
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
							 * is a passthrough and to manage its messages accordingly. | 
					 | 
					 | 
					 | 
							 * is a passthrough and to manage its messages accordingly. | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
							 * Remove this instance since the client id may well be | 
					 | 
					 | 
					 | 
							 * Remove this instance since the client id may well be | 
				
			
			
		
	
	
		
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
					 | 
					@ -3147,17 +3175,16 @@ static void parse_method(sdata_t *sdata, const int64_t client_id, json_t *id_val | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
							__add_dead(sdata, client); | 
					 | 
					 | 
					 | 
							__add_dead(sdata, client); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
							ck_wunlock(&sdata->instance_lock); | 
					 | 
					 | 
					 | 
							ck_wunlock(&sdata->instance_lock); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
							LOGNOTICE("Adding passthrough client %ld", client->id); | 
					 | 
					 | 
					 | 
							snprintf(buf, 255, "passthrough=%ld", client_id); | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
							snprintf(buf, 255, "passthrough=%ld", client->id); | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
							send_proc(client->ckp->connector, buf); | 
					 | 
					 | 
					 | 
							send_proc(client->ckp->connector, buf); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
							goto out; | 
					 | 
					 | 
					 | 
							return; | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						} | 
					 | 
					 | 
					 | 
						} | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						if (cmdmatch(method, "mining.auth") && client->subscribed) { | 
					 | 
					 | 
					 | 
						if (cmdmatch(method, "mining.auth") && client->subscribed) { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
							json_params_t *jp = create_json_params(client_id, method_val, params_val, id_val, address); | 
					 | 
					 | 
					 | 
							json_params_t *jp = create_json_params(client_id, method_val, params_val, id_val, address); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
							ckmsgq_add(sdata->sauthq, jp); | 
					 | 
					 | 
					 | 
							ckmsgq_add(sdata->sauthq, jp); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
							goto out; | 
					 | 
					 | 
					 | 
							return; | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						} | 
					 | 
					 | 
					 | 
						} | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						/* We should only accept authorised requests from here on */ | 
					 | 
					 | 
					 | 
						/* We should only accept authorised requests from here on */ | 
				
			
			
		
	
	
		
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
					 | 
					@ -3165,22 +3192,22 @@ static void parse_method(sdata_t *sdata, const int64_t client_id, json_t *id_val | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
							/* Dropping unauthorised clients here also allows the
 | 
					 | 
					 | 
					 | 
							/* Dropping unauthorised clients here also allows the
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
							 * stratifier process to restart since it will have lost all | 
					 | 
					 | 
					 | 
							 * stratifier process to restart since it will have lost all | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
							 * the stratum instance data. Clients will just reconnect. */ | 
					 | 
					 | 
					 | 
							 * the stratum instance data. Clients will just reconnect. */ | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
							LOGINFO("Dropping unauthorised client %ld", client->id); | 
					 | 
					 | 
					 | 
							LOGINFO("Dropping unauthorised client %ld", client_id); | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
							snprintf(buf, 255, "dropclient=%ld", client->id); | 
					 | 
					 | 
					 | 
							snprintf(buf, 255, "dropclient=%ld", client_id); | 
				
			
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
							send_proc(client->ckp->connector, buf); | 
					 | 
					 | 
					 | 
							send_proc(client->ckp->connector, buf); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
							goto out; | 
					 | 
					 | 
					 | 
							return; | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						} | 
					 | 
					 | 
					 | 
						} | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						if (cmdmatch(method, "mining.submit")) { | 
					 | 
					 | 
					 | 
						if (cmdmatch(method, "mining.submit")) { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
							json_params_t *jp = create_json_params(client_id, method_val, params_val, id_val, address); | 
					 | 
					 | 
					 | 
							json_params_t *jp = create_json_params(client_id, method_val, params_val, id_val, address); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
							ckmsgq_add(sdata->sshareq, jp); | 
					 | 
					 | 
					 | 
							ckmsgq_add(sdata->sshareq, jp); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
							goto out; | 
					 | 
					 | 
					 | 
							return; | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						} | 
					 | 
					 | 
					 | 
						} | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						if (cmdmatch(method, "mining.suggest")) { | 
					 | 
					 | 
					 | 
						if (cmdmatch(method, "mining.suggest")) { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
							suggest_diff(client, method, params_val); | 
					 | 
					 | 
					 | 
							suggest_diff(client, method, params_val); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
							goto out; | 
					 | 
					 | 
					 | 
							return; | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						} | 
					 | 
					 | 
					 | 
						} | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						/* Covers both get_transactions and get_txnhashes */ | 
					 | 
					 | 
					 | 
						/* Covers both get_transactions and get_txnhashes */ | 
				
			
			
		
	
	
		
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
					 | 
					@ -3188,14 +3215,15 @@ static void parse_method(sdata_t *sdata, const int64_t client_id, json_t *id_val | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
							json_params_t *jp = create_json_params(client_id, method_val, params_val, id_val, address); | 
					 | 
					 | 
					 | 
							json_params_t *jp = create_json_params(client_id, method_val, params_val, id_val, address); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
							ckmsgq_add(sdata->stxnq, jp); | 
					 | 
					 | 
					 | 
							ckmsgq_add(sdata->stxnq, jp); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
							goto out; | 
					 | 
					 | 
					 | 
							return; | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						} | 
					 | 
					 | 
					 | 
						} | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						/* Unhandled message here */ | 
					 | 
					 | 
					 | 
						/* Unhandled message here */ | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					out: | 
					 | 
					 | 
					 | 
						LOGINFO("Unhandled client %ld method %s", client_id, method); | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						dec_instance_ref(sdata, client); | 
					 | 
					 | 
					 | 
						return; | 
				
			
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					} | 
					 | 
					 | 
					 | 
					} | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					static void parse_instance_msg(sdata_t *sdata, smsg_t *msg) | 
					 | 
					 | 
					 | 
					/* Entered with client holding ref count */ | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					static void parse_instance_msg(sdata_t *sdata, smsg_t *msg, stratum_instance_t *client) | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					{ | 
					 | 
					 | 
					 | 
					{ | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						json_t *val = msg->json_msg, *id_val, *method, *params; | 
					 | 
					 | 
					 | 
						json_t *val = msg->json_msg, *id_val, *method, *params; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						int64_t client_id = msg->client_id; | 
					 | 
					 | 
					 | 
						int64_t client_id = msg->client_id; | 
				
			
			
		
	
	
		
		
			
				
					| 
						
							
								
							
						
						
							
								
							
						
						
					 | 
					 | 
					@ -3226,7 +3254,7 @@ static void parse_instance_msg(sdata_t *sdata, smsg_t *msg) | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
							send_json_err(sdata, client_id, id_val, "-1:params not found"); | 
					 | 
					 | 
					 | 
							send_json_err(sdata, client_id, id_val, "-1:params not found"); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
							goto out; | 
					 | 
					 | 
					 | 
							goto out; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						} | 
					 | 
					 | 
					 | 
						} | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						parse_method(sdata, client_id, id_val, method, params, msg->address); | 
					 | 
					 | 
					 | 
						parse_method(sdata, client, client_id, id_val, method, params, msg->address); | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					out: | 
					 | 
					 | 
					 | 
					out: | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						json_decref(val); | 
					 | 
					 | 
					 | 
						json_decref(val); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						free(msg); | 
					 | 
					 | 
					 | 
						free(msg); | 
				
			
			
		
	
	
		
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
					 | 
					@ -3235,6 +3263,7 @@ out: | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					static void srecv_process(ckpool_t *ckp, char *buf) | 
					 | 
					 | 
					 | 
					static void srecv_process(ckpool_t *ckp, char *buf) | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					{ | 
					 | 
					 | 
					 | 
					{ | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						sdata_t *sdata = ckp->data; | 
					 | 
					 | 
					 | 
						sdata_t *sdata = ckp->data; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
						stratum_instance_t *client; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						smsg_t *msg; | 
					 | 
					 | 
					 | 
						smsg_t *msg; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						json_t *val; | 
					 | 
					 | 
					 | 
						json_t *val; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						int server; | 
					 | 
					 | 
					 | 
						int server; | 
				
			
			
		
	
	
		
		
			
				
					| 
						
							
								
							
						
						
							
								
							
						
						
					 | 
					 | 
					@ -3279,12 +3308,15 @@ static void srecv_process(ckpool_t *ckp, char *buf) | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						/* Parse the message here */ | 
					 | 
					 | 
					 | 
						/* Parse the message here */ | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						ck_wlock(&sdata->instance_lock); | 
					 | 
					 | 
					 | 
						ck_wlock(&sdata->instance_lock); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						/* client_id instance doesn't exist yet, create one */ | 
					 | 
					 | 
					 | 
						client = __instance_by_id(sdata, msg->client_id); | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						if (!__instance_by_id(sdata, msg->client_id)) | 
					 | 
					 | 
					 | 
						/* If client_id instance doesn't exist yet, create one */ | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
							__stratum_add_instance(ckp, msg->client_id, server); | 
					 | 
					 | 
					 | 
						if (unlikely(!client)) | 
				
			
			
				
				
			
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
							client = __stratum_add_instance(ckp, msg->client_id, server); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
						__inc_instance_ref(client); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						ck_wunlock(&sdata->instance_lock); | 
					 | 
					 | 
					 | 
						ck_wunlock(&sdata->instance_lock); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						parse_instance_msg(sdata, msg); | 
					 | 
					 | 
					 | 
						parse_instance_msg(sdata, msg, client); | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
						dec_instance_ref(sdata, client); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					out: | 
					 | 
					 | 
					 | 
					out: | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						free(buf); | 
					 | 
					 | 
					 | 
						free(buf); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					} | 
					 | 
					 | 
					 | 
					} | 
				
			
			
		
	
	
		
		
			
				
					| 
						
							
								
							
						
						
						
					 | 
					 | 
					
  |