/****************************************************************************** COPYRIGHT(C) JONAS 'SORTIE' TERMANSEN 2011. This file is part of Sortix. Sortix is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Sortix is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Sortix. If not, see . http.cpp A very small http server running in kernel mode, heh! ******************************************************************************/ #include "platform.h" #include #include #include "uart.h" using namespace Maxsi; namespace Sortix { namespace HTTP { uint32_t Left; bool TryByte(char* Dest) { if ( Left == 0 ) { UART::Read((uint8_t*) &Left, sizeof(Left)); } if ( Left == 0 ) { return false; } UART::Read((uint8_t*) Dest, 1); Left--; return true; } void Close() { uint32_t ToSend = 0; UART::Write(&ToSend, sizeof(ToSend)); } void Send(const char* Response, uint32_t Len) { UART::Write(&Len, sizeof(Len)); UART::Write(Response, Len); } void Respond(const char* Body, uint32_t Len) { const char* Headers = "HTTP/1.1 200 Success\r\nConnection: close\r\nContent-Type: application/xhtml+xml\r\n\r\n"; Send(Headers, String::Length(Headers)); Send(Body, Len); Close(); } void HandleResource(const char* Operation, const char* Resource) { if ( String::Compare(Resource, "/") == 0 ) { const char* Response = "\n" "\n" " \n" " Hello, World!\n" " \n" " \n" "

\"Hello, World!\" said Sortix with a big smile!

\n" "

\"Finally\", Sortix continued, \"someone completed a working HTTP server that runs under Sortix, which runs as a virtual machine, that communicates over a serial terminal driver to proxy server that communicates with the real internet!\".

\n" "

Sortix was happy.

\n" "

This website was served by a server running under my very own operating system, which is connected to the internet through a serial modem driver. Heh!

\n" " \n" "\n" ; Respond(Response, String::Length(Response)); return; } else { const char* Response = "HTTP/1.1 400 Not Found\r\nConnection: close\r\n\r\nHTTP 404 File Not Found\n"; Send(Response, String::Length(Response)); Close(); return; } } void HandleConnection() { char Buffer[1024]; char* Operation = NULL; char* Resource = NULL; size_t Used = 0; nat State = 0; while ( true ) { if ( !TryByte(Buffer + Used) ) { return; } Used++; Buffer[Used] = '\0'; if ( State == 0 ) { if ( Used >= 4 ) { if ( Buffer[0] == 'G' && Buffer[1] == 'E' && Buffer[2] == 'T' && Buffer[3] == ' ' ) { State++; Buffer[3] = '\0'; Operation = Buffer; } else { const char* Response = "HTTP/1.1 501 Not Implemented\r\nConnection: close\r\n\r\nThis request is not supported by this server!\n"; Send(Response, String::Length(Response)); Close(); return; } } } if ( State == 1 ) { if ( Buffer[Used-1] == ' ' ) { Resource = Buffer + 4; Buffer[Used-1] = '\0'; State++; break; } } if ( Used == 1024 ) { const char* Response = "HTTP/1.1 400 Bad Request\r\n\r\n"; Send(Response, String::Length(Response)); Close(); return; } } nat LineChars = 0; while ( LineChars < 4 ) { char TMP; if ( !TryByte(&TMP) ) { return; } if ( TMP == '\r' || TMP == '\n' ) { LineChars++; } else { LineChars = 0; } } HandleResource(Operation, Resource); } void Init() { Left = 0; while ( true ) { HandleConnection(); } } } }