コード例 #1
0
ファイル: tcp.c プロジェクト: Distrotech/FreeRDP
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;
}
コード例 #2
0
ファイル: tcp.c プロジェクト: Auto-Droid/FreeRDP
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;
}
コード例 #3
0
ファイル: tcp.c プロジェクト: Auto-Droid/FreeRDP
BOOL transport_bio_buffered_drain(BIO *bio)
{
	int status;
	rdpTcp* tcp = (rdpTcp*) bio->ptr;

	if (!ringbuffer_used(&tcp->xmitBuffer))
		return 1;

	status = transport_bio_buffered_write(bio, NULL, 0);

	return status >= 0;
}
コード例 #4
0
ファイル: tcp.c プロジェクト: 99455125/FreeRDP
static long transport_bio_buffered_ctrl(BIO* bio, int cmd, long arg1, void* arg2)
{
	int status = -1;
	WINPR_BIO_BUFFERED_SOCKET* ptr = (WINPR_BIO_BUFFERED_SOCKET*) BIO_get_data(bio);

	switch (cmd)
	{
		case BIO_CTRL_FLUSH:
			if (!ringbuffer_used(&ptr->xmitBuffer))
				status = 1;
			else
				status = (transport_bio_buffered_write(bio, NULL, 0) >= 0) ? 1 : -1;

			break;

		case BIO_CTRL_WPENDING:
			status = ringbuffer_used(&ptr->xmitBuffer);
			break;

		case BIO_CTRL_PENDING:
			status = 0;
			break;

		case BIO_C_READ_BLOCKED:
			status = (int) ptr->readBlocked;
			break;

		case BIO_C_WRITE_BLOCKED:
			status = (int) ptr->writeBlocked;
			break;

		default:
			status = BIO_ctrl(BIO_next(bio), cmd, arg1, arg2);
			break;
	}

	return status;
}
コード例 #5
0
ファイル: ringbuffer.c プロジェクト: AMV007/FreeRDP
void ringbuffer_commit_read_bytes(RingBuffer* rb, size_t sz)
{
	DEBUG_RINGBUFFER("ringbuffer_commit_read_bytes(%p): sz: %d", rb, sz);
	
	if (sz < 1)
		return;
	
	assert(rb->size - rb->freeSize >= sz);

	rb->readPtr = (rb->readPtr + sz) % rb->size;
	rb->freeSize += sz;

	/* when we reach a reasonable free size, we can go back to the original size */
	if ((rb->size != rb->initialSize) && (ringbuffer_used(rb) < rb->initialSize / 2))
		ringbuffer_realloc(rb, rb->initialSize);
}
コード例 #6
0
ファイル: tcp.c プロジェクト: Auto-Droid/FreeRDP
static long transport_bio_buffered_ctrl(BIO* bio, int cmd, long arg1, void* arg2)
{
	rdpTcp* tcp = (rdpTcp*) bio->ptr;

	switch (cmd)
	{
		case BIO_CTRL_FLUSH:
			return 1;

		case BIO_CTRL_WPENDING:
			return ringbuffer_used(&tcp->xmitBuffer);

		case BIO_CTRL_PENDING:
			return 0;

		default:
			return BIO_ctrl(bio->next_bio, cmd, arg1, arg2);
	}

	return 0;
}
コード例 #7
0
ファイル: tcp.c プロジェクト: Auto-Droid/FreeRDP
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;
}
コード例 #8
0
ファイル: tls.c プロジェクト: JozLes77/FreeRDP
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;
}
コード例 #9
0
ファイル: ringbuffer.c プロジェクト: AMV007/FreeRDP
static BOOL ringbuffer_realloc(RingBuffer* rb, size_t targetSize)
{
	BYTE* newData;
	
	DEBUG_RINGBUFFER("ringbuffer_realloc(%p): targetSize: %d", rb, targetSize);

	if (rb->writePtr == rb->readPtr)
	{
		/* when no size is used we can realloc() and set the heads at the
		 * beginning of the buffer
		 */
		newData = (BYTE*) realloc(rb->buffer, targetSize);
		
		if (!newData)
			return FALSE;
		
		rb->readPtr = rb->writePtr = 0;
		rb->buffer = newData;
	}
	else if ((rb->writePtr >= rb->readPtr) && (rb->writePtr < targetSize))
	{
		/* we reallocate only if we're in that case, realloc don't touch read
		 * and write heads
		 *
		 *        readPtr              writePtr
		 *              |              |
		 *              v              v
		 * [............|XXXXXXXXXXXXXX|..........]
		 */
		newData = (BYTE*) realloc(rb->buffer, targetSize);
		
		if (!newData)
			return FALSE;

		rb->buffer = newData;
	}
	else
	{
		/* in case of malloc the read head is moved at the beginning of the new buffer
		 * and the write head is set accordingly
		 */
		newData = (BYTE*) malloc(targetSize);
		
		if (!newData)
			return FALSE;
		
		if (rb->readPtr < rb->writePtr)
		{
			/*        readPtr              writePtr
			 *              |              |
			 *              v              v
			 * [............|XXXXXXXXXXXXXX|..........]
			 */
			memcpy(newData, rb->buffer + rb->readPtr, ringbuffer_used(rb));
		}
		else
		{
			/*        writePtr             readPtr
			 *              |              |
			 *              v              v
			 * [XXXXXXXXXXXX|..............|XXXXXXXXXX]
			 */
			BYTE* dst = newData;
			
			memcpy(dst, rb->buffer + rb->readPtr, rb->size - rb->readPtr);
			dst += (rb->size - rb->readPtr);
			
			if (rb->writePtr)
				memcpy(dst, rb->buffer, rb->writePtr);
		}
		
		rb->writePtr = rb->size - rb->freeSize;
		rb->readPtr = 0;
		free(rb->buffer);
		rb->buffer = newData;
	}

	rb->freeSize += (targetSize - rb->size);
	rb->size = targetSize;
	
	return TRUE;
}