/*   
SCOL sockets - windows  . Magma 1.0 . 1996 . Sylvain HUET

  socket.c : routines sockets bas-niveau
*/
// Modifications History
//
//$ LB(20/06/2001): Modify function SCKconnect : replace old socks4 protocol by SOCKSconnect function call 
//                  in order to manage socks4 and socks5
//$ FA(06/08/2001): Modify include of mbytec.h to vm/mbytec.h
//$ FA(30/08/2001): Set no delay option (TCP_NODELAY) (commented out)
//

#include <stdio.h>
#include <string.h>
#include <time.h>

//$BLG - v5.3.01: Modif
//#include <winsock.h>
#include <winsock2.h>

#include <windows.h>
#include "common/common.h"
#include "common/socket.h"
#include "scolMMemory.h"
#include "vm/mbytec.h"
#include "OS_specific/windows/winscol.h"
#include "common/socks.h"

#include <wininet.h>

int socklife;
int sockudp;
int STDPORT=1200;

int localscolIP;
char szHost[256];
char achHostInfo[MAXGETHOSTSTRUCT];

int proxyIp;
int proxyPort;
int proxyMask;

int hostIPtab[32];
int nbIPtab;

int testconnect (int ip)
{
	if ((localscolIP==(int)inet_addr("127.0.0.1"))&&(ip!=localscolIP)) return 0;
	return 1;
}

int SCKbindadress()
{
#ifdef SERVER
  if (forcedIP[0]) return inet_addr(forcedIP);
#endif
  return INADDR_ANY;
}

int SCKlocalconnection()
{
#ifdef SERVER
  if (forcedIP[0]) return inet_addr(forcedIP);
#endif
  return inet_addr("127.0.0.1");
}

/* 2 fonctions mises pour compatibilite unix */
int SCKclrwrite(int s)
{
    return 0;
}

int SCKsetwrite(int s)
{
    return 0;
}


int SCKtestLife()
{
	char bf[8];
	int res;
	
	if (socklife==-1) return 0;
    res=recv((SOCKET)socklife,bf,4,MSG_PEEK);
    if (res<0)
	{
		if (WSAGetLastError()!=WSAEWOULDBLOCK) res=-1;
		else res=0;
	}
    else if (res==0) res=-1;
	if (res<0)
	{
		MMechostr(MSKRUNTIME,"\n\nBroken LifeSocket\n");
		EndScolMachine(0);
		return -1;
	}
	return 0;
}

int flaggethost;

/*
int hostnameWin(char *name,int size)
{
int n;
HKEY key;

  return -1;
  if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,"System\\CurrentControlSet\\Services\\VxD\\MSTCP",0,KEY_ALL_ACCESS,&key)
		!=ERROR_SUCCESS) return -1;
		n=size;
		if (RegQueryValueEx(key,"HostName",0,NULL,name,&n)!=ERROR_SUCCESS)
		{
		name[0]=0;
		return -1;
		}
		if (name[0]==0) return -1;
		return 0;
		}
*/
int myhostname(char *name,int size)
{
	if (name[0]) return 0;
	//$BLG - v5.11: Modif
	//MMechostr(MSKFOO,"BSD request\n");
	MMechostr(MSKFOO,"Requesting hostname ..\n");
	if (gethostname(name,size)==SOCKET_ERROR)
	{
		name[0]=0;
		return -1;
	}
	return 0;
}

int SCKstarthostname(HWND h)
{
	time_t timep;
	struct tm *res;

	//$BLG - v5.21: Add
	MMechostr(MSKFOO, "\n> Retrieving local host informations\n");
	
	time(&timep);
	res=localtime(&timep);
	if (res) MMechostr(MSKFOO,"Date: %d-%02d-%02d %02d-%02d-%02d\n", res->tm_year+1900, res->tm_mon+1, res->tm_mday, res->tm_hour, res->tm_min, res->tm_sec);
	if ((!flaggethost)&&(!myhostname(szHost,256)))
	{
		MMechostr(MSKFOO,"Hostname: %s\n",szHost);
		flaggethost=1;
		WSAAsyncGetHostByName(h,WSA_GETHOST,szHost,achHostInfo,MAXGETHOSTSTRUCT);
	}
	return 0;
}

int SCKendhostname(LONG lParam)
{
	int i;
  
  //$BLG - v5.21: Del (Unappropriate msg)
  //MMechostr(MSKFOO,">>resultat gethostbyname\n");
  
  SCKgethostIP(lParam);
	//MMechostr(MSKFOO,"Local IP = %s\n",inet_ntoa(*(struct in_addr*)&localscolIP));
	
	for(i=0;i<nbIPtab;i++) MMechostr(MSKFOO,"HostIP: %d:%s\n",i,inet_ntoa(*(struct in_addr*)&hostIPtab[i]));
	flaggethost=0;
	
	return 0;
}

/* initialisation des sockets windows
definition de la fenetre devant recevoir les evenements reseau
lancement de la recherche de l'adresse IP locale 
retourne 0 si OK */
int SCKinit(HWND h)
{
	WORD wVersionRequested;
	WSADATA wsaData;
	
	hscol=h;
	
	//$BLG - v5.3.01: Modif
	//wVersionRequested = MAKEWORD( 1, 1 );
	wVersionRequested = MAKEWORD( 2, 2);
	
	MMechostr(MSKDEBUG,"\n> WSA Startup: Initializing Windows sockets\n");
	if (WSAStartup( wVersionRequested, &wsaData )) return -1;
	SCKloopbackIP();
	szHost[0]=0;
	nbIPtab=0;
	proxyIp=0;
	flaggethost=0;
	SCKstarthostname(h);
	sockudp=-1;
	return 0;
}

/* fin d'utilisation des sockets windows
retourne toujours 0 */
int SCKend()
{
	WSACleanup();
	return 0;
}

/* regle le proxy (ip="0.0.0.0" -> pas de proxy) */
int SCKsetproxy(char *ip, char *port,char *mask)
{
	struct hostent *hp;
	if (ip)
	{
		if ((proxyIp=inet_addr(ip))==INADDR_NONE)
		{
			if ((hp=gethostbyname(ip))) proxyIp=*((int *) (hp->h_addr));
			else proxyIp=0;
		}
	}
	else proxyIp=0;
	if (port) proxyPort=atoi(port);
	if (mask) proxyMask=inet_addr(mask);
	return 0;
}

/* definit l'adresse IP locale comme loopback */
int SCKloopbackIP()
{
    localscolIP=inet_addr("127.0.0.1");
	hostIPtab[0]=localscolIP;
	nbIPtab=1;
    return localscolIP;
}

/* definit l'adresse IP locale a partir du resultat de WSAAsyncGetHostByName */
int SCKgethostIP(LONG lParam)
{
	int i;
	u_long **p;
	
    if (WSAGETASYNCERROR(lParam)) return SCKloopbackIP();
    localscolIP=(int)*((u_long FAR*)(((struct hostent FAR*)achHostInfo)->h_addr));
    if (localscolIP==0) return SCKloopbackIP();
	
	p=(u_long**)((struct hostent FAR*)achHostInfo)->h_addr_list;
	i=0;
	while((p[i])&&(i<32))
	{
		hostIPtab[i]=*(p[i]);
		i++;
	}
	nbIPtab=i;
    return localscolIP;
}

/*retourne le nombre d'adresses IP locales */
int SCKgetnbIP()
{
	return nbIPtab;
}

/*retourne la i-eme adresse IP locale */
int SCKgetnthIP(char *buf,int i)
{
	struct in_addr Addr;
	if ((i<0)||(i>=nbIPtab))
		buf[0]=0;
	else
	{
		Addr.s_addr=hostIPtab[i];
		strcpy(buf,inet_ntoa(Addr));
	}
	return 0;
}

char *SCKhostname(char *buf)
{
	if (gethostname(buf,256)) strcpy(buf,"localhost");
	return buf;
}

char *SCKhostIP(char *buf)
{
	struct in_addr Addr;
	
	Addr.s_addr=localscolIP;
	strcpy(buf,inet_ntoa(Addr));
	return buf;
}

char *SCKgetstringbyip(char *buf,int ip,int port)
{
	struct in_addr Addr;
	
	Addr.s_addr=ip;
	sprintf(buf,"%s:%d",inet_ntoa(Addr),port);
	return buf;
}

char *SCKgetstringbyip2(char *buf,int ip)
{
	struct in_addr Addr;
	
	Addr.s_addr=ip;
	sprintf(buf,"%s",inet_ntoa(Addr));
	return buf;
}

char *SCKgethostbyname(char *buf,char *name)
{
	struct hostent *hp;
	struct in_addr Addr;
	
	if (testconnect(0)==0)
	{
		MMechostr(MSKDEBUG,"do not perform gethostbyname\n");
		return NULL;
	}
	
	hp = gethostbyname(name);
	if (hp==NULL) return NULL;
	Addr.s_addr=*((int *) (hp->h_addr));
	sprintf(buf,"%s",inet_ntoa(Addr));
	return buf;
}

char *SCKgetnamebyIP(char *buf,char *IP)
{
	struct hostent *h;
	int k;
	char *p;
	
	if (testconnect(0)==0)
	{
		MMechostr(MSKDEBUG,"do not perform gethostbyaddr\n");
		return NULL;
	}
	
	k=inet_addr(IP);
	p=(char*)&k;
	h=gethostbyaddr(p,4,AF_INET);
	if (h==NULL) return NULL;
	strcpy(buf,h->h_name);
	return buf;
}

/* definit le serveur associe a la machine scol
retourne le descripteur de socket si succes
retourne un code negatif si erreur */
int SCKstartserver(int port)
{
  SOCKADDR_IN ina;
  SOCKET socksrv;
	//int nodelay = 1;
	//$BLG: v4.6a5 - Add 
	int ret;
  //$BLG - v5.11: Add
  int sockbufsize = 0;
  int size = sizeof(int);
  int newsize = 65536;
	
  socksrv = socket(PF_INET,SOCK_STREAM,0);
  if (socksrv == INVALID_SOCKET) return -1;

  //$BLG - v5.11: Add
  //MMechostr(0,"$BLG - SCKstartserver: Socket creation - Buffers' information\n");
  //getsockopt(socksrv, SOL_SOCKET, SO_SNDBUF, (char *)&sockbufsize, &size);
  //MMechostr(0,"SND: %d\n", sockbufsize);
  //getsockopt(socksrv, SOL_SOCKET, SO_RCVBUF, (char *)&sockbufsize, &size);
  //MMechostr(0,"RCV: %d\n", sockbufsize);
  //MMechostr(0,"$BLG - Increasing socket buffers to 64Ko\n");
  setsockopt(socksrv, SOL_SOCKET, SO_SNDBUF, (char *)&newsize, (int)sizeof(newsize));
  setsockopt(socksrv, SOL_SOCKET, SO_RCVBUF, (char *)&newsize, (int)sizeof(newsize));
  //MMechostr(0,"$BLG - Checking\n");
  //getsockopt(socksrv, SOL_SOCKET, SO_SNDBUF, (char *)&sockbufsize, &size);
  //MMechostr(0,"SND: %d\n", sockbufsize);
  //getsockopt(socksrv, SOL_SOCKET, SO_RCVBUF, (char *)&sockbufsize, &size);
  //MMechostr(0,"RCV: %d\n", sockbufsize);
  //MMechostr(0,"$BLG - Done\n");
	
  //$ FA(30/08/2001)
  //setsockopt(socksrv, IPPROTO_TCP, TCP_NODELAY, (const char*)&nodelay, sizeof(int));
	
  if (WSAAsyncSelect(socksrv, hscol, WSA_ASYNC, (FD_ACCEPT|FD_READ|FD_WRITE|FD_CLOSE)) == SOCKET_ERROR)
	{
		closesocket(socksrv);
		return -1;
	}
	
  ina.sin_family = PF_INET;
  ina.sin_port   = htons((unsigned short)port);
  ina.sin_addr.s_addr = SCKbindadress();
	
  if (bind(socksrv,(struct sockaddr*)&ina,sizeof(ina))!=0)
	{
	  MMechostr(MSKDEBUG,"Tcp port %d busy\n",port);
	  //$BLG: v4.6a5 - Added debug
	  ret = WSAGetLastError();
	  if (ret == WSANOTINITIALISED) MMechostr(0, "WSANOTINITIALISED\n");
	  else if (ret == WSAENETDOWN) MMechostr(0, "WSAENETDOWN\n");
	  else if (ret == WSAEACCES) MMechostr(0, "WSAEACCES\n");
	  else if (ret == WSAEADDRINUSE) MMechostr(0, "WSAEADDRINUSE\n");
	  else if (ret == WSAEADDRNOTAVAIL) MMechostr(0, "WSAEADDRNOTAVAIL\n");
	  else if (ret == WSAEFAULT) MMechostr(0, "WSAEFAULT\n");
	  else if (ret == WSAEINPROGRESS) MMechostr(0, "WSAEINPROGRESS\n");
	  else if (ret == WSAEINVAL) MMechostr(0, "WSAEINVAL\n");
	  else if (ret == WSAENOBUFS) MMechostr(0, "WSAENOBUFS\n");
	  else if (ret == WSAENOTSOCK) MMechostr(0, "WSAENOTSOCK\n");
	  else MMechostr(0, "UNDEFINED\n");
	  //$BLG: End
		closesocket(socksrv);
		return -2;
	}
  
  if (listen(socksrv,3)!=0)
	{
	  MMechostr(MSKDEBUG,"Tcp port %d listen error\n",port);
		closesocket(socksrv);
		return -3;
	}

  MMechostr(MSKDEBUG,"create Tcp server %d on %d\n",socksrv,port);
  return (int)socksrv;
}

/* acceptation d'une liaison de type serveur
retourne le descripteur de socket si succes
retourne un code negatif si erreur */
int SCKaccept(int s,int *ip,int *port)
{
    SOCKADDR_IN cor;
    SOCKET ns;
    int sizecor;
	
    sizecor=sizeof(cor);
    ns=accept(s,(struct sockaddr*)&cor,&sizecor);
    if (ns==INVALID_SOCKET) return -1;
    *ip=cor.sin_addr.s_addr;
    *port=ntohs(cor.sin_port);
    return (int)ns;
}


int cutaddr(char *addr, char *buf)
{
    while(((*addr)!=':')&&(*addr)) *(buf++)=*(addr++);
    *buf=0;
    if ((*addr)!=':') return -1;
    return atoi(&addr[1]);
}

/* creation d'une liaison de type client
retourne le descripteur de socket si succes
retourne un code negatif si erreur */
int SCKconnect(char *addr,int *ip,int *prt,int *proxy)
{
  SOCKADDR_IN ina;
  SOCKET s;
  int port,x;
  char buf[256];
  //int nodelay = 1;
  //$BLG - v5.11: Add
  int sockbufsize = 0;
  int size = sizeof(int);
  int newsize = 65536;  

    if (strlen(addr)>256) return -1;
    port=cutaddr(addr,buf);
    if (port==-1) return -1;
    if (buf[0]==0) x=SCKlocalconnection();
    else x=inet_addr(buf);
    
    MMechostr(MSKDEBUG,"CONNECT %s (%x):%x\n",buf,x,port);
	
	if (testconnect (x)==0)
	{
		MMechostr(MSKDEBUG,"do not connect\n");
		return -1;
	}
	
	s=socket(PF_INET,SOCK_STREAM,0);
  //$ FA(30/08/2001)
  //setsockopt(s, IPPROTO_TCP, TCP_NODELAY, (const char*)&nodelay, sizeof(int));
  if (s==INVALID_SOCKET) return -1;
  
  
  //$BLG - v5.11: Add
  //MMechostr(0,"$BLG - SCKconnect: Socket creation - Buffers' information\n");
  //getsockopt(s, SOL_SOCKET, SO_SNDBUF, (char *)&sockbufsize, &size);
  //MMechostr(0,"SND: %d\n", sockbufsize);
  //getsockopt(s, SOL_SOCKET, SO_RCVBUF, (char *)&sockbufsize, &size);
  //MMechostr(0,"RCV: %d\n", sockbufsize);
  //MMechostr(0,"$BLG - Increasing socket buffers to 64Ko\n");
  setsockopt(s, SOL_SOCKET, SO_SNDBUF, (char *)&newsize, (int)sizeof(newsize));
  setsockopt(s, SOL_SOCKET, SO_RCVBUF, (char *)&newsize, (int)sizeof(newsize));
  //MMechostr(0,"$BLG - Checking\n");
  //getsockopt(s, SOL_SOCKET, SO_SNDBUF, (char *)&sockbufsize, &size);
  //MMechostr(0,"SND: %d\n", sockbufsize);
  //getsockopt(s, SOL_SOCKET, SO_RCVBUF, (char *)&sockbufsize, &size);
  //MMechostr(0,"RCV: %d\n", sockbufsize);
  //MMechostr(0,"$BLG - Done\n");  
  
  
	if ((proxyIp==0)||(x==(int)SCKlocalconnection())||((proxyIp&proxyMask)==(x&proxyMask)))
	{
    if (WSAAsyncSelect(s,hscol,WSA_ASYNC,(FD_CONNECT|FD_READ|FD_WRITE|FD_CLOSE))==SOCKET_ERROR)
		{
			closesocket(s);
			return -1;
		}
		ina.sin_family = PF_INET;
		ina.sin_port   = htons((unsigned short)port);
		ina.sin_addr.s_addr = x;
		if ( (connect(s,(struct sockaddr *)&ina,sizeof(ina))!=0)
			&&(WSAGetLastError()!=WSAEWOULDBLOCK) )
		{
			closesocket(s);
			return -1;
		}
		*proxy=0;
	}
	else
	{
		MMechostr(MSKDEBUG,"using proxy %x %x\n",proxyIp,proxyMask);

		//$ LB : replace old socks4 protocol by SOCKSconnect function call from socks.c
		// which manage socks 4 and socks 5
		if (SOCKSconnect (s, x, htons((unsigned short)port)) != SOCKS_SUCCESS)
		{
			MMechostr (MSKDEBUG, "SCKconnect : error connecting socket %d\n", s);
			return -1;
		}
		else
			MMechostr (MSKDEBUG, "SCKconnect : socket %d connected\n", s);
		//

		if (WSAAsyncSelect(s,hscol,WSA_ASYNC,(FD_CONNECT|FD_READ|FD_WRITE|FD_CLOSE))==SOCKET_ERROR)
		{
			closesocket(s);
			return -1;
		}
		*proxy=0;
	}
    *ip=x;
	*prt=port;
	
    return (int)s;
}

/* definit un serveur udp
retourne le descripteur de socket si succes
retourne un code negatif si erreur */
int SCKstartudpserver(int port)
{
  SOCKADDR_IN ina;
  SOCKET socksrv;
	int un=1;
  //$BLG - v5.11: Add
  int sockbufsize = 0;
  int size = sizeof(int);
  int newsize = 65536;	
	
    socksrv=socket(PF_INET,SOCK_DGRAM,0);
    if (socksrv==INVALID_SOCKET) return -1;
	
	
	//$BLG - v5.11: Add
  //MMechostr(0,"$BLG - SCKstartudpserver: Socket creation - Buffers' information\n");
  //getsockopt(socksrv, SOL_SOCKET, SO_SNDBUF, (char *)&sockbufsize, &size);
  //MMechostr(0,"SND: %d\n", sockbufsize);
  //getsockopt(socksrv, SOL_SOCKET, SO_RCVBUF, (char *)&sockbufsize, &size);
  //MMechostr(0,"RCV: %d\n", sockbufsize);
  //MMechostr(0,"$BLG - Increasing socket buffers to 64Ko\n");
  setsockopt(socksrv, SOL_SOCKET, SO_SNDBUF, (char *)&newsize, (int)sizeof(newsize));
  setsockopt(socksrv, SOL_SOCKET, SO_RCVBUF, (char *)&newsize, (int)sizeof(newsize));
  //MMechostr(0,"$BLG - Checking\n");
  //getsockopt(socksrv, SOL_SOCKET, SO_SNDBUF, (char *)&sockbufsize, &size);
  //MMechostr(0,"SND: %d\n", sockbufsize);
  //getsockopt(socksrv, SOL_SOCKET, SO_RCVBUF, (char *)&sockbufsize, &size);
  //MMechostr(0,"RCV: %d\n", sockbufsize);
  //MMechostr(0,"$BLG - Done\n");
	
	
    setsockopt(socksrv,SOL_SOCKET,SO_BROADCAST,(char*)&un,sizeof(int));
	
	
    ina.sin_family = PF_INET;
    ina.sin_port   = htons((unsigned short)port);
    ina.sin_addr.s_addr = SCKbindadress();
	
    if (bind(socksrv,(struct sockaddr*)&ina,sizeof(ina))!=0)
	{
	    MMechostr(MSKDEBUG,"Tcp port %d busy\n",port);
		closesocket(socksrv);
		return -2;
	}
    if (WSAAsyncSelect(socksrv,hscol,WSA_ASYNC,
        (FD_ACCEPT|FD_READ|FD_WRITE|FD_CLOSE))==SOCKET_ERROR)
	{
		closesocket(socksrv);
		return -1;
	}
    MMechostr(MSKDEBUG,"create Udp server %d on %d\n",socksrv,port);
    return (int)socksrv;
}

/* creation d'une liaison de type client
retourne le descripteur de socket si succes
retourne un code negatif si erreur */
int SCKsendudp(char *addr,char *txt, int len)
{
  SOCKADDR_IN ina;
  int port,x;
  char buf[256];
	int un=1;
  //$BLG - v5.11: Add
  int sockbufsize = 0;
  int size = sizeof(int);
  int newsize = 65536;

	
    if (strlen(addr)>256) return -1;
    port=cutaddr(addr,buf);
    if (port==-1) return -1;
    if (buf[0]==0) x=SCKlocalconnection();
    else x=inet_addr(buf);
    
	if (testconnect (x)==0)
	{
		MMechostr(MSKDEBUG,"do not send udp\n");
		return -1;
	}
	
	ina.sin_family = PF_INET;
	ina.sin_port   = htons((unsigned short)port);
	ina.sin_addr.s_addr = x;

	if (sockudp==-1)
	{
		sockudp=socket(PF_INET,SOCK_DGRAM,0);
		MMechostr(MSKDEBUG,"create udp socket\n");
		if (sockudp==INVALID_SOCKET)
		{
			MMechostr(MSKTRACE,"create udp socket ERROR\n");
			return 0;
		}
		setsockopt(sockudp,SOL_SOCKET,SO_BROADCAST,(char*)&un,sizeof(int));
		
	  //$BLG - v5.11: Add
	  //MMechostr(0,"$BLG - SCKsendudp: Socket creation - Buffers' information\n");
	  //getsockopt(sockudp, SOL_SOCKET, SO_SNDBUF, (char *)&sockbufsize, &size);
	  //MMechostr(0,"SND: %d\n", sockbufsize);
	  //getsockopt(sockudp, SOL_SOCKET, SO_RCVBUF, (char *)&sockbufsize, &size);
	  //MMechostr(0,"RCV: %d\n", sockbufsize);
	  //MMechostr(0,"$BLG - Increasing socket buffers to 64Ko\n");
	  setsockopt(sockudp, SOL_SOCKET, SO_SNDBUF, (char *)&newsize, (int)sizeof(newsize));
	  setsockopt(sockudp, SOL_SOCKET, SO_RCVBUF, (char *)&newsize, (int)sizeof(newsize));
	  //MMechostr(0,"$BLG - Checking\n");
	  //getsockopt(sockudp, SOL_SOCKET, SO_SNDBUF, (char *)&sockbufsize, &size);
	  //MMechostr(0,"SND: %d\n", sockbufsize);
	  //getsockopt(sockudp, SOL_SOCKET, SO_RCVBUF, (char *)&sockbufsize, &size);
	  //MMechostr(0,"RCV: %d\n", sockbufsize);
	  //MMechostr(0,"$BLG - Done\n");		
	}
	sendto(sockudp,txt,len,0,(struct sockaddr *)&ina,sizeof(ina));
	
    return 0;
}

/* creation d'une liaison de type client
retourne le descripteur de socket si succes
retourne un code negatif si erreur */
int SCKsendudpchn(int sock,char *addr,char *txt, int len)
{
    SOCKADDR_IN ina;
    int port,x;
    char buf[256];
	
    if (strlen(addr)>256) return -1;
    port=cutaddr(addr,buf);
    if (port==-1) return -1;
    if (buf[0]==0) x=SCKlocalconnection();
    else x=inet_addr(buf);
    
	if (testconnect (x)==0)
	{
		MMechostr(MSKDEBUG,"do not sendudp\n");
		return -1;
	}
	
	
	ina.sin_family = PF_INET;
	ina.sin_port   = htons((unsigned short)port);
	ina.sin_addr.s_addr = x;
	sendto(sock,txt,len,0,(struct sockaddr *)&ina,sizeof(ina));
	
    return 0;
}

/* ferme une socket
retourne toujours 0 */
int SCKclose(int s)
{
    if (s>=0) closesocket((SOCKET)s);
    return 0;
}

/* ferme le serveur
retourne toujours 0 */
int SCKcloseserver(int s)
{
    if (s>=0) closesocket((SOCKET)s);
    return 0;
}

/* envoie un paquet de caracteres sur une socket
retourne le nombre d'octets effectivement envoyés (eventuellement 0)
retourne un code negatif si erreur autre que WouldBlock */
int SCKsend(int s,char *buf, int len)
{
  int res;
  
  //$BLG - v5.22: Add
	//int i;
	
	//$BLG - v5.22: Add
	/*
	MMechostr(0, ">SCKsend:\n");
  for (i = 0; i < len; i++)
  {
  	if (buf[i] == 0)	MMechostr(0, "%d: 0\n", i);
  }	
  */
//MMechostr(0, "%s\n", buf);
    
//MMechostr(0,"SCKsend\n");
  res=send((SOCKET)s,buf,len,0);
  if (res<0)
	{
		if (WSAGetLastError() != WSAEWOULDBLOCK) res=-1;
		else res=0;
	}
  
  //MMechostr(0,"<SCKsend\n");
  
  return res;
}


/* lit un paquet de caracteres sur une socket
retourne le nombre d'octets effectivement lus (eventuellement 0)
retourne un code negatif si erreur autre que WouldBlock */
int SCKrecv(int s,char *buf, int len,int *ip,int *port)
{
  int res;
	SOCKADDR_IN add;
	int l;
	
	//$BLG - v5.22: Add
	//int i;

//MMechostr(0,"SCKrecv\n");
//MMechostr(MSKTRACE, "=> SCKrecv(): sock = %d, len = %d\n", s, len);
	l = sizeof(add);
  res = recvfrom((SOCKET)s, buf, len, 0, (struct sockaddr *)&add, &l);
	//    res=recv((SOCKET)s,buf,len,0);
  if (res < 0)
	{
		if (WSAGetLastError() != WSAEWOULDBLOCK) res = -1;
		else res = 0;
	}
		
  else if (res == 0) res = -1;
  *ip = add.sin_addr.s_addr;
  *port = ntohs(add.sin_port);
//MMechostr(MSKTRACE, "<= SCKrecv(): res = %d\n", res);
  
	//$BLG - v5.22: Add
	/*
	MMechostr(0, ">SCKrecv:\n");
  for (i = 0; i < res; i++)
  {
  	if (buf[i] == 0)	MMechostr(0, "%d: 0\n", i);
  }
  */
  
  return res;
}


int SCKpostclose(int s)
{
//	closesocket((SOCKET)s);
//  PostMessage(hscol,WSA_ASYNC,s,FD_CLOSE);
    return 0;
}