/*
File Name : sockutil.c
Version : 1.0
Created :  2003/05/
Copyright : (C) 2003 ~ 2004 WIZnet, Inc. (http://www.wiznet.co.kr)
Description : Implementation of useful function of iinChip
*/

#include <stdio.h>
#include <string.h>
#include "../mcu/types.h"
#include "../mcu/serial.h"
#include "../util/myprintf.h"
#include "../util/util.h"
#include "../evb/config.h"
#include "../iinchip/w5100.h"

#include "sockutil.h"


/*
Description   :  Convert 32bit Address(Host Ordering) into Dotted Decimal Format
Argument      :  addr - Pointer variable to store converted value(INPUT)
		 addr_str - (INPUT,OUTPUT)
Return Value  :  a char pointer to a static buffer containing the text address in standard ".'' notation. Otherwise, it returns NULL. 
Note          :  
*/
char* inet_ntoa(unsigned long addr)
{
	static char addr_str[16];
	memset(addr_str,0,16);
	sprintf(addr_str,"%d.%d.%d.%d",(int)(addr>>24 & 0xFF),(int)(addr>>16 & 0xFF),(int)(addr>>8 & 0xFF),(int)(addr & 0xFF));
	return addr_str;
}

char* inet_ntoa_pad(unsigned long addr)
{
	static char addr_str[16];
	memset(addr_str,0,16);
	sprintf(addr_str,"%03d.%03d.%03d.%03d",(int)(addr>>24 & 0xFF),(int)(addr>>16 & 0xFF),(int)(addr>>8 & 0xFF),(int)(addr & 0xFF));
	return addr_str;
}
/*
Description   :  Converts a string containing an (Ipv4) Internet Protocol decimal dotted address into a 32bit address 
Argument      :  addr - dotted notation address string. 
Return Value  :  32bit address (Host Odering)
Note          :  
*/
unsigned long inet_addr(char* addr)
{
	char i;
	u_long inetaddr = 0;
	char taddr[30];
	char * nexttok;
	int num;
	strcpy(taddr,addr);
	
	nexttok = taddr;
	for(i = 0; i < 4 ; i++)
	{
		nexttok = strtok(nexttok,".");
		if(nexttok[0] == '0' && nexttok[1] == 'x') num = ATOI(nexttok+2,0x10);
		else num = ATOI(nexttok,10);
		inetaddr = inetaddr << 8;		
		inetaddr |= (num & 0xFF);
		nexttok = NULL;
	}
	return inetaddr;	
}	

/*
Description   :  Verify dotted notation IP address string
Argument      :  src - pointer to IP address string
Return Value  :  success - 1, fail - 0
Note          :  
*/
char VerifyIPAddress(char* src)
{
	int i;
	u_int tnum;
	char tsrc[50];
	char* tok = tsrc;
	
	strcpy(tsrc,src);
	
	for(i = 0; i < 4; i++)
	{
		tok = strtok(tok,".");
		if ( !tok ) return 0;
		if(tok[0] == '0' && tok[1] == 'x')
		{
			if(!ValidATOI(tok+2,0x10,&tnum)) return 0;
		}
		else if(!ValidATOI(tok,10,&tnum)) return 0;
		
		if(tnum < 0 || tnum > 255) return 0;
		tok = NULL;
	}
	return 1;	
}


////---- MODIFY_2005_10_31 (Network Ordering -> Host Ordering)
/*
Description : Output destination IP address of appropriate channel
Arguments   : s  - Channel number which try to get destination IP Address
Returns     : 32bit destination address (Host Ordering)
*/
unsigned long GetDestAddr(SOCKET s)
{
	u_long addr=0;
	int i = 0;
	for(i=0; i < 4; i++)
	{
		addr <<=8;
		addr += IINCHIP_READ(Sn_DIPR0(s)+i);
	}
	return addr;
}
////---- END_MODIFY

/*
Description : Output destination port number of appropriate channel
Arguments   : s  - Channel number which try to get destination port
Returns     : 16bit destination port number
*/
unsigned int GetDestPort(SOCKET s)
{
	u_int port;
	port = ((u_int) IINCHIP_READ(Sn_DPORT0(s))) & 0x00FF;
	port <<= 8;
	port += ((u_int) IINCHIP_READ(Sn_DPORT0(s)+1)) & 0x00FF;
	return port;
}

/*
Description : htons function converts a unsigned short from host to TCP/IP network byte order (which is big-endian).
Arguments   : hostshort  - A 16-bit number in host byte order. 
Returns     : the value in TCP/IP network byte order
*/
unsigned short htons( unsigned short hostshort)
{
#ifdef LITTLE_ENDIAN	
	return swaps(hostshort);
#else
	return hostshort;
#endif		
}

/*
Description : htonl function converts a unsigned long from host to TCP/IP network byte order (which is big-endian).
Arguments   : hostshort  - A 32-bit number in host byte order. 
Returns     : the value in TCP/IP network byte order
*/
unsigned long htonl(unsigned long hostlong)
{
#ifdef LITTLE_ENDIAN	
	return swapl(hostlong);
#else
	return hostlong;
#endif	
}


/*
Description : ntohs function converts a unsigned short from TCP/IP network byte order to host byte order (which is little-endian on Intel processors).
Arguments   : netshort - network odering 16bit value
Returns     : a 16-bit number in host byte order
*/
unsigned long ntohs(unsigned short netshort)
{
#ifdef LITTLE_ENDIAN	
	return htons(netshort);
#else
	return netshort;
#endif		
}

/*
Description : Output destination IP address of appropriate channel
Arguments   : s  - Channel number which try to get destination IP Address
              addr - Buffer address to store destination IP address
Returns     : 32bit destination address
*/
unsigned long ntohl(unsigned long netlong)
{
#ifdef LITTLE_ENDIAN	
	return htonl(netlong);
#else
	return netlong;
#endif		
}

// destip : BigEndian
u_char CheckDestInLocal(u_long destip)
{
	int i = 0;
	u_char * pdestip = (u_char*)&destip;
	for(i =0; i < 4; i++)
	{
		if((pdestip[i] & IINCHIP_READ(SUBR0+i)) != (IINCHIP_READ(SIPR0+i) & IINCHIP_READ(SUBR0+i)))
			return 1;	// Remote
	}
	return 0;
}


/*
Description   :  Get handle of socket which status is same to 'status'
Argument      :  status - socket's status to be found
		 start  - base of socket to be found
Return Value  :  socket number
Note          :  
*/    
SOCKET getSocket(unsigned char status, SOCKET start)
{
	SOCKET i;
	if(start > 3) start = 0;

	for(i = start; i < MAX_SOCK_NUM ; i++) if( getSn_SR(i)==status ) return i;
	return MAX_SOCK_NUM;	
}


/*
Description   :  Calculate checksum of a stream
Argument      :  src - pointer to stream 
		 len - size of stream
Return Value  :  checksum
Note          :  
*/
unsigned short checksum(unsigned char * src, unsigned int len)
{
	u_int sum, tsum, i, j;
	u_long lsum;

	j = len >> 1;

	lsum = 0;

	for (i = 0; i < j; i++) 
	{
		tsum = src[i * 2];
		tsum = tsum << 8;
		tsum += src[i * 2 + 1];
		lsum += tsum;
	}

	if (len % 2) 
	{
		tsum = src[i * 2];
		lsum += (tsum << 8);
	}

	sum = lsum;
	sum = ~(sum + (lsum >> 16));
	return (u_short) sum;	
}



#ifndef NO_USE_SOCKUTIL_FUNC

/*
Description   :  Get Source IP Address of iinChip.
Argument      :  
Return Value  :  Source IP Address(32bit Address-Host Ordering)
Note          :  
*/
u_long GetIPAddress(void)
{
	u_long ip=0;
	int i;
	for(i=0; i < 4; i++)
	{
		ip <<= 8;
		ip += (char)IINCHIP_READ(SRC_IP_PTR+i);
	}
	return ip;
}

/*
Description   :  Get Gateway IP Address of iinChip.
Argument      :  
Return Value  :  Gateway IP Address(32bit Address-Host Ordering)
Note          :  
*/
u_long GetGWAddress(void)
{
	u_long ip=0;
	int i;
	for(i=0; i < 4; i++)
	{
		ip <<= 8;
		ip += (char)IINCHIP_READ(GATEWAY_PTR+i);
	}
	return ip;	
}

/*
Description   : Get Subnet mask of iinChip.
Argument      : 
Return Value  : Subnet Mask(32bit Address-Host Ordering)
Note          :  
*/
u_long GetSubMask(void)
{
	u_long ip=0;
	int i;
	for(i=0; i < 4; i++)
	{
		ip <<= 8;
		ip += (char)IINCHIP_READ(SUBR0+i);
	}
	return ip;	
}

/*
Description   :  Get Mac Address of iinChip.
Argument      :  addr - Pointer to store Mac Address(48bit Address)(INPUT, OUTPUT)
Return Value  :  
Note          :  
*/
void GetMacAddress(unsigned char* mac)
{
	int i = 0;
	for(i=0; i<6;i++)*mac++ = IINCHIP_READ(SRC_HA_PTR+i);
}

void GetDestMacAddr(SOCKET s, u_char* mac)
{
	int i = 0;
	for(i=0; i<6;i++)*mac++ = IINCHIP_READ(DST_HA_PTR(s)+i);
}

/*
Description: Read established network information(G/W, IP, S/N, Mac) of iinChip and Output that through Serial.
Arguments  :  
Returns    :
Note       :  Mac Address is output into format of Dotted HexaDecimal.Others are output into format of Dotted Decimal Format.
*/
void GetNetConfig(void)
{
	u_char addr[6];
	u_long iaddr;
	printf("\r\n================================================\r\n");
	printf("       Net Config Information\r\n");
	printf("================================================\r\n");
	GetMacAddress(addr);
	printf("MAC ADDRESS      : 0x%02X.0x%02X.0x%02X.0x%02X.0x%02X.0x%02X\r\n",addr[0],addr[1],addr[2],addr[3],addr[4],addr[5]);
	
	iaddr = GetSubMask();
	printf("SUBNET MASK      : %s\r\n",inet_ntoa(iaddr));

	iaddr = GetGWAddress();
	printf("G/W IP ADDRESS   : %s\r\n",inet_ntoa(iaddr));

	iaddr = GetIPAddress();
	printf("LOCAL IP ADDRESS : %s\r\n",inet_ntoa(iaddr));
	printf("================================================\r\n");		
}

#endif

