#include "stdio.h"
#include 
#include "rom400_init.h"
#include "rom400_sock.h"
#include "rom400_sched.h"

/*
 * This program will maintain a couple files.  One file will 
 * contain the current time, along with the last time we got
 * the time from the time server.  Another file will maintain
 * some statistics, and still another file will contain the main 
 * index file, linking to the others.
 *
 */


//
// Some defines for the program run.
//
#define RAM_START             0x14000
#define RAM_END               0x5FFFF

#define FS_START              0x60000
#define FS_BLOCKS                 512          // 2 banks worth of file system


// Static IP Address (used if you are selecting a static IP)
#define STATIC_IP_MSB             180
#define STATIC_IP_2                 0
#define STATIC_IP_3                54
#define STATIC_IP_LSB              91

// Static Subnet Mask (used if you are selecting a static IP)
#define STATIC_SUBNETMASK_MSB     255
#define STATIC_SUBNETMASK_2       255
#define STATIC_SUBNETMASK_3         0
#define STATIC_SUBNETMASK_LSB       0

#define STATIC_IPV4_PREFIX         16

// Static Gateway (used if you are selecting a static IP)
#define STATIC_GATEWAY_MSB        180
#define STATIC_GATEWAY_2            0
#define STATIC_GATEWAY_3          110
#define STATIC_GATEWAY_LSB         24


#define HTTP_INVALID_REQUEST        0
#define HTTP_FILENOTFOUND           1
#define HTTP_FILEERROR              2

char last_time_reading[200];
unsigned long last_reading_seconds;

unsigned long request_count;

void sendTimeFile(unsigned int handle);
void http_fail(unsigned int, unsigned int);
void time_server_start();
unsigned int http_server_start();
void handleRequest(unsigned int);
unsigned long getTimeSeconds();
void downloadTime();

unsigned char xdata config[56];

unsigned int initialize_network()
{
    unsigned int i;
    for (i=0;i<56;i++)
        config[i] = 0;

    //set the ip address
    config[12] = STATIC_IP_MSB;
    config[13] = STATIC_IP_2;
    config[14] = STATIC_IP_3;
    config[15] = STATIC_IP_LSB;

    //set the subnet mask
    config[16] = STATIC_SUBNETMASK_MSB;
    config[17] = STATIC_SUBNETMASK_2;
    config[18] = STATIC_SUBNETMASK_3;
    config[19] = STATIC_SUBNETMASK_LSB;

    //set the iP4 prefix
    config[20] = STATIC_IPV4_PREFIX;

    //set the gateway
    config[33] = STATIC_GATEWAY_MSB;
    config[34] = STATIC_GATEWAY_2;
    config[35] = STATIC_GATEWAY_3;
    config[36] = STATIC_GATEWAY_LSB;

    return setnetworkparams(config);
}

void network_config()
{
    unsigned char result;
    unsigned int i;
    for (i=0;i<56;i++)
        config[i] = 0;

    result = getnetworkparams(config);
    printf("Network params result: %d\r\n", result);

    printf("IP    : %bu %bu %bu %bu\r\n", config[12], config[13], config[14], config[15]);
    printf("Subnet: %bu %bu %bu %bu\r\n", config[16], config[17], config[18], config[19]);
    printf("Prefix: %bu\r\n", config[20]);
    printf("Gate  : %bu %bu %bu %bu\r\n", config[33], config[34], config[35], config[36]);
}


void initialize_filesystem()
{
    // it'd be nice for the filesystem to stick around between
	// reboots, so I can keep track of the number of reboots,
	// and activity since first birthday
	FILE* file;
    void* start = (void*)FS_START;
    int x = finit(FOPEN_MAX, FS_BLOCKS, start);
	printf("Result of FS init: %d \r\n", x);

//    file = fopen("index.html", "w");
//	fwrite(INDEX_FILE_CONTENTS, 1, strlen(INDEX_FILE_CONTENTS), file);

   // lets get the files we want off a TFTP server


}

void main()
{
    unsigned int temp;
	char buffer[40];

    request_count = 0;

    printf("DS80C400 Timer Server Demonstration\r\n");
    rom_init(RAM_START, RAM_END);

    temp = initialize_network();
	if (temp==0)
	    printf("Network parameters succesfully set.\r\n");
	else
	    printf("Network parameters could not be set.\r\n");

    network_config();

	initialize_filesystem();

    // start the time server
    time_server_start();

    // start the HTTP server
    temp = http_server_start();

	sprintf(buffer, "Process ID of HTTP server: %d\r\n", temp);
    printf(buffer);

    while(1)
	{
	    // sleep for about a minute
	    task_sleep(0, 0, 60000);

		downloadTime();
	}

}

void time_server_start()
{
    sprintf(last_time_reading, "No time reading has been taken yet.");

    downloadTime();
}

unsigned int http_server_start()
{
    int i, temp;
    unsigned int socket_handle;
    unsigned int new_socket_handle;
    struct sockaddr address;
    struct sockaddr local;

    // spawn off a new process.  The child will remain here and listen for connections.
    unsigned int result;
	
    EnterCritSection();

	result = task_fork(NORM_PRIORITY, ROM_SAVESIZE);

    if (result==0xFFFF)
    {
        LeaveCritSection();
        printf("Attempt to start HTTP server failed\r\n");
        return 0;
    }
    //else result is 0 for the child process, else it is the child PID

    if (result==0)
    {
        // this is the child.  Wait for a connection on port 80.
        printf("\r\nCreating a new TCP connection for listening...");
        socket_handle = socket(0, SOCKET_TYPE_STREAM, 0);
        printf("Result of socket creation: %u\r\n", socket_handle);
        for (i=0;i<18;i++)
        {
            local.sin_addr[i] = 0;
            address.sin_addr[i] = 0;
        }
        local.sin_port = 80;
        temp = bind(socket_handle, &local, sizeof(local));
        printf("Result of bind to port 80: %x\r\n", temp);
        temp = listen(socket_handle, 5);
        printf("Result of listen         : %x\r\n", temp);
        printf("Ready to accept HTTP connections...\r\n");
        while (1)
        {
            new_socket_handle = accept(socket_handle, &address, sizeof(address));
            request_count++;
			// This is just a simple example.  A more complex server
			// would spawn off a new thread/process to handle this request.
            handleRequest(new_socket_handle);
			closesocket(new_socket_handle);
        }
    }
    else
    {
        // 'result' is the HTTP server's process ID

        // Return to the main program
        LeaveCritSection();
        return result;
    }
}

void handleRequest(unsigned int handle)
{
    // Here we're looking for something like this:
    // GET http://www.w3.org/pub/WWW/TheProject.html HTTP/1.1
    // We'll ignore the first part of the URI and just look 
    // at the file name.
    unsigned char buffer[101];
    unsigned char request[20];
    unsigned char filename[50];
    unsigned char* fn;
    unsigned char version[20];
    int length, start;

    unsigned int result = recv(handle, buffer, 100, 0);
    
printf("I am in handle Request\r\n");
printf("Result of recv %d \r\n", result);
if (result != 0xFFFF)
{
    buffer[result] = 0;
	printf("Result buffer: %s \r\n", buffer);
}

    sscanf(buffer, "%s %s %s", request, filename, version);
printf("Request: %s\r\n", request);
printf("Filename: %s\r\n", filename);
printf("Version: %s\r\n", version);
   	
    // make sure this is a GET request.  We don't know nuthin' else.
    if (strncmp(request, "GET", 3) != 0)
    {
        http_fail(HTTP_INVALID_REQUEST, handle);
printf("...not a GET\r\n");
        return;
    }

    // else let's get the filename
    length = strlen(filename);
    start = length;
    while ((filename[start] != '/') && (start > -1))
        start--;

    start++;
    // from start to length is the filename

    fn = filename + start;

    if (strcmp(fn, "time.html")==0)
    {
        sendTimeFile(handle);
printf("...filename is time.html\r\n");
        return;
    }

    // request the filename from the file system, and write the bytes to the handle

printf("...looking for file...\r\n");
    /*
	file = fopen(fn, "r");
    if (file==NULL)
	{
	    http_fail(HTTP_FILENOTFOUND, handle);
		return;
	}

	// else the file is valid
    int amount = fread(file, buffer, 100);
    while (amount > 0)
	{
	    send(handle, buffer, amount, 0);
		amount = fread(file, buffer, 100);
	}
	*/
}

static char* Response_404 = "HTTP/1.0 404 File Not Found\r\n";
static char* Response_405 = "HTTP/1.0 405 Invalid Request Method\r\n";
static char* Response_500 = "HTTP/1.0 500 Internal Server Error\r\n";

static char* CRLF = "\r\n";

static char* Message_404 = "The file requested could not be found.  Stop snooping around. Please follow the links from index.html for a valid file.";
static char* Message_405 = "This server only supports the GET method.  Please make a valid request or risk my wrath.";
static char* Message_500 = "Server had an error and could not fulfill this request.  Please ask again when I feel better.";


void http_fail(unsigned int failcode, unsigned int handle)
{
    // write out to handle the error text
    switch(failcode)
	{
	    case HTTP_FILENOTFOUND:
		    send(handle, Response_404, strlen(Response_404), 0);
			send(handle, CRLF, strlen(CRLF), 0);
			send(handle, Message_404, strlen(Message_404), 0);
			return;

	    case HTTP_INVALID_REQUEST:
		    send(handle, Response_405, strlen(Response_405), 0);
			send(handle, CRLF, strlen(CRLF), 0);
			send(handle, Message_405, strlen(Message_405), 0);
			return;

	    case HTTP_FILEERROR:
		default:
		    send(handle, Response_500, strlen(Response_500), 0);
			send(handle, CRLF, strlen(CRLF), 0);
			send(handle, Message_500, strlen(Message_500), 0);
			return;
	}
}

unsigned long getTimeSeconds()
{
    // this does a divide by 1024 on the milliseconds, 
	// close enough if we have 60 second time server updates
    struct TIME t;
	unsigned long temp;
	GetTimeMillis(&t);
	temp = (t.msb << 22);
	temp = temp | (t.millis >> 10);
    return temp;
	return t.millis;
}

static char* RESPONSE_OK = "HTTP/1.0 200 Okily-Dokily\r\n";
static char* time_file_0 = "DS80C400 Time Server: Current Time

The last result from the time server was: "; static char* time_file_1 = ".

That reading was taken "; static char* time_file_2 = " seconds ago."; void sendTimeFile(unsigned int handle) { char buffer[50]; send(handle, RESPONSE_OK, strlen(RESPONSE_OK), 0); send(handle, CRLF, strlen(CRLF), 0); send(handle, time_file_0, strlen(time_file_0), 0); send(handle, last_time_reading, strlen(last_time_reading), 0); send(handle, time_file_1, strlen(time_file_1), 0); sprintf(buffer, "%ld", getTimeSeconds() - last_reading_seconds); send(handle, buffer, strlen(buffer), 0); send(handle, time_file_2, strlen(time_file_2), 0); } void downloadTime() { // go contact the server // 1 contact time.nst.gov and get the current time // 2 update our records // 3 last_reading_seconds = getTimeSeconds(); }