/* ************************************************************************** */
/* ************* functions for exchanging data through socket *************** */
/* ************************************************************************** */

#include "MPSClient_defs.h"
#include "MPSClient_vars.h"
#include <memory.h>

/* read array of chars from socket */
int td_read_char_array(int socket, char *data, u_long length)
{
	ssize_t size;

	if ( length == 0 )
	{
		return 1;
	}
	else
	{
		data[length - 1] = 0;
		size = recv(socket, data, length * sizeof(char), 0);

		if ( size == length * sizeof(char) )
		{
			return 1;
		}
		else
		{
			*data = 0;
			return 0;
		}
	}
}

/* read string from socket */
int td_read_string(int socket, char *data, u_long length)
{
	int ret;
	if ( length == 0 )
	{
		return 1;
	}
	else
	{
		ret = td_read_char_array(socket, data, length);

		if (ret)
		{
			data[length] = 0;
		}

		return ret;
	}
}

/* read u_char from socket */
int td_read_u_char(int socket, u_char *data)
{
	u_long td_data;
	ssize_t size;

	size = recv(socket, (void *) &td_data, sizeof(u_long), 0);

	if ( size == sizeof(u_long) )
	{
		*data = ntohl(td_data);
		return 1;
	}
	else
	{
		*data = 0;
		return 0;
	}
}

/* read u_long from socket */
int td_read_u_long(int socket, u_long *data)
{
	u_long td_data;
	ssize_t size;

	size = recv(socket, (void *) &td_data, sizeof(u_long), 0);

	if ( size == sizeof(u_long) )
	{
		*data = ntohl(td_data);
		return 1;
	}
	else
	{
		*data = 0;
		return 0;
	}
}


/* write array of chars to socket */
int td_write_char_array(int socket, char *data, u_long length, td_buffer_struct *buffer)
{
	ssize_t size;
	int directsend, sendfirst;
	u_long remaining, copysize;
	char *current;

	if ( length == 0 )
	{
		return 1;
	}
	else
	{
		directsend = 0;
		sendfirst = 0;

		if (buffer == NULL) directsend = 1;
		else if (buffer->buf == NULL) directsend = 1;
		else if (buffer->size < sizeof(char))
		{
			directsend = 1;
			sendfirst = 1;
		}

		if (sendfirst && buffer->pos != 0)
		{
			size = send(socket, buffer->buf, buffer->pos, 0);

			if ( size == buffer->pos )
			{
				buffer->pos = 0;
				return 1;
			}
			else
			{
				buffer->pos = 0;
				return 0;
			}
		}

		if (directsend)
		{
			size = send(socket, data, length * sizeof(char), 0);

			if ( size == length * sizeof(char) )
			{
				return 1;
			}
			else
			{
				return 0;
			}
		}
		else
		{
			remaining = length;
			current = data;

			while ( remaining != 0 )
			{
				if ( buffer->pos + sizeof(char) > buffer->size )
				{
					size = send(socket, buffer->buf, buffer->pos, 0);

					if ( size == buffer->pos )
					{
						buffer->pos = 0;
						return 1;
					}
					else
					{
						buffer->pos = 0;
						return 0;
					}
				}

				copysize = MIN(remaining, (buffer->size - buffer->pos) / sizeof(char));

				memcpy( (void *) (((u_long) (buffer->buf)) + buffer->pos), (void *) current, copysize * sizeof(char));

				buffer->pos += copysize * sizeof(char);
				current += copysize;
				remaining -= copysize;
			}

			return 1;
		}
	}
}

/* write u_char to socket */
int td_write_u_char(int socket, u_char *data, td_buffer_struct *buffer)
{
	u_long td_data;
	ssize_t size;
	int directsend, sendfirst;

	directsend = 0;
	sendfirst = 0;

	if (buffer == NULL) directsend = 1;
	else if (buffer->buf == NULL) directsend = 1;
	else if (buffer->size < sizeof(u_long))
	{
		directsend = 1;
		sendfirst = 1;
	}
	else if (buffer->size - buffer->pos < sizeof(u_long)) sendfirst = 1;

	td_data = htonl(*data);

	if (sendfirst && buffer->pos != 0)
	{
		size = send(socket, buffer->buf, buffer->pos, 0);

		if ( size == buffer->pos )
		{
			buffer->pos = 0;
			return 1;
		}
		else
		{
			buffer->pos = 0;
			return 0;
		}
	}

	if (directsend)
	{
		size = send(socket, (void *) &td_data, sizeof(u_long), 0);

		if ( size == sizeof(u_long) )
		{
			return 1;
		}
		else
		{
			return 0;
		}
	}
	else
	{
		memcpy( (void *) (((u_long) (buffer->buf)) + buffer->pos), (void *) &td_data, sizeof(u_long));
		buffer->pos += sizeof(u_long);

		return 1;
	}
}

/* write u_long to socket */
int td_write_u_long(int socket, u_long *data, td_buffer_struct *buffer)
{
	u_long td_data;
	ssize_t size;
	int directsend, sendfirst;

	directsend = 0;
	sendfirst = 0;

	if (buffer == NULL) directsend = 1;
	else if (buffer->buf == NULL) directsend = 1;
	else if (buffer->size < sizeof(u_long))
	{
		directsend = 1;
		sendfirst = 1;
	}
	else if (buffer->size - buffer->pos < sizeof(u_long)) sendfirst = 1;

	td_data = htonl(*data);

	if (sendfirst && buffer->pos != 0)
	{
		size = send(socket, buffer->buf, buffer->pos, 0);

		if ( size == buffer->pos )
		{
			buffer->pos = 0;
			return 1;
		}
		else
		{
			buffer->pos = 0;
			return 0;
		}
	}

	if (directsend)
	{
		size = send(socket, (void *) &td_data, sizeof(u_long), 0);

		if ( size == sizeof(u_long) )
		{
			return 1;
		}
		else
		{
			return 0;
		}
	}
	else
	{
		memcpy( (void *) (((u_long) (buffer->buf)) + buffer->pos), (void *) &td_data, sizeof(u_long));
		buffer->pos += sizeof(u_long);

		return 1;
	}
}

int td_flush(int socket, td_buffer_struct *buffer)
{
	ssize_t size;
	int buffersend;

	buffersend = 1;

	if (buffer == NULL) buffersend = 0;
	else if (buffer->buf == NULL) buffersend = 0;

	if (buffersend && buffer->pos != 0)
	{
		size = send(socket, buffer->buf, buffer->pos, 0);

		if ( size == buffer->pos )
		{
			buffer->pos = 0;
			return 1;
		}
		else
		{
			buffer->pos = 0;
			return 0;
		}
	}
	else return 1;
}
