|  |  |  | @@ -355,7 +355,6 @@ static void _tf_ssb_add_broadcast(tf_ssb_t* ssb, const tf_ssb_broadcast_t* broad | 
		
	
		
			
				|  |  |  |  | static uint64_t _tf_ssb_callback_pre(tf_ssb_t* ssb); | 
		
	
		
			
				|  |  |  |  | static void _tf_ssb_callback_post(tf_ssb_t* ssb, void* callback, uint64_t pre); | 
		
	
		
			
				|  |  |  |  | static void _tf_ssb_connection_client_send_hello(tf_ssb_connection_t* connection); | 
		
	
		
			
				|  |  |  |  | static void _tf_ssb_connection_close(tf_ssb_connection_t* connection, const char* reason); | 
		
	
		
			
				|  |  |  |  | static void _tf_ssb_connection_destroy(tf_ssb_connection_t* connection, const char* reason); | 
		
	
		
			
				|  |  |  |  | static void _tf_ssb_connection_finalizer(JSRuntime* runtime, JSValue value); | 
		
	
		
			
				|  |  |  |  | static void _tf_ssb_connection_on_close(uv_handle_t* handle); | 
		
	
	
		
			
				
					
					|  |  |  | @@ -407,10 +406,10 @@ static void _tf_ssb_connection_send_close(tf_ssb_connection_t* connection) | 
		
	
		
			
				|  |  |  |  | 	{ | 
		
	
		
			
				|  |  |  |  | 		_tf_ssb_write(connection, message_enc, sizeof(message_enc)); | 
		
	
		
			
				|  |  |  |  | 	} | 
		
	
		
			
				|  |  |  |  | 	_tf_ssb_connection_close(connection, "crypto_secretbox_easy close message"); | 
		
	
		
			
				|  |  |  |  | 	tf_ssb_connection_close(connection, "crypto_secretbox_easy close message"); | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | static void _tf_ssb_connection_close(tf_ssb_connection_t* connection, const char* reason) | 
		
	
		
			
				|  |  |  |  | void tf_ssb_connection_close(tf_ssb_connection_t* connection, const char* reason) | 
		
	
		
			
				|  |  |  |  | { | 
		
	
		
			
				|  |  |  |  | 	if (connection->state == k_tf_ssb_state_closing) | 
		
	
		
			
				|  |  |  |  | 	{ | 
		
	
	
		
			
				
					
					|  |  |  | @@ -441,7 +440,7 @@ static void _tf_ssb_connection_on_write(uv_write_t* req, int status) | 
		
	
		
			
				|  |  |  |  | 	{ | 
		
	
		
			
				|  |  |  |  | 		char buffer[256]; | 
		
	
		
			
				|  |  |  |  | 		snprintf(buffer, sizeof(buffer), "write failed asynchronously: %s", uv_strerror(status)); | 
		
	
		
			
				|  |  |  |  | 		_tf_ssb_connection_close(connection, buffer); | 
		
	
		
			
				|  |  |  |  | 		tf_ssb_connection_close(connection, buffer); | 
		
	
		
			
				|  |  |  |  | 	} | 
		
	
		
			
				|  |  |  |  | 	tf_free(req); | 
		
	
		
			
				|  |  |  |  | } | 
		
	
	
		
			
				
					
					|  |  |  | @@ -460,7 +459,7 @@ static void _tf_ssb_write(tf_ssb_connection_t* connection, void* data, size_t si | 
		
	
		
			
				|  |  |  |  | 			tf_ssb_connection_adjust_write_count(connection, -1); | 
		
	
		
			
				|  |  |  |  | 			char buffer[256]; | 
		
	
		
			
				|  |  |  |  | 			snprintf(buffer, sizeof(buffer), "write failed: %s", uv_strerror(result)); | 
		
	
		
			
				|  |  |  |  | 			_tf_ssb_connection_close(connection, buffer); | 
		
	
		
			
				|  |  |  |  | 			tf_ssb_connection_close(connection, buffer); | 
		
	
		
			
				|  |  |  |  | 			tf_free(write); | 
		
	
		
			
				|  |  |  |  | 		} | 
		
	
		
			
				|  |  |  |  | 	} | 
		
	
	
		
			
				
					
					|  |  |  | @@ -476,28 +475,28 @@ static void _tf_ssb_connection_send_identity(tf_ssb_connection_t* connection, ui | 
		
	
		
			
				|  |  |  |  | 	memcpy(connection->serverepub, pubkey, sizeof(connection->serverepub)); | 
		
	
		
			
				|  |  |  |  | 	if (crypto_auth_hmacsha512256_verify(hmac, connection->serverepub, 32, connection->ssb->network_key) != 0) | 
		
	
		
			
				|  |  |  |  | 	{ | 
		
	
		
			
				|  |  |  |  | 		_tf_ssb_connection_close(connection, "invalid server hello"); | 
		
	
		
			
				|  |  |  |  | 		tf_ssb_connection_close(connection, "invalid server hello"); | 
		
	
		
			
				|  |  |  |  | 		return; | 
		
	
		
			
				|  |  |  |  | 	} | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 	uint8_t shared_secret_ab[crypto_scalarmult_curve25519_SCALARBYTES]; | 
		
	
		
			
				|  |  |  |  | 	if (crypto_scalarmult_curve25519(shared_secret_ab, connection->epriv, connection->serverepub) != 0) | 
		
	
		
			
				|  |  |  |  | 	{ | 
		
	
		
			
				|  |  |  |  | 		_tf_ssb_connection_close(connection, "unable to compute shared_secret_ab as client"); | 
		
	
		
			
				|  |  |  |  | 		tf_ssb_connection_close(connection, "unable to compute shared_secret_ab as client"); | 
		
	
		
			
				|  |  |  |  | 		return; | 
		
	
		
			
				|  |  |  |  | 	} | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 	uint8_t servercurvepub[crypto_scalarmult_curve25519_SCALARBYTES]; | 
		
	
		
			
				|  |  |  |  | 	if (crypto_sign_ed25519_pk_to_curve25519(servercurvepub, connection->serverpub) != 0) | 
		
	
		
			
				|  |  |  |  | 	{ | 
		
	
		
			
				|  |  |  |  | 		_tf_ssb_connection_close(connection, "unable to compute key to curve25519 as client"); | 
		
	
		
			
				|  |  |  |  | 		tf_ssb_connection_close(connection, "unable to compute key to curve25519 as client"); | 
		
	
		
			
				|  |  |  |  | 		return; | 
		
	
		
			
				|  |  |  |  | 	} | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 	uint8_t shared_secret_aB[crypto_scalarmult_curve25519_SCALARBYTES]; | 
		
	
		
			
				|  |  |  |  | 	if (crypto_scalarmult_curve25519(shared_secret_aB, connection->epriv, servercurvepub) != 0) | 
		
	
		
			
				|  |  |  |  | 	{ | 
		
	
		
			
				|  |  |  |  | 		_tf_ssb_connection_close(connection, "unable to compute shared_secret_aB as client"); | 
		
	
		
			
				|  |  |  |  | 		tf_ssb_connection_close(connection, "unable to compute shared_secret_aB as client"); | 
		
	
		
			
				|  |  |  |  | 		return; | 
		
	
		
			
				|  |  |  |  | 	} | 
		
	
		
			
				|  |  |  |  |  | 
		
	
	
		
			
				
					
					|  |  |  | @@ -512,7 +511,7 @@ static void _tf_ssb_connection_send_identity(tf_ssb_connection_t* connection, ui | 
		
	
		
			
				|  |  |  |  | 	unsigned long long siglen; | 
		
	
		
			
				|  |  |  |  | 	if (crypto_sign_detached(connection->detached_signature_A, &siglen, msg, sizeof(msg), connection->ssb->priv) != 0) | 
		
	
		
			
				|  |  |  |  | 	{ | 
		
	
		
			
				|  |  |  |  | 		_tf_ssb_connection_close(connection, "unable to compute detached_signature_A as client"); | 
		
	
		
			
				|  |  |  |  | 		tf_ssb_connection_close(connection, "unable to compute detached_signature_A as client"); | 
		
	
		
			
				|  |  |  |  | 		return; | 
		
	
		
			
				|  |  |  |  | 	} | 
		
	
		
			
				|  |  |  |  |  | 
		
	
	
		
			
				
					
					|  |  |  | @@ -531,7 +530,7 @@ static void _tf_ssb_connection_send_identity(tf_ssb_connection_t* connection, ui | 
		
	
		
			
				|  |  |  |  | 	uint8_t c[crypto_secretbox_MACBYTES + sizeof(tosend)]; | 
		
	
		
			
				|  |  |  |  | 	if (crypto_secretbox_easy(c, tosend, sizeof(tosend), nonce, hash2) != 0) | 
		
	
		
			
				|  |  |  |  | 	{ | 
		
	
		
			
				|  |  |  |  | 		_tf_ssb_connection_close(connection, "unable to create initial secretbox as client"); | 
		
	
		
			
				|  |  |  |  | 		tf_ssb_connection_close(connection, "unable to create initial secretbox as client"); | 
		
	
		
			
				|  |  |  |  | 		return; | 
		
	
		
			
				|  |  |  |  | 	} | 
		
	
		
			
				|  |  |  |  |  | 
		
	
	
		
			
				
					
					|  |  |  | @@ -566,7 +565,7 @@ static void _tf_ssb_connection_box_stream_send(tf_ssb_connection_t* connection, | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 		if (crypto_secretbox_easy(message_enc + 34 - 16, message + offset, send_size, nonce2, connection->c_to_s_box_key) != 0) | 
		
	
		
			
				|  |  |  |  | 		{ | 
		
	
		
			
				|  |  |  |  | 			_tf_ssb_connection_close(connection, "unable to secretbox message"); | 
		
	
		
			
				|  |  |  |  | 			tf_ssb_connection_close(connection, "unable to secretbox message"); | 
		
	
		
			
				|  |  |  |  | 			tf_free(message_enc); | 
		
	
		
			
				|  |  |  |  | 			return; | 
		
	
		
			
				|  |  |  |  | 		} | 
		
	
	
		
			
				
					
					|  |  |  | @@ -576,7 +575,7 @@ static void _tf_ssb_connection_box_stream_send(tf_ssb_connection_t* connection, | 
		
	
		
			
				|  |  |  |  | 		memcpy(header + sizeof(uint16_t), message_enc + 34 - 16, 16); | 
		
	
		
			
				|  |  |  |  | 		if (crypto_secretbox_easy(message_enc, header, sizeof(header), nonce1, connection->c_to_s_box_key) != 0) | 
		
	
		
			
				|  |  |  |  | 		{ | 
		
	
		
			
				|  |  |  |  | 			_tf_ssb_connection_close(connection, "unable to secretbox header"); | 
		
	
		
			
				|  |  |  |  | 			tf_ssb_connection_close(connection, "unable to secretbox header"); | 
		
	
		
			
				|  |  |  |  | 			tf_free(message_enc); | 
		
	
		
			
				|  |  |  |  | 			return; | 
		
	
		
			
				|  |  |  |  | 		} | 
		
	
	
		
			
				
					
					|  |  |  | @@ -1122,7 +1121,7 @@ void tf_ssb_close_all(tf_ssb_t* ssb, const char* reason) | 
		
	
		
			
				|  |  |  |  | { | 
		
	
		
			
				|  |  |  |  | 	for (tf_ssb_connection_t* connection = ssb->connections; connection; connection = connection->next) | 
		
	
		
			
				|  |  |  |  | 	{ | 
		
	
		
			
				|  |  |  |  | 		_tf_ssb_connection_close(connection, reason); | 
		
	
		
			
				|  |  |  |  | 		tf_ssb_connection_close(connection, reason); | 
		
	
		
			
				|  |  |  |  | 	} | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
	
		
			
				
					
					|  |  |  | @@ -1185,35 +1184,35 @@ static void _tf_ssb_connection_verify_identity(tf_ssb_connection_t* connection, | 
		
	
		
			
				|  |  |  |  | 	uint8_t shared_secret_ab[crypto_scalarmult_curve25519_SCALARBYTES]; | 
		
	
		
			
				|  |  |  |  | 	if (crypto_scalarmult_curve25519(shared_secret_ab, connection->epriv, connection->serverepub) != 0) | 
		
	
		
			
				|  |  |  |  | 	{ | 
		
	
		
			
				|  |  |  |  | 		_tf_ssb_connection_close(connection, "unable to compute shared_secret_ab"); | 
		
	
		
			
				|  |  |  |  | 		tf_ssb_connection_close(connection, "unable to compute shared_secret_ab"); | 
		
	
		
			
				|  |  |  |  | 		return; | 
		
	
		
			
				|  |  |  |  | 	} | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 	uint8_t servercurvepub[crypto_scalarmult_curve25519_SCALARBYTES]; | 
		
	
		
			
				|  |  |  |  | 	if (crypto_sign_ed25519_pk_to_curve25519(servercurvepub, connection->serverpub) != 0) | 
		
	
		
			
				|  |  |  |  | 	{ | 
		
	
		
			
				|  |  |  |  | 		_tf_ssb_connection_close(connection, "unable to convert key to curve25519"); | 
		
	
		
			
				|  |  |  |  | 		tf_ssb_connection_close(connection, "unable to convert key to curve25519"); | 
		
	
		
			
				|  |  |  |  | 		return; | 
		
	
		
			
				|  |  |  |  | 	} | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 	uint8_t shared_secret_aB[crypto_scalarmult_curve25519_SCALARBYTES]; | 
		
	
		
			
				|  |  |  |  | 	if (crypto_scalarmult_curve25519(shared_secret_aB, connection->epriv, servercurvepub) != 0) | 
		
	
		
			
				|  |  |  |  | 	{ | 
		
	
		
			
				|  |  |  |  | 		_tf_ssb_connection_close(connection, "unable to compute shared_secret_aB"); | 
		
	
		
			
				|  |  |  |  | 		tf_ssb_connection_close(connection, "unable to compute shared_secret_aB"); | 
		
	
		
			
				|  |  |  |  | 		return; | 
		
	
		
			
				|  |  |  |  | 	} | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 	uint8_t clientcurvepriv[crypto_scalarmult_curve25519_SCALARBYTES]; | 
		
	
		
			
				|  |  |  |  | 	if (crypto_sign_ed25519_sk_to_curve25519(clientcurvepriv, connection->ssb->priv) != 0) | 
		
	
		
			
				|  |  |  |  | 	{ | 
		
	
		
			
				|  |  |  |  | 		_tf_ssb_connection_close(connection, "unable to convert key to curve25519"); | 
		
	
		
			
				|  |  |  |  | 		tf_ssb_connection_close(connection, "unable to convert key to curve25519"); | 
		
	
		
			
				|  |  |  |  | 		return; | 
		
	
		
			
				|  |  |  |  | 	} | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 	uint8_t shared_secret_Ab[crypto_scalarmult_curve25519_SCALARBYTES]; | 
		
	
		
			
				|  |  |  |  | 	if (crypto_scalarmult_curve25519(shared_secret_Ab, clientcurvepriv, connection->serverepub) != 0) | 
		
	
		
			
				|  |  |  |  | 	{ | 
		
	
		
			
				|  |  |  |  | 		_tf_ssb_connection_close(connection, "unable to compute shared_secret_Ab"); | 
		
	
		
			
				|  |  |  |  | 		tf_ssb_connection_close(connection, "unable to compute shared_secret_Ab"); | 
		
	
		
			
				|  |  |  |  | 		return; | 
		
	
		
			
				|  |  |  |  | 	} | 
		
	
		
			
				|  |  |  |  |  | 
		
	
	
		
			
				
					
					|  |  |  | @@ -1238,7 +1237,7 @@ static void _tf_ssb_connection_verify_identity(tf_ssb_connection_t* connection, | 
		
	
		
			
				|  |  |  |  | 	uint8_t m[80]; | 
		
	
		
			
				|  |  |  |  | 	if (crypto_secretbox_open_easy(m, message, len, nonce, hash2) != 0) | 
		
	
		
			
				|  |  |  |  | 	{ | 
		
	
		
			
				|  |  |  |  | 		_tf_ssb_connection_close(connection, "unable to open initial secret box as client"); | 
		
	
		
			
				|  |  |  |  | 		tf_ssb_connection_close(connection, "unable to open initial secret box as client"); | 
		
	
		
			
				|  |  |  |  | 		return; | 
		
	
		
			
				|  |  |  |  | 	} | 
		
	
		
			
				|  |  |  |  |  | 
		
	
	
		
			
				
					
					|  |  |  | @@ -1252,14 +1251,14 @@ static void _tf_ssb_connection_verify_identity(tf_ssb_connection_t* connection, | 
		
	
		
			
				|  |  |  |  | 	memcpy(msg + sizeof(connection->ssb->network_key) + sizeof(connection->detached_signature_A) + sizeof(connection->ssb->pub), hash3, sizeof(hash3)); | 
		
	
		
			
				|  |  |  |  | 	if (crypto_sign_verify_detached(m, msg, sizeof(msg), connection->serverpub) != 0) | 
		
	
		
			
				|  |  |  |  | 	{ | 
		
	
		
			
				|  |  |  |  | 		_tf_ssb_connection_close(connection, "unable to verify server identity"); | 
		
	
		
			
				|  |  |  |  | 		tf_ssb_connection_close(connection, "unable to verify server identity"); | 
		
	
		
			
				|  |  |  |  | 		return; | 
		
	
		
			
				|  |  |  |  | 	} | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 	uint8_t nonce2[crypto_auth_hmacsha512256_BYTES]; | 
		
	
		
			
				|  |  |  |  | 	if (crypto_auth_hmacsha512256(nonce2, connection->epub, sizeof(connection->epub), connection->ssb->network_key) != 0) | 
		
	
		
			
				|  |  |  |  | 	{ | 
		
	
		
			
				|  |  |  |  | 		_tf_ssb_connection_close(connection, "unable to compute client recv nonce"); | 
		
	
		
			
				|  |  |  |  | 		tf_ssb_connection_close(connection, "unable to compute client recv nonce"); | 
		
	
		
			
				|  |  |  |  | 		return; | 
		
	
		
			
				|  |  |  |  | 	} | 
		
	
		
			
				|  |  |  |  | 	memcpy(connection->nonce, nonce2, sizeof(connection->nonce)); | 
		
	
	
		
			
				
					
					|  |  |  | @@ -1267,7 +1266,7 @@ static void _tf_ssb_connection_verify_identity(tf_ssb_connection_t* connection, | 
		
	
		
			
				|  |  |  |  | 	uint8_t nonce3[crypto_auth_hmacsha512256_BYTES]; | 
		
	
		
			
				|  |  |  |  | 	if (crypto_auth_hmacsha512256(nonce3, connection->serverepub, sizeof(connection->serverepub), connection->ssb->network_key) != 0) | 
		
	
		
			
				|  |  |  |  | 	{ | 
		
	
		
			
				|  |  |  |  | 		_tf_ssb_connection_close(connection, "unable to compute client send nonce"); | 
		
	
		
			
				|  |  |  |  | 		tf_ssb_connection_close(connection, "unable to compute client send nonce"); | 
		
	
		
			
				|  |  |  |  | 		return; | 
		
	
		
			
				|  |  |  |  | 	} | 
		
	
		
			
				|  |  |  |  | 	memcpy(connection->send_nonce, nonce3, sizeof(connection->send_nonce)); | 
		
	
	
		
			
				
					
					|  |  |  | @@ -1357,7 +1356,7 @@ static void _tf_ssb_connection_verify_client_identity(tf_ssb_connection_t* conne | 
		
	
		
			
				|  |  |  |  | 	uint8_t shared_secret_ab[crypto_scalarmult_curve25519_SCALARBYTES]; | 
		
	
		
			
				|  |  |  |  | 	if (crypto_scalarmult_curve25519(shared_secret_ab, connection->epriv, connection->serverepub) != 0) | 
		
	
		
			
				|  |  |  |  | 	{ | 
		
	
		
			
				|  |  |  |  | 		_tf_ssb_connection_close(connection, "unable to compute shared_secret_ab"); | 
		
	
		
			
				|  |  |  |  | 		tf_ssb_connection_close(connection, "unable to compute shared_secret_ab"); | 
		
	
		
			
				|  |  |  |  | 		return; | 
		
	
		
			
				|  |  |  |  | 	} | 
		
	
		
			
				|  |  |  |  |  | 
		
	
	
		
			
				
					
					|  |  |  | @@ -1370,7 +1369,7 @@ static void _tf_ssb_connection_verify_client_identity(tf_ssb_connection_t* conne | 
		
	
		
			
				|  |  |  |  | 	uint8_t curvepriv[crypto_scalarmult_curve25519_SCALARBYTES]; | 
		
	
		
			
				|  |  |  |  | 	if (crypto_sign_ed25519_sk_to_curve25519(curvepriv, connection->ssb->priv) != 0) | 
		
	
		
			
				|  |  |  |  | 	{ | 
		
	
		
			
				|  |  |  |  | 		_tf_ssb_connection_close(connection, "unable to convert key to curve25519"); | 
		
	
		
			
				|  |  |  |  | 		tf_ssb_connection_close(connection, "unable to convert key to curve25519"); | 
		
	
		
			
				|  |  |  |  | 		return; | 
		
	
		
			
				|  |  |  |  | 	} | 
		
	
		
			
				|  |  |  |  |  | 
		
	
	
		
			
				
					
					|  |  |  | @@ -1379,7 +1378,7 @@ static void _tf_ssb_connection_verify_client_identity(tf_ssb_connection_t* conne | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 	if (crypto_scalarmult(shared_secret_aB, curvepriv, connection->serverepub) != 0) | 
		
	
		
			
				|  |  |  |  | 	{ | 
		
	
		
			
				|  |  |  |  | 		_tf_ssb_connection_close(connection, "unable to compute shared_secret_aB"); | 
		
	
		
			
				|  |  |  |  | 		tf_ssb_connection_close(connection, "unable to compute shared_secret_aB"); | 
		
	
		
			
				|  |  |  |  | 		return; | 
		
	
		
			
				|  |  |  |  | 	} | 
		
	
		
			
				|  |  |  |  |  | 
		
	
	
		
			
				
					
					|  |  |  | @@ -1408,7 +1407,7 @@ static void _tf_ssb_connection_verify_client_identity(tf_ssb_connection_t* conne | 
		
	
		
			
				|  |  |  |  | 	uint8_t m[96]; | 
		
	
		
			
				|  |  |  |  | 	if (crypto_secretbox_open_easy(m, message, len, nonce, hash2) != 0) | 
		
	
		
			
				|  |  |  |  | 	{ | 
		
	
		
			
				|  |  |  |  | 		_tf_ssb_connection_close(connection, "unable to open initial secret box as server"); | 
		
	
		
			
				|  |  |  |  | 		tf_ssb_connection_close(connection, "unable to open initial secret box as server"); | 
		
	
		
			
				|  |  |  |  | 		return; | 
		
	
		
			
				|  |  |  |  | 	} | 
		
	
		
			
				|  |  |  |  | 	uint8_t* detached_signature_A = m; | 
		
	
	
		
			
				
					
					|  |  |  | @@ -1419,7 +1418,7 @@ static void _tf_ssb_connection_verify_client_identity(tf_ssb_connection_t* conne | 
		
	
		
			
				|  |  |  |  | 		tf_ssb_id_bin_to_str(id_base64, sizeof(id_base64), m + 64); | 
		
	
		
			
				|  |  |  |  | 		char reason[256]; | 
		
	
		
			
				|  |  |  |  | 		snprintf(reason, sizeof(reason), "already connected: %s\n", id_base64); | 
		
	
		
			
				|  |  |  |  | 		_tf_ssb_connection_close(connection, reason); | 
		
	
		
			
				|  |  |  |  | 		tf_ssb_connection_close(connection, reason); | 
		
	
		
			
				|  |  |  |  | 		return; | 
		
	
		
			
				|  |  |  |  | 	} | 
		
	
		
			
				|  |  |  |  |  | 
		
	
	
		
			
				
					
					|  |  |  | @@ -1434,14 +1433,14 @@ static void _tf_ssb_connection_verify_client_identity(tf_ssb_connection_t* conne | 
		
	
		
			
				|  |  |  |  | 	memcpy(msg + sizeof(connection->ssb->network_key) + sizeof(connection->ssb->pub), hash3, sizeof(hash3)); | 
		
	
		
			
				|  |  |  |  | 	if (crypto_sign_verify_detached(detached_signature_A, msg, sizeof(msg), connection->serverpub) != 0) | 
		
	
		
			
				|  |  |  |  | 	{ | 
		
	
		
			
				|  |  |  |  | 		_tf_ssb_connection_close(connection, "unable to verify client identity"); | 
		
	
		
			
				|  |  |  |  | 		tf_ssb_connection_close(connection, "unable to verify client identity"); | 
		
	
		
			
				|  |  |  |  | 		return; | 
		
	
		
			
				|  |  |  |  | 	} | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 	uint8_t nonce2[crypto_auth_hmacsha512256_BYTES]; | 
		
	
		
			
				|  |  |  |  | 	if (crypto_auth_hmacsha512256(nonce2, connection->epub, sizeof(connection->epub), connection->ssb->network_key) != 0) | 
		
	
		
			
				|  |  |  |  | 	{ | 
		
	
		
			
				|  |  |  |  | 		_tf_ssb_connection_close(connection, "unable to compute initial recv nonce as server"); | 
		
	
		
			
				|  |  |  |  | 		tf_ssb_connection_close(connection, "unable to compute initial recv nonce as server"); | 
		
	
		
			
				|  |  |  |  | 		return; | 
		
	
		
			
				|  |  |  |  | 	} | 
		
	
		
			
				|  |  |  |  | 	memcpy(connection->nonce, nonce2, sizeof(connection->nonce)); | 
		
	
	
		
			
				
					
					|  |  |  | @@ -1449,7 +1448,7 @@ static void _tf_ssb_connection_verify_client_identity(tf_ssb_connection_t* conne | 
		
	
		
			
				|  |  |  |  | 	uint8_t nonce3[crypto_auth_hmacsha512256_BYTES]; | 
		
	
		
			
				|  |  |  |  | 	if (crypto_auth_hmacsha512256(nonce3, connection->serverepub, sizeof(connection->serverepub), connection->ssb->network_key) != 0) | 
		
	
		
			
				|  |  |  |  | 	{ | 
		
	
		
			
				|  |  |  |  | 		_tf_ssb_connection_close(connection, "unable to compute initial send nonce as server"); | 
		
	
		
			
				|  |  |  |  | 		tf_ssb_connection_close(connection, "unable to compute initial send nonce as server"); | 
		
	
		
			
				|  |  |  |  | 		return; | 
		
	
		
			
				|  |  |  |  | 	} | 
		
	
		
			
				|  |  |  |  | 	memcpy(connection->send_nonce, nonce3, sizeof(connection->send_nonce)); | 
		
	
	
		
			
				
					
					|  |  |  | @@ -1465,21 +1464,21 @@ static void _tf_ssb_connection_verify_client_identity(tf_ssb_connection_t* conne | 
		
	
		
			
				|  |  |  |  | 	unsigned long long siglen; | 
		
	
		
			
				|  |  |  |  | 	if (crypto_sign_detached(detached_signature_B, &siglen, sign_b, sizeof(sign_b), connection->ssb->priv) != 0) | 
		
	
		
			
				|  |  |  |  | 	{ | 
		
	
		
			
				|  |  |  |  | 		_tf_ssb_connection_close(connection, "unable to compute detached_signature_B as server"); | 
		
	
		
			
				|  |  |  |  | 		tf_ssb_connection_close(connection, "unable to compute detached_signature_B as server"); | 
		
	
		
			
				|  |  |  |  | 		return; | 
		
	
		
			
				|  |  |  |  | 	} | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 	uint8_t clientcurvepub[crypto_scalarmult_curve25519_SCALARBYTES]; | 
		
	
		
			
				|  |  |  |  | 	if (crypto_sign_ed25519_pk_to_curve25519(clientcurvepub, connection->serverpub) != 0) | 
		
	
		
			
				|  |  |  |  | 	{ | 
		
	
		
			
				|  |  |  |  | 		_tf_ssb_connection_close(connection, "unable to convert key to curve25519"); | 
		
	
		
			
				|  |  |  |  | 		tf_ssb_connection_close(connection, "unable to convert key to curve25519"); | 
		
	
		
			
				|  |  |  |  | 		return; | 
		
	
		
			
				|  |  |  |  | 	} | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 	uint8_t shared_secret_Ab[crypto_scalarmult_curve25519_SCALARBYTES]; | 
		
	
		
			
				|  |  |  |  | 	if (crypto_scalarmult_curve25519(shared_secret_Ab, connection->epriv, clientcurvepub) != 0) | 
		
	
		
			
				|  |  |  |  | 	{ | 
		
	
		
			
				|  |  |  |  | 		_tf_ssb_connection_close(connection, "unable to compute shared_secret_Ab as server"); | 
		
	
		
			
				|  |  |  |  | 		tf_ssb_connection_close(connection, "unable to compute shared_secret_Ab as server"); | 
		
	
		
			
				|  |  |  |  | 		return; | 
		
	
		
			
				|  |  |  |  | 	} | 
		
	
		
			
				|  |  |  |  |  | 
		
	
	
		
			
				
					
					|  |  |  | @@ -1505,7 +1504,7 @@ static void _tf_ssb_connection_verify_client_identity(tf_ssb_connection_t* conne | 
		
	
		
			
				|  |  |  |  | 	uint8_t c[crypto_secretbox_MACBYTES + sizeof(detached_signature_B)]; | 
		
	
		
			
				|  |  |  |  | 	if (crypto_secretbox_easy(c, detached_signature_B, sizeof(detached_signature_B), nonce, key_hash) != 0) | 
		
	
		
			
				|  |  |  |  | 	{ | 
		
	
		
			
				|  |  |  |  | 		_tf_ssb_connection_close(connection, "unable to create initial secret box as server"); | 
		
	
		
			
				|  |  |  |  | 		tf_ssb_connection_close(connection, "unable to create initial secret box as server"); | 
		
	
		
			
				|  |  |  |  | 		return; | 
		
	
		
			
				|  |  |  |  | 	} | 
		
	
		
			
				|  |  |  |  |  | 
		
	
	
		
			
				
					
					|  |  |  | @@ -1533,7 +1532,7 @@ static bool _tf_ssb_connection_recv_pop(tf_ssb_connection_t* connection, uint8_t | 
		
	
		
			
				|  |  |  |  | 	{ | 
		
	
		
			
				|  |  |  |  | 		char message[256]; | 
		
	
		
			
				|  |  |  |  | 		snprintf(message, sizeof(message), "Trying to pop a message (%zd) larger than the connection's receive buffer (%zd).", size, sizeof(connection->recv_buffer)); | 
		
	
		
			
				|  |  |  |  | 		_tf_ssb_connection_close(connection, message); | 
		
	
		
			
				|  |  |  |  | 		tf_ssb_connection_close(connection, message); | 
		
	
		
			
				|  |  |  |  | 	} | 
		
	
		
			
				|  |  |  |  | 	if (connection->recv_size < size) | 
		
	
		
			
				|  |  |  |  | 	{ | 
		
	
	
		
			
				
					
					|  |  |  | @@ -1580,7 +1579,7 @@ static void _tf_ssb_connection_rpc_recv(tf_ssb_connection_t* connection, uint8_t | 
		
	
		
			
				|  |  |  |  | 	bool close_connection = false; | 
		
	
		
			
				|  |  |  |  | 	if (size == 0) | 
		
	
		
			
				|  |  |  |  | 	{ | 
		
	
		
			
				|  |  |  |  | 		_tf_ssb_connection_close(connection, "rpc recv zero"); | 
		
	
		
			
				|  |  |  |  | 		tf_ssb_connection_close(connection, "rpc recv zero"); | 
		
	
		
			
				|  |  |  |  | 		return; | 
		
	
		
			
				|  |  |  |  | 	} | 
		
	
		
			
				|  |  |  |  | 	else if (flags & k_ssb_rpc_flag_json) | 
		
	
	
		
			
				
					
					|  |  |  | @@ -1680,7 +1679,9 @@ static void _tf_ssb_connection_rpc_recv(tf_ssb_connection_t* connection, uint8_t | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 	if (close_connection) | 
		
	
		
			
				|  |  |  |  | 	{ | 
		
	
		
			
				|  |  |  |  | 		tf_ssb_connection_close(connection); | 
		
	
		
			
				|  |  |  |  | 		char buffer[1024]; | 
		
	
		
			
				|  |  |  |  | 		snprintf(buffer, sizeof(buffer), "Failed to parse: %.*s", (int)size, message); | 
		
	
		
			
				|  |  |  |  | 		tf_ssb_connection_close(connection, buffer); | 
		
	
		
			
				|  |  |  |  | 	} | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
	
		
			
				
					
					|  |  |  | @@ -1694,7 +1695,7 @@ static void _tf_ssb_connection_rpc_recv_push(tf_ssb_connection_t* connection, co | 
		
	
		
			
				|  |  |  |  | 			(connection->rpc_recv_size + size_left > sizeof(connection->rpc_recv_buffer)) ? sizeof(connection->rpc_recv_buffer) - connection->rpc_recv_size : size_left; | 
		
	
		
			
				|  |  |  |  | 		if (copy_size == 0) | 
		
	
		
			
				|  |  |  |  | 		{ | 
		
	
		
			
				|  |  |  |  | 			_tf_ssb_connection_close(connection, "recv buffer overflow"); | 
		
	
		
			
				|  |  |  |  | 			tf_ssb_connection_close(connection, "recv buffer overflow"); | 
		
	
		
			
				|  |  |  |  | 			return; | 
		
	
		
			
				|  |  |  |  | 		} | 
		
	
		
			
				|  |  |  |  | 		memcpy(connection->rpc_recv_buffer + connection->rpc_recv_size, data + size_processed, copy_size); | 
		
	
	
		
			
				
					
					|  |  |  | @@ -1742,7 +1743,7 @@ static bool _tf_ssb_connection_box_stream_recv(tf_ssb_connection_t* connection) | 
		
	
		
			
				|  |  |  |  | 			uint8_t header[18]; | 
		
	
		
			
				|  |  |  |  | 			if (crypto_secretbox_open_easy(header, header_enc, sizeof(header_enc), connection->nonce, connection->s_to_c_box_key) != 0) | 
		
	
		
			
				|  |  |  |  | 			{ | 
		
	
		
			
				|  |  |  |  | 				_tf_ssb_connection_close(connection, "failed to open header secret box"); | 
		
	
		
			
				|  |  |  |  | 				tf_ssb_connection_close(connection, "failed to open header secret box"); | 
		
	
		
			
				|  |  |  |  | 				return false; | 
		
	
		
			
				|  |  |  |  | 			} | 
		
	
		
			
				|  |  |  |  | 			_tf_ssb_nonce_inc(connection->nonce); | 
		
	
	
		
			
				
					
					|  |  |  | @@ -1750,7 +1751,7 @@ static bool _tf_ssb_connection_box_stream_recv(tf_ssb_connection_t* connection) | 
		
	
		
			
				|  |  |  |  | 			memcpy(connection->body_auth_tag, header + sizeof(uint16_t), sizeof(connection->body_auth_tag)); | 
		
	
		
			
				|  |  |  |  | 			if (!connection->body_len) | 
		
	
		
			
				|  |  |  |  | 			{ | 
		
	
		
			
				|  |  |  |  | 				_tf_ssb_connection_close(connection, "empty body, graceful close"); | 
		
	
		
			
				|  |  |  |  | 				tf_ssb_connection_close(connection, "empty body, graceful close"); | 
		
	
		
			
				|  |  |  |  | 			} | 
		
	
		
			
				|  |  |  |  | 		} | 
		
	
		
			
				|  |  |  |  | 		else | 
		
	
	
		
			
				
					
					|  |  |  | @@ -1766,7 +1767,7 @@ static bool _tf_ssb_connection_box_stream_recv(tf_ssb_connection_t* connection) | 
		
	
		
			
				|  |  |  |  | 		{ | 
		
	
		
			
				|  |  |  |  | 			if (crypto_secretbox_open_easy(connection->secretbox_buf, connection->box_stream_buf, 16 + connection->body_len, connection->nonce, connection->s_to_c_box_key) != 0) | 
		
	
		
			
				|  |  |  |  | 			{ | 
		
	
		
			
				|  |  |  |  | 				_tf_ssb_connection_close(connection, "failed to open secret box"); | 
		
	
		
			
				|  |  |  |  | 				tf_ssb_connection_close(connection, "failed to open secret box"); | 
		
	
		
			
				|  |  |  |  | 				return false; | 
		
	
		
			
				|  |  |  |  | 			} | 
		
	
		
			
				|  |  |  |  | 			_tf_ssb_nonce_inc(connection->nonce); | 
		
	
	
		
			
				
					
					|  |  |  | @@ -1901,7 +1902,7 @@ static void _tf_ssb_connection_destroy(tf_ssb_connection_t* connection, const ch | 
		
	
		
			
				|  |  |  |  | 			if (it->tunnel_connection == connection) | 
		
	
		
			
				|  |  |  |  | 			{ | 
		
	
		
			
				|  |  |  |  | 				it->tunnel_connection = NULL; | 
		
	
		
			
				|  |  |  |  | 				_tf_ssb_connection_close(it, "tunnel closed"); | 
		
	
		
			
				|  |  |  |  | 				tf_ssb_connection_close(it, "tunnel closed"); | 
		
	
		
			
				|  |  |  |  | 				again = true; | 
		
	
		
			
				|  |  |  |  | 				break; | 
		
	
		
			
				|  |  |  |  | 			} | 
		
	
	
		
			
				
					
					|  |  |  | @@ -1981,7 +1982,7 @@ static void _tf_ssb_connection_on_tcp_recv_internal(tf_ssb_connection_t* connect | 
		
	
		
			
				|  |  |  |  | 	{ | 
		
	
		
			
				|  |  |  |  | 		if (connection->recv_size + nread > sizeof(connection->recv_buffer)) | 
		
	
		
			
				|  |  |  |  | 		{ | 
		
	
		
			
				|  |  |  |  | 			_tf_ssb_connection_close(connection, "recv buffer overflow"); | 
		
	
		
			
				|  |  |  |  | 			tf_ssb_connection_close(connection, "recv buffer overflow"); | 
		
	
		
			
				|  |  |  |  | 			return; | 
		
	
		
			
				|  |  |  |  | 		} | 
		
	
		
			
				|  |  |  |  | 		memcpy(connection->recv_buffer + connection->recv_size, data, nread); | 
		
	
	
		
			
				
					
					|  |  |  | @@ -1990,10 +1991,10 @@ static void _tf_ssb_connection_on_tcp_recv_internal(tf_ssb_connection_t* connect | 
		
	
		
			
				|  |  |  |  | 		switch (connection->state) | 
		
	
		
			
				|  |  |  |  | 		{ | 
		
	
		
			
				|  |  |  |  | 		case k_tf_ssb_state_invalid: | 
		
	
		
			
				|  |  |  |  | 			_tf_ssb_connection_close(connection, "received a message in invalid state"); | 
		
	
		
			
				|  |  |  |  | 			tf_ssb_connection_close(connection, "received a message in invalid state"); | 
		
	
		
			
				|  |  |  |  | 			break; | 
		
	
		
			
				|  |  |  |  | 		case k_tf_ssb_state_connected: | 
		
	
		
			
				|  |  |  |  | 			_tf_ssb_connection_close(connection, "received a message in connected state"); | 
		
	
		
			
				|  |  |  |  | 			tf_ssb_connection_close(connection, "received a message in connected state"); | 
		
	
		
			
				|  |  |  |  | 			break; | 
		
	
		
			
				|  |  |  |  | 		case k_tf_ssb_state_sent_hello: | 
		
	
		
			
				|  |  |  |  | 			{ | 
		
	
	
		
			
				
					
					|  |  |  | @@ -2026,7 +2027,7 @@ static void _tf_ssb_connection_on_tcp_recv_internal(tf_ssb_connection_t* connect | 
		
	
		
			
				|  |  |  |  | 					static_assert(sizeof(connection->serverepub) == crypto_box_PUBLICKEYBYTES, "serverepub size"); | 
		
	
		
			
				|  |  |  |  | 					if (crypto_auth_hmacsha512256_verify(hmac, connection->serverepub, 32, connection->ssb->network_key) != 0) | 
		
	
		
			
				|  |  |  |  | 					{ | 
		
	
		
			
				|  |  |  |  | 						_tf_ssb_connection_close(connection, "crypto_auth_hmacsha512256_verify failed"); | 
		
	
		
			
				|  |  |  |  | 						tf_ssb_connection_close(connection, "crypto_auth_hmacsha512256_verify failed"); | 
		
	
		
			
				|  |  |  |  | 					} | 
		
	
		
			
				|  |  |  |  | 					else | 
		
	
		
			
				|  |  |  |  | 					{ | 
		
	
	
		
			
				
					
					|  |  |  | @@ -2059,7 +2060,7 @@ static void _tf_ssb_connection_on_tcp_recv_internal(tf_ssb_connection_t* connect | 
		
	
		
			
				|  |  |  |  | 	} | 
		
	
		
			
				|  |  |  |  | 	else | 
		
	
		
			
				|  |  |  |  | 	{ | 
		
	
		
			
				|  |  |  |  | 		_tf_ssb_connection_close(connection, uv_strerror(nread)); | 
		
	
		
			
				|  |  |  |  | 		tf_ssb_connection_close(connection, uv_strerror(nread)); | 
		
	
		
			
				|  |  |  |  | 	} | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
	
		
			
				
					
					|  |  |  | @@ -2076,14 +2077,14 @@ static void _tf_ssb_connection_client_send_hello(tf_ssb_connection_t* connection | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 	if (crypto_box_keypair(connection->epub, connection->epriv) != 0) | 
		
	
		
			
				|  |  |  |  | 	{ | 
		
	
		
			
				|  |  |  |  | 		_tf_ssb_connection_close(connection, "failed to generate ephemeral keypair"); | 
		
	
		
			
				|  |  |  |  | 		tf_ssb_connection_close(connection, "failed to generate ephemeral keypair"); | 
		
	
		
			
				|  |  |  |  | 		return; | 
		
	
		
			
				|  |  |  |  | 	} | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 	uint8_t a[crypto_auth_hmacsha512256_BYTES]; | 
		
	
		
			
				|  |  |  |  | 	if (crypto_auth_hmacsha512256(a, connection->epub, sizeof(connection->epub), connection->ssb->network_key) != 0) | 
		
	
		
			
				|  |  |  |  | 	{ | 
		
	
		
			
				|  |  |  |  | 		_tf_ssb_connection_close(connection, "failed to create hello message"); | 
		
	
		
			
				|  |  |  |  | 		tf_ssb_connection_close(connection, "failed to create hello message"); | 
		
	
		
			
				|  |  |  |  | 		return; | 
		
	
		
			
				|  |  |  |  | 	} | 
		
	
		
			
				|  |  |  |  |  | 
		
	
	
		
			
				
					
					|  |  |  | @@ -2102,7 +2103,7 @@ static bool _tf_ssb_connection_read_start(tf_ssb_connection_t* connection) | 
		
	
		
			
				|  |  |  |  | 	{ | 
		
	
		
			
				|  |  |  |  | 		char reason[1024]; | 
		
	
		
			
				|  |  |  |  | 		snprintf(reason, sizeof(reason), "uv_read_start failed: %s", uv_strerror(result)); | 
		
	
		
			
				|  |  |  |  | 		_tf_ssb_connection_close(connection, reason); | 
		
	
		
			
				|  |  |  |  | 		tf_ssb_connection_close(connection, reason); | 
		
	
		
			
				|  |  |  |  | 		return false; | 
		
	
		
			
				|  |  |  |  | 	} | 
		
	
		
			
				|  |  |  |  | 	return true; | 
		
	
	
		
			
				
					
					|  |  |  | @@ -2115,7 +2116,7 @@ static bool _tf_ssb_connection_read_stop(tf_ssb_connection_t* connection) | 
		
	
		
			
				|  |  |  |  | 	{ | 
		
	
		
			
				|  |  |  |  | 		char reason[1024]; | 
		
	
		
			
				|  |  |  |  | 		snprintf(reason, sizeof(reason), "uv_read_stop failed: %s", uv_strerror(result)); | 
		
	
		
			
				|  |  |  |  | 		_tf_ssb_connection_close(connection, reason); | 
		
	
		
			
				|  |  |  |  | 		tf_ssb_connection_close(connection, reason); | 
		
	
		
			
				|  |  |  |  | 		return false; | 
		
	
		
			
				|  |  |  |  | 	} | 
		
	
		
			
				|  |  |  |  | 	return true; | 
		
	
	
		
			
				
					
					|  |  |  | @@ -2137,7 +2138,7 @@ static void _tf_ssb_connection_on_connect(uv_connect_t* connect, int status) | 
		
	
		
			
				|  |  |  |  | 	{ | 
		
	
		
			
				|  |  |  |  | 		char reason[1024]; | 
		
	
		
			
				|  |  |  |  | 		snprintf(reason, sizeof(reason), "uv_tcp_connect failed: %s", uv_strerror(status)); | 
		
	
		
			
				|  |  |  |  | 		_tf_ssb_connection_close(connection, reason); | 
		
	
		
			
				|  |  |  |  | 		tf_ssb_connection_close(connection, reason); | 
		
	
		
			
				|  |  |  |  | 	} | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
	
		
			
				
					
					|  |  |  | @@ -2575,7 +2576,7 @@ void tf_ssb_destroy(tf_ssb_t* ssb) | 
		
	
		
			
				|  |  |  |  | 	while (connection) | 
		
	
		
			
				|  |  |  |  | 	{ | 
		
	
		
			
				|  |  |  |  | 		tf_ssb_connection_t* next = connection->next; | 
		
	
		
			
				|  |  |  |  | 		tf_ssb_connection_close(connection); | 
		
	
		
			
				|  |  |  |  | 		tf_ssb_connection_close(connection, "Shutting down."); | 
		
	
		
			
				|  |  |  |  | 		connection = next; | 
		
	
		
			
				|  |  |  |  | 	} | 
		
	
		
			
				|  |  |  |  | 	uv_run(ssb->loop, UV_RUN_NOWAIT); | 
		
	
	
		
			
				
					
					|  |  |  | @@ -2781,7 +2782,10 @@ static void _tf_ssb_connection_tunnel_callback( | 
		
	
		
			
				|  |  |  |  | 	{ | 
		
	
		
			
				|  |  |  |  | 		tf_ssb_connection_remove_request(connection, -request_number); | 
		
	
		
			
				|  |  |  |  | 		tf_ssb_connection_rpc_send(connection, flags, -request_number, NULL, (const uint8_t*)"false", strlen("false"), NULL, NULL, NULL); | 
		
	
		
			
				|  |  |  |  | 		tf_ssb_connection_close(tunnel); | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 		char buffer[1024]; | 
		
	
		
			
				|  |  |  |  | 		snprintf(buffer, sizeof(buffer), "tunnel error: %.*s", (int)size, message); | 
		
	
		
			
				|  |  |  |  | 		tf_ssb_connection_close(tunnel, buffer); | 
		
	
		
			
				|  |  |  |  | 	} | 
		
	
		
			
				|  |  |  |  | 	else | 
		
	
		
			
				|  |  |  |  | 	{ | 
		
	
	
		
			
				
					
					|  |  |  | @@ -2928,11 +2932,6 @@ void tf_ssb_connect(tf_ssb_t* ssb, const char* host, int port, const uint8_t* ke | 
		
	
		
			
				|  |  |  |  | 	} | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | void tf_ssb_connection_close(tf_ssb_connection_t* connection) | 
		
	
		
			
				|  |  |  |  | { | 
		
	
		
			
				|  |  |  |  | 	_tf_ssb_connection_close(connection, "tf_ssb_connection_close"); | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | static void _tf_ssb_on_connection(uv_stream_t* stream, int status) | 
		
	
		
			
				|  |  |  |  | { | 
		
	
		
			
				|  |  |  |  | 	tf_ssb_t* ssb = stream->data; | 
		
	
	
		
			
				
					
					|  |  |  |   |