示例#1
0
int tnet_ice_candidate_send_stun_bind_request(tnet_ice_candidate_t* self, struct sockaddr_storage* server_addr, const char* username, const char* password)
{
	tnet_stun_message_t *request = tsk_null; 
	tsk_buffer_t *buffer = tsk_null;
	int ret, sendBytes;

	if(!self || !server_addr || !TNET_SOCKET_IS_VALID(self->socket)){
		TSK_DEBUG_ERROR("Invalid parameter");
		return -1;
	}

	request = _tnet_ice_candidate_stun_create_bind_request(self, username, password);
	if(!request){
		TSK_DEBUG_ERROR("Failed to create STUN request");
		ret = -2;
		goto bail;
	}

	if(!(buffer = tnet_stun_message_serialize(request))){
		TSK_DEBUG_ERROR("Failed to serialize STUN request");
		ret = -3;
		goto bail;
	}

	sendBytes = tnet_sockfd_sendto(self->socket->fd, (const struct sockaddr*)server_addr, buffer->data, buffer->size);// return number of sent bytes
	if(sendBytes == buffer->size){
		memcpy(self->stun.transac_id, request->transaction_id, sizeof(tnet_stun_transacid_t));
		ret = 0;
	}
	else{
		TSK_DEBUG_ERROR("Only %d bytes sent", sendBytes);
		ret = -4;
		goto bail;
	}

bail:
	TSK_OBJECT_SAFE_FREE(request);
	TSK_OBJECT_SAFE_FREE(buffer);

	return 0;
}
tsk_size_t tnet_transport_sendto(const tnet_transport_handle_t *handle, tnet_fd_t from, const struct sockaddr *to, const void* buf, tsk_size_t size)
{
	tnet_transport_t *transport = (tnet_transport_t*)handle;
	int numberOfBytesSent = 0;
	
	if(!transport){
		TSK_DEBUG_ERROR("Invalid server handle.");
		goto bail;
	}
	
	if(!TNET_SOCKET_TYPE_IS_DGRAM(transport->master->type)){
		TSK_DEBUG_ERROR("In order to use sendto() you must use an udp transport.");
		goto bail;
	}
	
    if((numberOfBytesSent = tnet_sockfd_sendto(from, to, buf, size)) <= 0){
		TNET_PRINT_LAST_ERROR("sendto have failed.");
		goto bail;
	}
		
bail:
	return numberOfBytesSent;
}
示例#3
0
int tnet_dtls_socket_do_handshake(tnet_dtls_socket_handle_t* handle, const struct sockaddr_storage* remote_addr)
{
#if !HAVE_OPENSSL || !HAVE_OPENSSL_DTLS
	TSK_DEBUG_ERROR("OpenSSL or DTLS not enabled");
	return -1;

#else
	tnet_dtls_socket_t *socket = handle;
	int ret = 0, len;
	void* out_data;

	if (!socket) {
		TSK_DEBUG_ERROR("Invalid parameter");
		return -1;
	}

	tsk_safeobj_lock(socket);

	// update remote address even if handshaking is completed
	if (remote_addr) {
		socket->remote.addr = *remote_addr;
	}

	if (socket->handshake_completed) {
		TSK_DEBUG_INFO("Handshake completed");
		ret = 0;
		goto bail;
	}

	if (!socket->handshake_started) {
		if ((ret = SSL_do_handshake(socket->ssl)) != 1) {
			switch ((ret = SSL_get_error(socket->ssl, ret))) {
			case SSL_ERROR_WANT_READ:
			case SSL_ERROR_WANT_WRITE:
			case SSL_ERROR_NONE:
				break;
			default:
				TSK_DEBUG_ERROR("DTLS handshake failed [%s]", ERR_error_string(ERR_get_error(), tsk_null));
				_tnet_dtls_socket_raise_event_dataless(socket, tnet_dtls_socket_event_type_handshake_failed);
				ret = -2;
				goto bail;
			}
		}
		socket->handshake_started = (ret == SSL_ERROR_NONE); // TODO: reset for renegotiation
	}

	if ((len = (int)BIO_get_mem_data(socket->wbio, &out_data)) > 0 && out_data) {
		if (socket->handshake_storedata) { // e.g. when TURN is enabled we have to query handshaking data and sent it via the negotiated channel
			if ((int)socket->handshake_data.size < len) {
				if (!(socket->handshake_data.ptr = tsk_realloc(socket->handshake_data.ptr, len))) {
					socket->handshake_data.size = 0;
					socket->handshake_data.count = 0;
					ret = -5;
					goto bail;
				}
				socket->handshake_data.size = len;
			}
			socket->handshake_data.count = len;
			memcpy(socket->handshake_data.ptr, out_data, len);
		}
		else {
			int sentlen = 0;
			tnet_port_t port;
			tnet_ip_t ip;
			tsk_bool_t is_dgram = TNET_SOCKET_TYPE_IS_DGRAM(socket->wrapped_sock->type);
			const uint8_t *record_ptr, *records_ptr = out_data;
			tsk_size_t record_size;
			int records_len = len;

			tnet_get_sockip_n_port((const struct sockaddr *)&socket->remote.addr, &ip, &port);
			TSK_DEBUG_INFO("DTLS data handshake to send with len = %d, from(%.*s/%d) to(%.*s/%d)", len, (int)sizeof(socket->wrapped_sock->ip), socket->wrapped_sock->ip, socket->wrapped_sock->port, (int)sizeof(ip), ip, port);

			//!\ IP fragmentation issues must be avoided even if the local transport is TCP/TLS because the relayed (TURN) transport could be UDP
			while (records_len > 0 && (ret = tnet_dtls_socket_get_record_first(records_ptr, (tsk_size_t)records_len, &record_ptr, &record_size)) == 0) {
				if (is_dgram) {
					sentlen += tnet_sockfd_sendto(socket->wrapped_sock->fd, (const struct sockaddr *)&socket->remote.addr, record_ptr, record_size);
				}
				else {
					sentlen += tnet_socket_send_stream(socket->wrapped_sock, record_ptr, record_size);
				}
				records_len -= (int)record_size;
				records_ptr += record_size;
			}
			TSK_DEBUG_INFO("DTLS data handshake sent len = %d", sentlen);
		}
	}

	BIO_reset(socket->rbio);
	BIO_reset(socket->wbio);

	if ((socket->handshake_completed = SSL_is_init_finished(socket->ssl))) {
		TSK_DEBUG_INFO("DTLS handshake completed");

#if HAVE_OPENSSL_DTLS_SRTP
		if (socket->use_srtp){
#if !defined(SRTP_MAX_KEY_LEN)
#	define cipher_key_length (128 >> 3) // rfc5764 4.1.2.  SRTP Protection Profiles
#	define cipher_salt_length (112 >> 3) // rfc5764 4.1.2.  SRTP Protection Profiles
			// "cipher_key_length" is also equal to srtp_profile_get_master_key_length(srtp_profile_aes128_cm_sha1_80)
			// "cipher_salt_length" is also srtp_profile_get_master_salt_length(srtp_profile_aes128_cm_sha1_80)
#	define SRTP_MAX_KEY_LEN (cipher_key_length + cipher_salt_length)
#endif /* SRTP_MAX_KEY_LEN */
#define EXTRACTOR_dtls_srtp_text "EXTRACTOR-dtls_srtp"
#define EXTRACTOR_dtls_srtp_text_len 19
			uint8_t keying_material[SRTP_MAX_KEY_LEN << 1];
			static const tsk_size_t keying_material_size = sizeof(keying_material);
			/*if(socket->use_srtp)*/{
				SRTP_PROTECTION_PROFILE *p = SSL_get_selected_srtp_profile(socket->ssl);
				if (!p) {
					TSK_DEBUG_ERROR("SSL_get_selected_srtp_profile() returned null [%s]", ERR_error_string(ERR_get_error(), tsk_null));
					ret = -2;
					goto bail;
				}
				// alert user
				_tnet_dtls_socket_raise_event(socket, tnet_dtls_socket_event_type_dtls_srtp_profile_selected, p->name, tsk_strlen(p->name));

				memset(keying_material, 0, sizeof(keying_material));

				// rfc5764 - 4.2.  Key Derivation
				ret = SSL_export_keying_material(socket->ssl, keying_material, sizeof(keying_material), EXTRACTOR_dtls_srtp_text, EXTRACTOR_dtls_srtp_text_len, tsk_null, 0, 0);
				if (ret != 1) {
					// alert listener
					_tnet_dtls_socket_raise_event_dataless(socket, tnet_dtls_socket_event_type_error);
					TSK_DEBUG_ERROR("SSL_export_keying_material() failed [%s]", ERR_error_string(ERR_get_error(), tsk_null));
					ret = -2;
					goto bail;
				}
			}
			// alert listener
			_tnet_dtls_socket_raise_event(socket, tnet_dtls_socket_event_type_dtls_srtp_data, keying_material, keying_material_size);
		}
#endif /* HAVE_OPENSSL_DTLS_SRTP */
		_tnet_dtls_socket_raise_event_dataless(socket, tnet_dtls_socket_event_type_handshake_succeed);
	}
	ret = 0; // clear "ret", error will directly jump to "bail:"
bail:
	tsk_safeobj_unlock(socket);
	return ret;
#endif
}