/* UDP stack */

#include "stdint.h"
#include "udp.h"
#include "ip.h"
#include "net.h"
#include "eth.h"
#include "arp.h"
#include "enc28j60.h"
#include "net_checksum.h"

extern unsigned char my_IP[IP_ADR_SIZE];					// IP adresa HTTP serveru
extern unsigned char my_MAC[MAC_ADR_SIZE];					// MAC adresa HTTP serveru

/* --------------------------------------
   Nastavi polev UDP hlavicce
   ----------------------------------- */
void UDP_Set_UDP_Header(uint8_t *buffer, uint16_t SourcePort, uint16_t DestPort, uint16_t Length)
{
	uint16_t tmp;
	// Vyplneni zdrojoveho portu
	buffer[OFFSET_UDP_SourcePort+0] = (0xFF00&SourcePort)>>8;
	buffer[OFFSET_UDP_SourcePort+1] = 0x00FF&SourcePort;
	// Vyplneni ciloveho portu
	buffer[OFFSET_UDP_DestPort+0] = (0xFF00&DestPort)>>8;
	buffer[OFFSET_UDP_DestPort+1] = 0x00FF&DestPort;
	// Vyplneni Delky UDP (data + hlavicka)
	Length = Length + UDP_Header_len;								// Pricteni delky hlavicky UDP
	buffer[OFFSET_UDP_Length+0] = (0xFF00&Length)>>8;
	buffer[OFFSET_UDP_Length+1] = 0x00FF&Length;
	// Vynulovani checksumu UDP datagramu
	buffer[OFFSET_UDP_CheckSum+0] = 0x00;							//  SourceIP, DestIP, "zeros", IPProtokol,
	buffer[OFFSET_UDP_CheckSum+1] = 0x00;							//  IPLength, SourceUDP Port, DestUDP Port,
																	//  UDP length, UDP checksum = 0x00 a UDP data
	tmp = NET_checksum(&buffer[OFFSET_IP_SourceIP], 8+Length, UDP_TYPE);	//	8 = 4(Source IP)+4(Dest. IP)
	buffer[OFFSET_UDP_CheckSum+0] = (0xFF00&tmp)>>8;
	buffer[OFFSET_UDP_CheckSum+1] = 0x00FF&tmp;
}

/* ---------------------------------------
   Overeni jestli je prichozi paket
   UDP paketem se spravnym cislem portu
   ------------------------------------ */
uint8_t UDP_Check_UDP_Port(uint8_t *buffer, uint16_t Port)
{
	if (buffer[OFFSET_IP_Protokol]==IP_Protokol_UDP && 
		buffer[OFFSET_UDP_DestPort+0]==(0xFF00&Port)>>8 && buffer[OFFSET_UDP_DestPort+1]==(0x00FF&Port))
	{
		return(1);
	}
	return(0);
}

/* --------------------------------------
   Vytvori ETH + IP + UDP hlavicku
   a takto vytvoreny paket odesle
   ----------------------------------- */
uint8_t UDP_Build_Datagram(uint8_t *buffer_TX, uint8_t *DestIP[IP_ADR_SIZE], uint16_t DestPort, 
						   uint16_t SourcePort, uint8_t *data, uint16_t Delka_UDP_dat)
{
	uint16_t i;
	static uint8_t MAC_address[MAC_ADR_SIZE];

	// Naplneni UDP datagramu daty
	for(i=0;i<Delka_UDP_dat;i++)
	{
		buffer_TX[OFFSET_UDP_Data+i] = data[i];
	} 

	// Vyplneni Hlavicky UDP datagramu
	UDP_Set_UDP_Header(buffer_TX, 
					   DestPort, 
					   SourcePort, 
					   Delka_UDP_dat);

	// Vyplneni IP hlavicky
	IP_Set_IP_Header(buffer_TX, 
					 IP_Header_len+UDP_Header_len+Delka_UDP_dat,
					 0x0000, 
					 0x00, 
					 IP_Default_TTL, 
					 IP_Protokol_UDP, 
					 my_IP, 
					 *DestIP);
	// Vyplneni ETH hlavicky
	if(ARP_Get_MAC(*DestIP, MAC_address)!=MAC_Found) return(UDP_SendFail);				// Dotaz na MAC adresu podle IP adresy
	ETH_Set_ETH_Header(buffer_TX, MAC_address, my_MAC, ETH_Type_IPv4);
	// Odeslani vytvoreneho paketu
	ETH_SendPacket(ETH_Header_len+IP_Header_len+UDP_Header_len+Delka_UDP_dat,
				   buffer_TX,0);															// Odeslani
	return(UDP_SendOK);
}

/* --------------------------------------
   Vytvori ETH + IP + UDP hlavicku
   z naposledy prijateho paketu
   ----------------------------------- */
void UDP_Build_Datagram_From_RX(uint8_t *buffer_RX, uint8_t *buffer_TX, uint8_t *data, uint16_t Delka_UDP_dat, uint8_t DataVlozena)
{
	uint16_t i;
	
	// Vyplneni ETH hlavicky
	ETH_CopyETH_Header(buffer_TX, buffer_RX, ETH_Type_IPv4);
	// Vyplneni IP hlavicky
	IP_Set_IP_Header(buffer_TX, 
					 IP_Header_len+UDP_Header_len+Delka_UDP_dat,
					 0x0000, 
					 0x00, 
					 IP_Default_TTL, 
					 IP_Protokol_UDP, 
					 my_IP, 
					 IP_Get_SourceIP(buffer_RX));
	// Naplneni UDP datagramu daty
	if(DataVlozena!=1)
	{
		for(i=0;i<Delka_UDP_dat;i++)
		{
			buffer_TX[OFFSET_UDP_Data+i] = data[i];
		} 
	}
	// Vyplneni Hlavicky UDP datagramu
	UDP_Set_UDP_Header(buffer_TX, 
					  (buffer_RX[OFFSET_UDP_DestPort+0]<<8)|buffer_RX[OFFSET_UDP_DestPort+1], 
					  (buffer_RX[OFFSET_UDP_SourcePort+0]<<8)|buffer_RX[OFFSET_UDP_SourcePort+1], 
					   Delka_UDP_dat);	
	
	// Odeslani vytvoreneho paketu
	ETH_SendPacket(ETH_Header_len+IP_Header_len+UDP_Header_len+Delka_UDP_dat,buffer_TX,0);			// Odeslani	
}

/* --------------------------------------
   Vrati delku UDP datagramu vcetne delky
   hlavicky (8 bytu)
   ----------------------------------- */
uint16_t UDP_Get_Length(uint8_t *buffer)
{
	return(buffer[OFFSET_UDP_Length+0]<<8 | buffer[OFFSET_UDP_Length+1]);
}
/* Konec souboru */
