// All in wide character/Unicode and IPv6
// Uninitialized socket parameters will be assigned the
// default values. The comment parts are for IPv4
#include <winsock2.h>
#include <ws2tcpip.h>
#include <stdio.h>

int main(int argc, char **argv)
{
	WSADATA		wsaData;
	int			iResult, RetVal, RetVal2;
	// SOCKADDR_IN  MyAddr;
	SOCKADDR_IN6  MyAddrValue;
	// Storage buffer, using LPWSTR pointer failed lor!
	// WCHAR  MyAddrString[256] = L"For IPv4...";
	WCHAR  MyAddrString[256] = L"Some dummy initializer";
	// Take note that if the address is in FQDN/Name/hostname
	// we need to convert it to a dotted IP address. For example:
	// WCHAR IPAddr[256] = L"localhost"; // this should fail lor!
	// WCHAR IPAddr[256] = L"209.131.36.158";
	WCHAR IPAddr[256] = L"2a01:48:1:0:2e0:81ff:fe05:4658";
	
	// These buffer sizes must be allocated properly else
	// the WSAStringToAddress() and WSAAddressToString() will
	// fail miserabily!

	// int MyAddrSize = sizeof(struct sockaddr_storage);
	int MyAddrSize = sizeof(struct sockaddr_storage);
	// DWORD MyAddrSize2 = sizeof(struct sockaddr_storage);
	DWORD MyAddrSize2 = sizeof(struct sockaddr_storage);

	// Initialize Winsock
    iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
    if (iResult != 0)
	{
        printf("WSAStartup() failed with error code %d\n", WSAGetLastError());
		// Exit with error
        return 1;
    }
	else
		printf("WSAStartup() is OK...\n");

	// Initialize the address family
	// MyAddrValue.sin_family = AF_INET;
	MyAddrValue.sin6_family = AF_INET6;

	// This part should convert the server/hostname/FQDN to a standard dotted IP address
	// string first (if any) using other helper functions such as getaddressinfo()

	// 	============Convert address string to value using WSAStringToAddress()==============
	printf("\nWSAStringToAddress() - string to address value\n");
	RetVal = WSAStringToAddress(
		IPAddr,						// Pointer to address string to be converted
		AF_INET6 /* AF_INET*/,		// address family
		NULL,						// Protocol info structure, not useable here
		(LPSOCKADDR)&MyAddrValue,	// Socket address string buffer [out]
		&MyAddrSize					// Length of socket structure
		);
	
	// Something wrong
	if( RetVal != 0)
	{
		printf("WSAStringToAddress() failed with error code %ld\n", WSAGetLastError());
		// Clean-up
		WSACleanup();
		// Exit with error
		return 1;
	}
	else
		printf("WSAStringToAddress() looks fine! Return value is %ld\n", RetVal);

	// printf("The IP Address part of the buffer filled with %ul\n", MyAddr.sin_addr);
	printf("The IP address value is %ul\n", MyAddrValue.sin6_addr);
	// and other info
	printf("The address family value is %ul\n", MyAddrValue.sin6_family);
	printf("The port value is %ul\n", MyAddrValue.sin6_port);
	printf("The scopeID is %ul\n", MyAddrValue.sin6_scope_id);

	// =========Do the reconversion using WSAAddressToString()===============
	printf("\nWSAAddressToString() - address value to string\n");
	RetVal2 = WSAAddressToString(
		(LPSOCKADDR)&MyAddrValue,	// Pointer to address value to be converted
		MyAddrSize,		// Length of pointer to address value, in bytes
		NULL,			// A pointer to the WSAPROTOCOL_INFO structure for a particular provider
		MyAddrString,	// A pointer to the buffer that receives the human-readable address string
		&MyAddrSize2	// length of the buffer pointed to by the MyAddrString parameter
		);

	// Something wrong
	if( RetVal2 != 0)
	{
		printf("WSAAddressToString() failed with error code %ld\n", WSAGetLastError());
		// Clean-up
		WSACleanup();
		// Exit with error
		return 1;
	}
	else
		printf("WSAAddressToString() looks fine! Return value is %ld\n", RetVal2);
	
	// printf("The IP Address is %ul\n", MyAddr.sin_addr);
	printf("The address string is %S\n", MyAddrString);
	// and other info
	printf("The address family is %ul\n", MyAddrValue.sin6_family);
	printf("The port value is %ul\n", MyAddrValue.sin6_port);
	printf("The scopeID is %ul\n", MyAddrValue.sin6_scope_id);

	// Call WSACleanup for WSA* cleanup
	if(WSACleanup() != 0)
		printf("\nWSACleanup() failed!...\n");
	else
		printf("\nWSACleanup() is OK...\n");

	return 0;
}
