#include "stdafx.h"


extern "C" {
	__declspec(dllexport) void  dsInit(char* host, int port);
	__declspec(dllexport) int   dsRegister(char* data_source);
	__declspec(dllexport) char* dsGetNext(int data_idx);
	__declspec(dllexport) char* dsGetKeyed(int data_idx, char *key);
	__declspec(dllexport) char* dsGetIndexed(int data_idx, char *index);
	__declspec(dllexport) void  dsStore(int data_idx, char *data);
	__declspec(dllexport) void  get_buffered( int data_idx, char* buf, int buflen);
}
//------------------------------------------------------------------------

#include <string.h>
#include <winsock.h>

//------------------------------------------------------------------------

#define TCP            "tcp"

//------------------------------------------------------------------------

char *recv_host       = "localhost";
char *recv_service    = "dserver";

unsigned long    host_address;
int     port          = 9578;
SOCKET  sock;

//--------------------------------------------------------------------

void  dsInit(void);
int   dsRegister(char*);
char* dsGetNext(int data_idx);
char* dsGetKeyed(int data_idx, char *key);
char* dsGetIndexed(int data_idx, int row_index);
void  dsStore(int data_idx, char *data);

char* sock_send(char*);


//------------------------------------------------------------------------

char* sock_send(char *buf, int size)
{
  int n;

   //fprintf(stderr, "[sock_send] buf = \"%s\"\n\n", buf);
   
   n = send(sock, buf, (int)strlen(buf), 0);

   if (n == SOCKET_ERROR)
   {
      printf("[dcl::sock_send] send() failed (errno %d)", errno);
      closesocket(sock);	
      exit(5);
   }

   if ((n = recv(sock, buf, size, 0)) == 0) {
         exit(6);
   }
   
   buf[n] = '\0';

   //fprintf(stderr, "\nbuf -> \"%s\"\n", buf); 

   return buf;
}  // sock_send

//--------------------------------------------------------------------

void dsInit(char *host, int port)
{
	int ierr;
    int rc;

    WSADATA               wsaData;
	LPHOSTENT            lpHostEntry;
	// LPSERVENT            lpServEnt;
	SOCKADDR_IN          saServer;

	        printf("dsInit\n"); 

	WORD wVersionRequested = MAKEWORD(1,1);

    struct in_addr *pinAddr;   // Pointer to an internet address

    // Initialize WinSock.dll

    if (rc = WSAStartup(wVersionRequested, &wsaData))
    {
        printf("WSAStartup() error: %d\n", rc); 
        WSACleanup();
        return;
    }

    // Check WinSock version

    if (wVersionRequested != wsaData.wVersion)
    {
        printf("\nWinSock version 1.1 not supported\n");
        WSACleanup();
        return;
    }

	u_short                b0, b1, b2, b3;

	fprintf(stderr, "recv_host = \"%s\"\n", recv_host);

	if ((lpHostEntry = gethostbyname(host)) == (LPHOSTENT)0 ) {
		printf("gethostbyname() call failed\n");
		exit(0);
	}

	b0 = *(lpHostEntry->h_addr_list[0] + 0) & 0xff;
	b1 = *(lpHostEntry->h_addr_list[0] + 1) & 0xff;
	b2 = *(lpHostEntry->h_addr_list[0] + 2) & 0xff;
	b3 = *(lpHostEntry->h_addr_list[0] + 3) & 0xff;

	host_address  = (b0 << 24) + (b1 << 16) + (b2 <<  8) + b3;

	printf("      name: %s\n",  lpHostEntry->h_name);
	printf("      type: %d\n",  lpHostEntry->h_addrtype);
	printf("     alias: %s\n", *lpHostEntry->h_aliases);
	printf("    length: %d\n",  lpHostEntry->h_length);
	printf("IP Address: %d.%d.%d.%d\n", b0 & 0xff, b1 & 0xff, b2 & 0xff, b3 & 0xff);

	pinAddr = ((LPIN_ADDR)lpHostEntry->h_addr_list[0]);

	host_address = (unsigned long)*lpHostEntry->h_addr_list[0];

    printf("Host address: %s\n", inet_ntoa(*pinAddr));
	printf("Got address 0x%08x\n", host_address);
	printf("Using  port %d\n", port);

	if ((sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == INVALID_SOCKET) {
		printf("[dcl::init] socket() failed (errno %d)", errno);
		exit(3);
	}

	/*
	// Find the port number for the HTTP service on TCP
	//

	lpServEnt = getservbyname("http", "tcp");
	if (lpServEnt == NULL)
		saServer.sin_port = htons(80);
	else
		saServer.sin_port = lpServEnt->s_port;

		*/

	fprintf(stderr, "@@@ socket fd = %d\n", sock );

	// memcpy(&saServer.sin_addr.s_addr, lpHostEntry->h_addr, lpHostEntry->h_length);
	saServer.sin_family      = AF_INET;
	saServer.sin_port        = htons(port);
	saServer.sin_addr        = *((LPIN_ADDR)*lpHostEntry->h_addr_list);

	if ((ierr = connect(sock, (LPSOCKADDR)&saServer, sizeof(SOCKADDR_IN))) == -1) {
		printf("[initiateConnection] connect() failed (errno %d)", errno);
		closesocket(sock);
		exit(4);
	}

	fprintf(stderr, "connected\n");

}  // dsInit

//------------------------------------------------------------------------

int dsRegister(char *data_source)
{
	char  buf[1024];
	char *reply;

	sprintf_s(buf, 1024, "REG|%s", data_source);

	reply = sock_send(buf, 1024);

	return atoi(reply);
}  // dsRegister

//------------------------------------------------------------------------

char* dsGetNext(int data_idx)
{
	char  buf[1024];
	char *reply;

	sprintf_s(buf, 1024, "GETN|%d", data_idx);

    reply = sock_send(buf, 1024);

    printf("data -> \"%s\"\n", reply);

	return reply;
}  // dsGetNext

//------------------------------------------------------------------------

char* dsGetKeyed(int data_idx, char *key)
{
	char  buf[1024];
	char *reply;

	sprintf_s(buf, 1024, "GETK|%d|%s", data_idx, key);

    reply = sock_send(buf, 1024);

    printf("data -> \"%s\"\n", reply);

	return reply;
}  // dsGetKeyed

//------------------------------------------------------------------------

char* dsGetIndexed(int data_idx, int index)
{
	char  buf[1024];
	char *reply;

	sprintf_s(buf, 1024, "GETI|%d|%d", data_idx, index);

    reply = sock_send(buf, 1024);

    printf("data -> \"%s\"\n", reply);

	return reply;
}  // dsGetIndexed

//------------------------------------------------------------------------

void dsStore(int data_idx, char *data)
{
	char  buf[1024];
	char *reply;

	sprintf_s(buf, 1024, "STOC|%d|%s", data_idx, data);

    reply = sock_send(buf, 1024);

    printf("data -> \"%s\"\n", reply);
}  // dsStore

//------------------------------------------------------------------------

void get_buffered(int data_idx, char* buf, int buflen)
{
	strncpy_s(buf, buflen, "1,2,3,4", buflen);
	buf[buflen-1]='\0';
}
//------------------------------------------------------------------------
