#include <winsock2.h>
#include <af_irda.h>
#include <stdio.h>

// This service name should match the name set in the
// server program, change accordingly
#define IR_SERVICE_NAME "MIKEBLUR"
#define TEST_STRING "Sending all my love to youuu! Retard IR server!"
#define MAX_RETRIES     10
#define MAX_BUFFER      4096

//    This function attempts to locate any IR capable devices within
//    range. This is done by calling the IRLMP_ENUMDEVICES socket
//    option. We call this several times in a loop to make a good
//    effort to find any.  Upon success a DEVICELIST structure is
//    filled in with the device IDs of the discovered device.
int FindDevices(SOCKET s, DEVICELIST *devlist)
{
	int          dwNumRetries=0, dwDevListSz;
	int          ret;
	dwDevListSz = sizeof(*devlist);
	devlist->numDevice = 0;
	
	while ((devlist->numDevice == 0) && (dwNumRetries <= MAX_RETRIES))
	{
		printf("IR-Client: Retry #%d\n", dwNumRetries); 
		ret = getsockopt(s, SOL_IRLMP, IRLMP_ENUMDEVICES, (char *)devlist, &dwDevListSz);

		if (ret == SOCKET_ERROR)
		{
			printf("IR-Client: getsockopt() failed with error %d\n", WSAGetLastError());
			// return 0 indicates error
			return 0;
		}
		else
			printf("IR-Client: getsockopt() looks fine!\n");

		dwNumRetries++;
		// Sleep for a while...
		Sleep(1000);
	}
	
	if (dwNumRetries > MAX_RETRIES)
	{
		// Number of retries expired
		printf("IR-Client: Number of %d retries expired!\n", MAX_RETRIES);
		return 0;
	}
	// Else return the device number...
	return devlist->numDevice;
}

int main(int argc, char **argv)
{
	WSADATA         wsaData;
	SOCKET          sock;
	SOCKADDR_IRDA   irAddr = {AF_IRDA, 0, 0, 0, 0, "\0"};
	DWORD           dwIrSize = sizeof(SOCKADDR_IRDA), i, j;
	int             ret;
	DEVICELIST      devlist;
	char            szRecvBuff[MAX_BUFFER];
	
	if (WSAStartup(MAKEWORD(2,2), &wsaData) != 0)
	{
		printf("IR-Client: Unable to load the Winsock library!\n");
		return 1;
	}
	else
		printf("IR-Client: Winsock library 2.2 loaded!\n");
	
	if ((sock = socket(AF_IRDA, SOCK_STREAM, 0)) == INVALID_SOCKET)
	{
		printf("IR-Client: socket() failed with error %d\n", WSAGetLastError());
		return 1;
	}
	else
		printf("IR-Client: socket() looks fine!\n");
	
	// Find devices in range and store them in devlist...
	if (FindDevices(sock, &devlist) == 0)
	{
		printf("IR-Client: No IrDA devices in range!\n");
		// returns 1 indicates error
		return 1;
	}
	else
		printf("IR-Client: FindDevices() is OK!\n");
	
	printf("IR-Client: Found %d devices\n", devlist.numDevice);
	
	// Setup the SOCKADDR_IRDA structure with the service name we want to connect to.
	strcpy_s(irAddr.irdaServiceName, sizeof(irAddr.irdaServiceName), IR_SERVICE_NAME);
	// For every device...
	for(i=0; i < devlist.numDevice ;i++)
	{
		printf("IR-Client: i = %d, devlist.numDevice = %d\n", i, devlist.numDevice);
		// Fill up the device ID into irdaDeviceID[j] array
		for(j=0; j < 4 ;j++)
		{
			irAddr.irdaDeviceID[j] = devlist.Device[i].irdaDeviceID[j];
		}
		// Attempt to connect...
		printf("IR-Client: Attempting connection to %x%x%x%x, %s\n", devlist.Device[i].irdaDeviceID[0],
			devlist.Device[i].irdaDeviceID[1],
			devlist.Device[i].irdaDeviceID[2],
			devlist.Device[i].irdaDeviceID[3], irAddr.irdaServiceName);
		
		if (connect(sock, (struct sockaddr *)&irAddr, sizeof(SOCKADDR_IRDA)) == SOCKET_ERROR)
		{
			if (i == (devlist.numDevice - 1))
			{
				printf("IR-Client: Unable to locate service: '%s'\n", irAddr.irdaServiceName);
				printf("IR-Client: Error code is %ld\n", WSAGetLastError());
				return 1;
			}
			else
				printf("IR-Client: Connection attempt failed with error code %ld\n", WSAGetLastError());

			continue;
		}
		else
		{
			printf("connect() should be OK!\n");
			break;
		}
	}
	
	// Send the TEST_STRING to the server and receive it back.
	if ((ret = send(sock, TEST_STRING, strlen(TEST_STRING), 0)) == SOCKET_ERROR)
	{
		printf("IR-Client: send() failed with error %d\n", WSAGetLastError());
		closesocket(sock);
		WSACleanup();
		return 1;
	}
	else
		printf("IR-Client: send() also looks fine!\n");
	
	printf("IR-Client: Successfully sent %d bytes\n", ret);
	if ((ret = recv(sock, szRecvBuff, MAX_BUFFER, 0)) == SOCKET_ERROR)
	{
		printf("IR-Client: recv() failed with error code%d\n", WSAGetLastError());
		closesocket(sock);
		WSACleanup();
		return 1;
	}
	else
		printf("IR-Client: recv() seems working...\n");
	
	printf("Successfully received %d bytes\n", ret);
	printf("Closing socket\n");

	if(closesocket(sock) == SOCKET_ERROR)
		printf("IR-Client: Failed to close sock socket, error code %ld!\n", WSAGetLastError());
	else
		printf("IR-Client: sock socket successfully closed!\n");

	if(WSACleanup() == SOCKET_ERROR)
		printf("IR-Client: WSACleanup() failed with error code %ld\n", WSAGetLastError());
	else
		printf("IR-Client: WSACleanup() is OK!\n");
	return 0;
}
