#include <windows.h>                        /* Windows Main-Include         */
#include <winioctl.h>                       /* IOCTL Definitions            */
#include <stdio.h>                          /* Standard I/O                 */
#include <string.h>                          /* Standard I/O                 */
#include <sys\stat.h>

unsigned long sumbytes_recv = 0;
unsigned long sumbytes_send = 0;

int wsock_attach (char *IpAddr,int PORTNR)
{
  WSADATA sWData;
  struct hostent* pHost;
  struct sockaddr_in sMyAddr;
  struct sockaddr_in sSrvAddr;
  char logbuff[256];
  int iSock=0;

  WSAStartup(0x202, &sWData);

  iSock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
  if(iSock == INVALID_SOCKET)
  {
    WSACleanup();
    sprintf(logbuff,"socket() failed\n");
    return 0;
  }

  sMyAddr.sin_family = AF_INET;
  sMyAddr.sin_port = 0;
  sMyAddr.sin_addr.s_addr = INADDR_ANY;

  if(bind(iSock,(struct sockaddr*)&sMyAddr,sizeof(sMyAddr)))
  {
    WSACleanup();
    closesocket(iSock);
    sprintf(logbuff,"bind() failed\n");
    return 0;
  }

  sSrvAddr.sin_family = AF_INET;
  sSrvAddr.sin_port = htons((short)PORTNR);
  sSrvAddr.sin_addr.s_addr = inet_addr(IpAddr);

  if(sSrvAddr.sin_addr.s_addr == 0xFFFFFFFF)
  {
    pHost = gethostbyname(IpAddr);
    if(!pHost || pHost->h_addrtype != AF_INET)
    {
      closesocket(iSock);
      WSACleanup();
      sprintf(logbuff,"unable to resolve %s\n", IpAddr);
      return 0;
    }
    sSrvAddr.sin_addr.s_addr = *(unsigned long*)pHost->h_addr_list[0];
  }

  if(connect(iSock,(struct sockaddr*)&sSrvAddr,sizeof(sSrvAddr)))
  {
    closesocket(iSock);
    WSACleanup();
    sprintf(logbuff,"connect() failed\n");
    return 0;
  }
  return iSock;
}

DWORD wsock_detach (int iSock)
{
  closesocket(iSock);
  WSACleanup();
  return TRUE;
}

int wsock_recv (int isock,char *buff, int len)
{
  int rc;

  rc = recv (isock,buff,len,0);
  sumbytes_recv += rc;
  return (rc);
}

int wsock_send (int isock,char *buff, int len)
{
  int rc;

  rc = send (isock,buff,len,0);
  sumbytes_send += rc;
  return (rc);
}

unsigned long wsock_send_bytes (void)
{
  return (sumbytes_send);
}

unsigned long wsock_recv_bytes (void)
{
  return (sumbytes_recv);
}



/*
#int recv_ready(int Socket)
#{
#  fd_set SocketSet;
#  timeval TimeOut = { 0, 0 };
#  int Result;
#
#  FD_ZERO(&SocketSet);
#  FD_SET(Socket, &SocketSet);   // <Socket> dem Set hinzufügen
#
#  return (select(0, &SocketSet, 0, 0, &TimeOut) > 0);
#}
#
#
#// Daten von <Socket> empfangen wenn verfügbar
#// <TimeOutMS> Millisekunden warten wenn nötig, kann auch 0 sein
#// Alle weiteren Parameter und Rückgabewert wie bei recv()
#
#int recv_with_timeout(int Socket, char* Buff, int Len, int Flags, int TimeOutMS)
#{
#  fd_set SocketSet;
#  timeval TimeOut = { 0, 0 };
#  int Result;
#
#  TimeOut.tv_sec = (TimeOutMS / 1000);    // <TimeOutMS> in Sekunden/Mikrosekunden umrechnen
#  TimeOut.tv_usec = (TimeOutMS % 1000) * 1000;
#
#  FD_ZERO(&SocketSet);
#  FD_SET(Socket, &SocketSet);   // <Socket> dem Set hinzufügen
#
#  // Warten, bis ein Socket aus <SocketSet> Daten empfangen hat oder <TimeOut> verstrichen ist
#  Result = select(0, &SocketSet, 0, 0, &TimeOut);
#
#  if(Result > 0)
#  {
#    return recv(Socket, Buff, Len, Flags);
#  }
#  else
#  {
#    return Result; // Mögliche Werte sind 0 bei Timeout und SOCKET_ERROR bei Fehler
#  }
#}
#
#
#
##########################################################
#
#
#fd_set SocketSet;             // Ein Set kann einen oder mehrere Sockets enthalten
#timeval TimeOut = { 0, 0 };   // Timeout in Sekunden, Mikrosekunden
#
#FD_ZERO(&SocketSet);          // Set initialisieren
#FD_SET(Socket, &SocketSet);   // <Socket> dem Set hinzufügen
#
#// Warten, bis ein Socket aus <SocketSet> Daten empfangen hat oder <TimeOut> verstrichen ist
#int Result = select(0, &SocketSet, 0, 0, &TimeOut);
#
#if(Result == SOCKET_ERROR)
#{
#  // Fehler aufgetreten.
#}
#else if(Result == 0)
#{
#  // <TimeOut> verstrichen, keiner der Sockets in <SocketSet> enthält Daten.
#}
#else if(Result > 0)
#{
#  // <Result> gibt an, wieviele Sockets in <SocketSet> Daten enthalten.
#
#  // Nur die betreffenden Sockets sind noch in <SocketSet> enthalten.
#
#  // Mit FD_ISSET(Socket, &SocketSet) kann überprüft werden ob <Socket>
#  // immer noch in <SocketSet> enthalten ist, also Daten empfangen hat.
#
#  // Wenn wie oben nur ein Socket dem Set hinzugefügt wurde, kann man sich
#  // diese Prüfung schenken :-)
#}

*/

