int CLocalSocket::read(char * szDataBlock, int nSizeOfBlock)
{
	if (NULL == szDataBlock)
		return FUNCTION_WRONG_PARAMETER;

	if (IsAlreadyConnected())
	{
		HANDLE hDataReadEvent, hDataWrittenEvent;

		s_PacketBuffer * pDataBuffer			= GetReadDataBuffer();
		CMutex dataAccessMutex					= GetReadDataAccessMutex();
		CEvent dataReadEvent					= GetReadDataReadEvent();
		CEvent dataWrittenEvent					= GetReadDataWrittenEvent();

		dataWrittenEvent.SetTimeout(INFINITE);

		if (!dataWrittenEvent.get_signal())
			return LOCAL_SOCKET_ERROR;

		if (CheckForDisconnection())
			return LOCAL_SOCKET_ERROR;

		int nAmountOfIncomingPackets = 0;

		if (!dataAccessMutex.lock())
			return LOCAL_SOCKET_ERROR;

		nAmountOfIncomingPackets = pDataBuffer->nPacketsToBeSent;		

		int nPacketOffset = 0;

		if (nAmountOfIncomingPackets > 1)
		{
			int nLastUsedPacketBytes = 0;
			for(int nCur = 0; nCur < nAmountOfIncomingPackets; nCur++)
			{
				if (nCur > 0)
				{
					if (!dataWrittenEvent.get_signal())
						return LOCAL_SOCKET_ERROR;

					if (CheckForDisconnection())
						return LOCAL_SOCKET_ERROR;

					if (!dataAccessMutex.lock())
						return LOCAL_SOCKET_ERROR;
				}

				if (nCur == nAmountOfIncomingPackets - 1)
					nLastUsedPacketBytes = pDataBuffer->nBytesToBeSent;

				int nAmountOfIncomingBytes = pDataBuffer->nBytesToBeSent;
				if (nAmountOfIncomingBytes > nSizeOfBlock)
					// truncate the data
					memcpy(&szDataBlock[nPacketOffset], &pDataBuffer->cStorage[0], nSizeOfBlock);
				else
					memcpy(&szDataBlock[nPacketOffset], &pDataBuffer->cStorage[0], nAmountOfIncomingBytes);

				nPacketOffset += PACKET_SIZE;

				dataAccessMutex.unlock();

				dataReadEvent.fire_signal();
			}

			return (nLastUsedPacketBytes == 0 ? nAmountOfIncomingPackets * PACKET_SIZE : nAmountOfIncomingPackets * PACKET_SIZE - PACKET_SIZE + nLastUsedPacketBytes);

		}
		else
		{
			int nAmountOfIncomingBytes = pDataBuffer->nBytesToBeSent;
			if (nAmountOfIncomingBytes > nSizeOfBlock)
				// truncate the data
				memcpy(szDataBlock, &pDataBuffer->cStorage[0], nSizeOfBlock);
			else
				memcpy(szDataBlock, &pDataBuffer->cStorage[0], nAmountOfIncomingBytes);

			dataAccessMutex.unlock();

			dataReadEvent.fire_signal();

			return nSizeOfBlock;
		}
	}

	return LOCAL_SOCKET_ERROR;
}
int CLocalSocket::write(const char * szDataBlock, int nSizeOfBlock)
{
	if (NULL == szDataBlock)
		return FUNCTION_WRONG_PARAMETER;

	if (IsAlreadyConnected())
	{
		HANDLE hDataReadEvent, hDataWrittenEvent;

		s_PacketBuffer * pDataBuffer			= GetWriteDataBuffer();
		CMutex dataAccessMutex					= GetWriteDataAccessMutex();
		CEvent dataReadEvent					= GetWriteDataReadEvent();
		CEvent dataWrittenEvent					= GetWriteDataWrittenEvent();

		int nAmountOfPackets	 = nSizeOfBlock / PACKET_SIZE;
		int nLastUsedPacketBytes = nSizeOfBlock % PACKET_SIZE;

		if (0 != nLastUsedPacketBytes && 0 != nAmountOfPackets)
		{
			nAmountOfPackets++;
		}

		if (0 == nAmountOfPackets)
			nAmountOfPackets++;

		if (!dataAccessMutex.lock())
			return LOCAL_SOCKET_ERROR;
		
		pDataBuffer->nPacketsToBeSent  = nAmountOfPackets;
		pDataBuffer->nBytesToBeSent	= PACKET_SIZE;

		dataAccessMutex.unlock();

		int nAmountOfBytesToBeWritten = PACKET_SIZE;
		int nPacketOffset = 0;

			for (int nCur = 0; nCur < nAmountOfPackets; nCur++)
			{
				dataAccessMutex.lock();

				pDataBuffer->nCurrentNumber = nCur;

				if (nCur == nAmountOfPackets - 1)
				{
					(nLastUsedPacketBytes == 0) ? (nLastUsedPacketBytes = PACKET_SIZE) : (pDataBuffer->nBytesToBeSent = nLastUsedPacketBytes);
					nAmountOfBytesToBeWritten = nLastUsedPacketBytes;
				}

				memcpy(&pDataBuffer->cStorage[0], &szDataBlock[nPacketOffset], nAmountOfBytesToBeWritten);
				nPacketOffset += PACKET_SIZE;
				dataWrittenEvent.fire_signal();
				
				dataAccessMutex.unlock();


				if (!dataReadEvent.get_signal())
					return LOCAL_SOCKET_ERROR;

				if (CheckForDisconnection())
					return LOCAL_SOCKET_ERROR;
			}			

			return (nSizeOfBlock);
	}

	return LOCAL_SOCKET_ERROR;
}