/*#######################################################################################
AVR Small Webserver 

Copyright (C) 2004 Ulrich Radig

#######################################################################################*/

#include "main.h"

#include <webpage.h>

//delay.h used for _delay_ms (for pulse output). Clock frequency is 8 MHz.
#define F_CPU 8000000UL
#include <util/delay.h>

//Passwort
const unsigned char Password[] = {'P','a','s','s','w','o','r','d','&'}; // Max. 8 Chars + '&'

//read "ON" or "OFF" from pointer, return 1 or 0 accordingly (or -1 if none found)
char getOnOff(char * StringPointer)
{
	if (memcmp(StringPointer, "ON ", 3) == 0)
		return 1;
	if (memcmp(StringPointer, "OFF ", 4) == 0)
		return 0;
	return -1;
}

//############################################################################
//
void httpd (char* buffer,int *bufferlen)
//############################################################################
{	
 unsigned int tcpdata;
//Errechnet startpunkt der Daten im Tcp buffer
//IP Headerl�ge + TCP Headerl�ge + Ethernetframe
 tcpdata = ((buffer[IP_VERS_LEN] & 0x0F) << 2) + ((buffer[TCP_HDRFLAGS] & 0xF0) >>2) + 14;

	//Verwaltung Stackpointer

	unsigned char a;//Stack Speichplatz Default (0..10)
	if (TCP_Stack (buffer,bufferlen,&a)==1)
		{
		return;//keine Daten fr Anwendung
		}

	tcp_socket= &tcpsockets[a]; //Pointer auf tcpsockets[a] holen
	
	//�erprft HTTP Header 
	if ((buffer[TCP_HDRFLAGS+1]&PSH_FLAG) > 0 && tcp_socket->Status == TCP_SOCKET_OPEN1)
		{
			
		//Pointerold auf nix
		pointerold = 0;

		//File_Name entspricht 8.3 & Endmakierung
		unsigned char File_Name[13];
		unsigned int error = 404;
		
		//�erprft Header nach "GET /File_Name HTTP....."
		if ( memcmp(&buffer[tcpdata],"GET /",5) == 0)
			{
			char *tmppointer = &buffer[tcpdata + 5];
			unsigned char counter = 0;
			//Der Header wird durchsucht beginnend bei GET /
			//bis zum n�hsten Space Zeichen
			while ((*tmppointer != 0x20) && (*tmppointer != '?'))
				{
				File_Name[counter] = *tmppointer++;
				counter++;
				}
				//Endmakierung setzen
				File_Name[counter] = '\0';
			
			//Enth�t der Header keinen File Namen ist dieser index.htm
			if ((File_Name[0] == '\0') || (memcmp(File_Name, "index.htm\0",10) == 0))
				{
				memcpy(File_Name,"index.htm\0",10);
				error = 200;
				pointerold = PageMain;
				if (tmppointer[0] == '?')
					error = 302;
				if (memcmp(tmppointer, "?pwd=", 5) == 0)
					{
					tmppointer += 5;
					unsigned char check = 1;
					counter = 0;
					while (counter < 9) //max. 8 char password + '&'
						{
						if (*tmppointer++ != Password[counter])
							{
							check = 0;
							counter = 9;
							}
						if (Password[counter] == '&')
							counter = 9;
						counter++;
						}
					if (check == 1)
						{
						char OnOff = getOnOff(tmppointer + 4);
						if (memcmp(tmppointer, "rel=", 4) == 0) //pulse relay
							{
							if (OnOff == 1)
								PORTD |= 0x10;
								//wait 100 * 10 ms = 1 s
								for (unsigned int i = 0; i < 100; i++) {
									// maximum time for _delay_ms
									// is 262.14 ms @ 1 MHz
									// so max. @ 8 MHz is ~32 ms
									_delay_ms(10);
								}
								PORTD &= ~0x10;
							if (OnOff == 0)
								PORTD &= ~0x10;
							}
						if (memcmp(tmppointer, "out=", 4) == 0) //switch output
							{
							if (OnOff == 1)
								PORTD |= 0x08;
							if (OnOff == 0)
								PORTD &= ~0x08;
							}
						}
					}
				}
			
			// printf(File_Name);
			// printf("\n");
			
			#if USE_MMC
				//Durchsucht Root Verzeichnis nach File Namen
				unsigned char Dir_Attrib;

				//Lade Cluster fr das File welches in File_Name steht 
				tcp_socket->Cluster = 0; //suche im Root Directory
				if (Search_File(File_Name,&tcp_socket->Cluster,
										 &tcp_socket->File_Size,
										 &Dir_Attrib,
										 &buffer[tcpdata]) == 1)
					{
					tcp_socket->File_Block_Counter = 0;
					}
				else
					{
					//wurde das File nicht gefunden wird
					//Seite aus Flashspeicher angezeigt
					tcp_socket->Cluster = 0;
					}
			#endif //USE_MMC
			}

		if ( memcmp(File_Name,"m8.css\0",7) == 0)
			{
			pointerold = PageCSS;
			error = 201;
		}
			
		//Speichert Sequenzcounter und Aknowledgecounter
		tcp_store(buffer);
	
		//Setzen des Ack Flags und PSH Flags	
		buffer[TCP_HDRFLAGS+1] = ACK_FLAG | PSH_FLAG;
		
		switch (error)
			{
			case 200:
				tcp_add_data (HTTP_200,buffer,bufferlen);
				break;
			case 201:
				tcp_add_data (HTTP_200_CSS,buffer,bufferlen);
				break;
			case 302:
				pointerold = Page302;
				tcp_add_data (HTTP_302,buffer,bufferlen);
				break;
			case 404:
			default:
				pointerold = Page404;
				tcp_add_data (HTTP_404,buffer,bufferlen);
				break;
				
			}
		//Erzeugt ein TCP Packet
		tcp_make(buffer);
		//Sendet das erzeugte TCP Packet
		Write_Ethernet_Frame (buffer,*bufferlen);
		//(Ethernet Farne war aber voll) Weiters Frame mu�gesendet werden!
		tcp_socket->Status = TCP_SOCKET_OPEN2;
		tcp_socket->Pointer = pointerold;
		return;
		}
	
	//Senden der Webseite bzw. Daten war noch nicht Fertig (Ethernet Frame war aber voll)
	if (tcp_socket->Status == TCP_SOCKET_OPEN2) 
		{
			unsigned char Buffer_Full = 0;
			//Setzen des Ack Flags und PSH Flags	
			buffer[TCP_HDRFLAGS+1] = ACK_FLAG | PSH_FLAG;
			//Speichert Sequenzcounter und Aknowledgecounter
			tcp_store(buffer);		
			//erzeugt Seiten Packet
			
			#if USE_MMC
				if(tcp_socket->Cluster != 0)
					{
					Read_File (tcp_socket->Cluster,&buffer[tcpdata],tcp_socket->File_Block_Counter);
					tcp_socket->File_Block_Counter++;
					if (tcp_socket->File_Size > (unsigned long)512)
						{
						Buffer_Full = 1; //es wurden noch nicht alle Daten gesendet
						(unsigned long) tcp_socket->File_Size = (unsigned long) tcp_socket->File_Size - 512;
						TCP_New_Packtlen (buffer,bufferlen,tcpdata + 512);
						}
						else
						{
						Buffer_Full = 0; //es wurden alle Daten gesendet
						TCP_New_Packtlen (buffer,bufferlen,tcpdata + tcp_socket->File_Size);
						}
					goto endmakepacket;
					}
			#endif //USE_MMC
		
			pointerold = tcp_socket->Pointer;
			Buffer_Full = tcp_add_data (pointerold,buffer,bufferlen);
			tcp_socket->Pointer = pointerold;
			
			#if USE_MMC
				endmakepacket:
			#endif //USE_MMC
			//Erzeugt ein TCP Packet 
			tcp_make(buffer);			
			//Sendet das erzeugte TCP Packet 
			Write_Ethernet_Frame (buffer,*bufferlen);	
			if (Buffer_Full == 0)
				{
				#if USE_MMC
				tcp_socket->Cluster = 0;
				#endif //USE_MMC
				tcp_socket->Status = TCP_SOCKET_CLOSE;
				}
			return;		
		}
return;
}


