Exemple #1
0
static int transport_bio_buffered_write(BIO* bio, const char* buf, int num)
{
	int i, ret;
	int status;
	int nchunks;
	int committedBytes;
	DataChunk chunks[2];
	WINPR_BIO_BUFFERED_SOCKET* ptr = (WINPR_BIO_BUFFERED_SOCKET*) bio->ptr;

	ret = num;
	ptr->writeBlocked = FALSE;
	BIO_clear_flags(bio, BIO_FLAGS_WRITE);

	/* we directly append extra bytes in the xmit buffer, this could be prevented
	 * but for now it makes the code more simple.
	 */
	if (buf && num && !ringbuffer_write(&ptr->xmitBuffer, (const BYTE*) buf, num))
	{
		WLog_ERR(TAG, "an error occured when writing (num: %d)", num);
		return -1;
	}

	committedBytes = 0;
	nchunks = ringbuffer_peek(&ptr->xmitBuffer, chunks, ringbuffer_used(&ptr->xmitBuffer));

	for (i = 0; i < nchunks; i++)
	{
		while (chunks[i].size)
		{
			status = BIO_write(bio->next_bio, chunks[i].data, chunks[i].size);

			if (status <= 0)
			{
				if (!BIO_should_retry(bio->next_bio))
				{
					BIO_clear_flags(bio, BIO_FLAGS_SHOULD_RETRY);
					ret = -1; /* fatal error */
					goto out;
				}

				if (BIO_should_write(bio->next_bio))
				{
					BIO_set_flags(bio, BIO_FLAGS_WRITE);
					ptr->writeBlocked = TRUE;
					goto out; /* EWOULDBLOCK */
				}
			}

			committedBytes += status;
			chunks[i].size -= status;
			chunks[i].data += status;
		}
	}

out:
	ringbuffer_commit_read_bytes(&ptr->xmitBuffer, committedBytes);

	return ret;
}
Exemple #2
0
static int transport_bio_buffered_write(BIO* bio, const char* buf, int num)
{
	int status, ret;
	rdpTcp* tcp = (rdpTcp*) bio->ptr;
	int nchunks, committedBytes, i;
	DataChunk chunks[2];

	ret = num;
	tcp->writeBlocked = FALSE;
	BIO_clear_flags(bio, BIO_FLAGS_WRITE);

	/* we directly append extra bytes in the xmit buffer, this could be prevented
	 * but for now it makes the code more simple.
	 */
	if (buf && num && !ringbuffer_write(&tcp->xmitBuffer, (const BYTE*) buf, num))
	{
		fprintf(stderr, "%s: an error occured when writing(toWrite=%d)\n", __FUNCTION__, num);
		return -1;
	}

	committedBytes = 0;
	nchunks = ringbuffer_peek(&tcp->xmitBuffer, chunks, ringbuffer_used(&tcp->xmitBuffer));

	for (i = 0; i < nchunks; i++)
	{
		while (chunks[i].size)
		{
			status = BIO_write(bio->next_bio, chunks[i].data, chunks[i].size);

			if (status <= 0)
			{
				if (!BIO_should_retry(bio->next_bio))
				{
					BIO_clear_flags(bio, BIO_FLAGS_SHOULD_RETRY);
					ret = -1; /* fatal error */
					goto out;
				}

				if (BIO_should_write(bio->next_bio))
				{
					BIO_set_flags(bio, BIO_FLAGS_WRITE);
					tcp->writeBlocked = TRUE;
					goto out; /* EWOULDBLOCK */
				}
			}

			committedBytes += status;
			chunks[i].size -= status;
			chunks[i].data += status;
		}
	}

out:
	ringbuffer_commit_read_bytes(&tcp->xmitBuffer, committedBytes);
	return ret;
}
Exemple #3
0
int tcp_attach(rdpTcp* tcp, int sockfd)
{
	tcp->sockfd = sockfd;
	SetEventFileDescriptor(tcp->event, tcp->sockfd);

	ringbuffer_commit_read_bytes(&tcp->xmitBuffer, ringbuffer_used(&tcp->xmitBuffer));

	if (tcp->socketBio)
	{
		if (BIO_set_fd(tcp->socketBio, sockfd, 1) < 0)
			return -1;
	}
	else
	{
		tcp->socketBio = BIO_new(BIO_s_simple_socket());

		if (!tcp->socketBio)
			return -1;

		BIO_set_fd(tcp->socketBio, sockfd, BIO_CLOSE);
	}

	if (!tcp->bufferedBio)
	{
		tcp->bufferedBio = BIO_new(BIO_s_buffered_socket());

		if (!tcp->bufferedBio)
			return FALSE;

		tcp->bufferedBio->ptr = tcp;

		tcp->bufferedBio = BIO_push(tcp->bufferedBio, tcp->socketBio);
	}

	return 0;
}
Exemple #4
0
int tls_write_all(rdpTls* tls, const BYTE* data, int length)
{
	int status, nchunks, commitedBytes;
	rdpTcp *tcp;
#ifdef HAVE_POLL_H
	struct pollfd pollfds;
#else
	fd_set rset, wset;
	fd_set *rsetPtr, *wsetPtr;
	struct timeval tv;
#endif
	BIO* bio = tls->bio;
	DataChunk chunks[2];

	BIO* bufferedBio = findBufferedBio(bio);

	if (!bufferedBio)
	{
		DEBUG_WARN( "%s: error unable to retrieve the bufferedBio in the BIO chain\n", __FUNCTION__);
		return -1;
	}

	tcp = (rdpTcp*) bufferedBio->ptr;

	do
	{
		status = BIO_write(bio, data, length);

		if (status > 0)
			break;

		if (!BIO_should_retry(bio))
			return -1;
#ifdef HAVE_POLL_H
		pollfds.fd = tcp->sockfd;
		pollfds.revents = 0;
		pollfds.events = 0;

		if (tcp->writeBlocked)
		{
			pollfds.events |= POLLOUT;
		}
		else if (tcp->readBlocked)
		{
			pollfds.events |= POLLIN;
		}
		else
		{
			DEBUG_WARN( "%s: weird we're blocked but the underlying is not read or write blocked !\n", __FUNCTION__);
			USleep(10);
			continue;
		}

		do
		{
			status = poll(&pollfds, 1, 100);
		}
		while ((status < 0) && (errno == EINTR));
#else
		/* we try to handle SSL want_read and want_write nicely */
		rsetPtr = wsetPtr = NULL;

		if (tcp->writeBlocked)
		{
			wsetPtr = &wset;
			FD_ZERO(&wset);
			FD_SET(tcp->sockfd, &wset);
		}
		else if (tcp->readBlocked)
		{
			rsetPtr = &rset;
			FD_ZERO(&rset);
			FD_SET(tcp->sockfd, &rset);
		}
		else
		{
			DEBUG_WARN( "%s: weird we're blocked but the underlying is not read or write blocked !\n", __FUNCTION__);
			USleep(10);
			continue;
		}

		tv.tv_sec = 0;
		tv.tv_usec = 100 * 1000;

		status = _select(tcp->sockfd + 1, rsetPtr, wsetPtr, NULL, &tv);
#endif
		if (status < 0)
			return -1;
	}
	while (TRUE);

	/* make sure the output buffer is empty */
	commitedBytes = 0;
	while ((nchunks = ringbuffer_peek(&tcp->xmitBuffer, chunks, ringbuffer_used(&tcp->xmitBuffer))))
	{
		int i;

		for (i = 0; i < nchunks; i++)
		{
			while (chunks[i].size)
			{
				status = BIO_write(tcp->socketBio, chunks[i].data, chunks[i].size);

				if (status > 0)
				{
					chunks[i].size -= status;
					chunks[i].data += status;
					commitedBytes += status;
					continue;
				}

				if (!BIO_should_retry(tcp->socketBio))
					goto out_fail;

#ifdef HAVE_POLL_H
				pollfds.fd = tcp->sockfd;
				pollfds.events = POLLIN;
				pollfds.revents = 0;

				do
				{
					status = poll(&pollfds, 1, 100);
				}
				while ((status < 0) && (errno == EINTR));
#else
				FD_ZERO(&rset);
				FD_SET(tcp->sockfd, &rset);
				tv.tv_sec = 0;
				tv.tv_usec = 100 * 1000;

				status = _select(tcp->sockfd + 1, &rset, NULL, NULL, &tv);
#endif
				if (status < 0)
					goto out_fail;
			}

		}
	}

	ringbuffer_commit_read_bytes(&tcp->xmitBuffer, commitedBytes);
	return length;

out_fail:
	ringbuffer_commit_read_bytes(&tcp->xmitBuffer, commitedBytes);
	return -1;
}