#include "StdAfx.h"
#include "Csock_cl.h"
#include "utiles_dll.h"
#include "_error.h"
#include "utl.h"
//***********************************************************************************************
Csock_cl::Csock_cl(BOOL*sal/*=NULL*/, C_error*e/*=NULL*/ )
{
	creado = false;
	buf=NULL;
	nb=mb=0;
	time_sleep=1;
	intentos=500;
	//creamos log error--------------
	if (e)
	{
		borra_er=FALSE;
		er=e;
	}
	else
	{
		borra_er=TRUE;
		er=new C_error();
	}
	//ponemos pirate---------------
	if(sal)
	{
		pirate=sal;
		borra_pirate=FALSE;
	}
	else
	{
		pirate=new BOOL();
		borra_pirate=TRUE;
	}
	
}

//***********************************************************************************************
Csock_cl::~Csock_cl(void)
{
	if (pirate&&borra_pirate)
		free(pirate);
	if (buf)
		free(buf);
	if (borra_er && er)
		delete er;
}
//***********************************************************************************************
BOOL Csock_cl::Create( UINT puerto, int tipo, long eventos ,LPCTSTR ip)
{
	//AFX_MANAGE_STATE(AfxGetStaticModuleState());
	Cutiles_dll dll;
	BOOL resul=CAsyncSocket::Create(puerto, tipo,eventos,ip);
	if (!resul)
	{
		er->pon_win(MODULO_CSOCK_CL);
	}
	else 
		creado =true;
	return resul;
}
//***********************************************************************************************
BOOL Csock_cl::conectar(char *ipdot,int puerto)
{
	Cutiles_dll dll;
	//AFX_MANAGE_STATE(AfxGetStaticModuleState());
	fd_set rfds;
	struct timeval tv;
	FD_ZERO(&rfds);
	FD_SET(this->m_hSocket, &rfds);
	tv.tv_sec = 5;
	tv.tv_usec = 0;
	int err,vez;
	CString cstr;
	if(!creado && ! Create())
		return FALSE;

	if (Connect(ipdot, puerto))
	{
		err = GetLastError();
		if(err != WSAEWOULDBLOCK)
		{
			er->pon_win(MODULO_CSOCK_CL);
			return(FALSE);
		}
	}

	//vemos que realmente este conectado
	vez = 0;
	while (!*pirate)
	{ 
		int pruebaconexion = select((int)this->m_hSocket+1, NULL, &rfds, NULL, &tv); 
		if(pruebaconexion == 1)  
			break;    
		else if(pruebaconexion == SOCKET_ERROR && vez>20)     
		{
			er->pon_win(MODULO_CSOCK_CL);
			return FALSE;
		}
		vez++;
		Sleep(time_sleep);
		if (vez > intentos)	
		{
			er->pon(MODULO_CSOCK_CL,"conectar:Demasiado tiempo esperando");
			return FALSE;
		}
	} 
	if(*pirate)
	{
		er->pon(MODULO_CSOCK_CL,"conectar: Solicitud de salida activado");
		return FALSE; 
	}
	return TRUE;
}
//***********************************************************************************************
BOOL Csock_cl::recibe_package(int indice)
{
	nb=indice;//bytes recibidos;
	int bp=0;//bytes del bloque;

	//pillamos cabezera------------------------------------------------
	if (!recibe((BYTE*)&cab,sizeof(Package_head_0)))
		return FALSE;
	//verificamos------------------------------------------------------
	if(cab.version!=VERSION_PACKAGE_HEAD)
	{
		er->pon(MODULO_CSOCK_CL,"recibe_package:Versión de paquete recibido no compatible");
		return FALSE;
	}
	cuida_buf(cab.nb);
	//miramos si es un paquete----------------------------------------
	if(cab.n==1)
	{
		if (!recibe((BYTE*)&buf[nb],cab.nb))
			return FALSE;//error al parte
		nb+=cab.nb;
	}
	else
	{
		//pillamos partes---------------------------------------------
		for (int i=0; i<cab.n; i++)
		{
			//pillamos numero-----------------------
			if (!recibe((BYTE*)&bp,sizeof(int)))
				return FALSE;//error al pillar numero
			//verificamos---------------------------
			if (nb+bp>mb)
			{
				er->pon(MODULO_CSOCK_CL,"recibe_package:Paquete defectuoso, tamaño muy grande");
				return FALSE;//no entra en buffer
			}
			//pillamos parte------------------------
			if (!recibe((BYTE*)&buf[nb],bp))
				return FALSE;//error al parte
			nb+=bp;
		}
	}
	//verificamos-----------------------------------------------------
	if(cab.nb!=nb-indice)
	{
		er->pon(MODULO_CSOCK_CL,"recibe_package:Paquete defectuoso, tamaño incorrecto");
		return FALSE;//no coinciden bytes
	}
	//desencriptamos si hace falta------------------------------------
	if (cab.flags & FLAG_PACKAGE_HEAD_0_ENCRIPT1)
	{
		Cutl::descifra1(&buf[indice],cab.nb);
	}
	return TRUE;
}
//***********************************************************************************************
void Csock_cl::cuida_buf( int n )
{
	if (nb+n>=mb)
	{
		//necesitamos memoria------------------------------------------
		mb+=n;
		if (buf)
			buf=(BYTE*)malloc(mb);
		else
			buf=(BYTE*)realloc(buf,mb);
	}
}
//***********************************************************************************************
BOOL Csock_cl::envia_package( BYTE* buff, int n,int encrip )
{
	int env=0;
	int en=0;
	//rellenamos cabecera----------------------
	Package_head_0 cb;
	cb.nb=n;
	cb.flags=0;
	if (encrip==1)
	{
		cb.flags=cb.flags | FLAG_PACKAGE_HEAD_0_ENCRIPT1;
		Cutl::cifra1(buff,n);
	}
	
	cb.version=VERSION_PACKAGE_HEAD;
	
	//calculamos bloques---------------------------------
	cb.n=(n/MAX_LONG_PACKAGE_0)+1;
	cb.nb=n;
	//enviamos cabecera----------------------------------
	if(!envia((BYTE *)&cb,sizeof(cb)))
	{
		return FALSE;//error al enviar cabecera
	}
	//enviamos en uno si se puede------------------------
	if (cb.n==1)
	{
		if (!envia(buff,cb.nb))
		{
			return FALSE;//error al enviar paquete
		}
		env=cb.nb;
	}
	else
	{
		//enviamos en bloques-----------------------------
		for (int i=0; i<cb.n&&!*pirate;i++)
		{
			//calculamos tamaño envio
			en=n-env;
			if (en>MAX_LONG_PACKAGE_0)
				en=MAX_LONG_PACKAGE_0;
			//enviamos numero-----------------------------
			if (!envia((BYTE*)&en,sizeof(int)))
			{
				return FALSE;//error al tamaño
			}
			//enviamos datos------------------------------
			if (!envia(&buff[env],en))
			{
				return FALSE;//error al enviar datos
			}
			env+=en;
		}
	}
	if (*pirate)
	{
		er->pon(MODULO_CSOCK_CL,"envia_package: Solicitud de salida activado");
		return FALSE;
	}
	//verificamos----------------------------------------
	return env==n;
}
//***********************************************************************************************
BOOL Csock_cl::recibe( BYTE*b, int n )
{
	//int n,k,nv,err;
	CString s;
	int rec=0, rec_a=0,ier,nv=0;//bytes recibidos
	
	while (!*pirate && rec<n)
	{
		rec_a = Receive(&b[rec],n - rec,0);
		if (rec_a < 0)
		{
			ier = GetLastError();
			if( ier != WSAEWOULDBLOCK )
			{
				er->pon_win(MODULO_CSOCK_CL);
				return(FALSE);
			}
			nv++;
			if (nv > intentos)
			{
				er->pon(MODULO_CSOCK_CL,"Recibe: Demasiado tiempo esperando");
				return FALSE;
			}
			Sleep(time_sleep);
		}
		else if (rec_a == 0)
		{
			er->pon(MODULO_CSOCK_CL,"Recibe: Socket desconectado");
			return(FALSE);
		}
		else
		{
			rec+=rec_a;
			nv = 0;
		}

	} 

	if(*pirate) 
	{
		er->pon(MODULO_CSOCK_CL,"Recibe: Solicitud de salida activado");
		return FALSE;  
	}
	return TRUE;
}
//***********************************************************************************************
BOOL Csock_cl::envia( BYTE*buff, int n)
{
	//int ns,nv,err,ib;
	int nv=0,env=0,env_a=0,ier;
	//nv = ib = 0;

	while (!*pirate && n>env)
	{
		//enviamos-------------------------------------------
		env_a = Send(&buff[env],n-env,0);
		
		if(env_a <= 0)
		{
			//analizamos el fallo----------------------------
			ier = GetLastError();
			if (ier != WSAEWOULDBLOCK)
			{
				er->pon_win(MODULO_CSOCK_CL);
				return(FALSE);
			}
			//toca esperar-----------------------------------
			if (nv > intentos)
			{
				er->pon(MODULO_CSOCK_CL,"Envia: Demasiado tiempo esperando");
				return(FALSE);
			}
			nv++;
			Sleep(time_sleep);
		}
		else
		{
			env+=env_a;
			nv=0;
		}
	}
	if(*pirate)
	{
		er->pon(MODULO_CSOCK_CL,"Envia: Solicitud de salida activado");
		return FALSE;
	}

	return TRUE;
}
//***********************************************************************************************