Code archives/Networking/BlitzServe
This code has been declared by its author to be Public Domain code.
Download source code
| |||||
This is an update to the previous code I placed in the Code Archives. It now serves files... :) There are tons of limitations, and it would need loads of things added to be useable as a real server, but it might give someone an idea of how to handle this sorta thing... There's a hell of a lot of work required to make a HTTP server work 'properly' -- see http://www.w3.org/Protocols/rfc2616/rfc2616.html for HTTP 1.1 definition! UPDATED: Just fixed to convert all '%20' style characters in URLs (eg. %20 = a space). | |||||
; ----------------------------------------------------------------------------- ; BlitzServe: a very crude HTTP server... ; ----------------------------------------------------------------------------- ; james @ hi - toro . com ; ----------------------------------------------------------------------------- ; Although this can accept unlimited connections, it'll only actually serve one ; file at a time because I can't launch the file-send part of the code as a ; separate thread, meaning the program flow is held up while a file is being ; sent. Also, for reasons unknown, sending a file to a browser on the same ; machine is VERY slow, though it's nice and quick over a network... AppTitle "BlitzServe..." ; ----------------------------------------------------------------------------- ; The place you'll put any files to be served. It's like an FTP directory... ; ----------------------------------------------------------------------------- folder$ = "C:\My Documents" ; Just stripping any "/" characters you or I might accidentally stick on the end ;) If (Right (folder$, 1) = "/") Or (Right (folder$, 1) = "\") folder$ = Left (folder$, Len (folder$) - 1) EndIf ; ----------------------------------------------------------------------------- ; To test, open Internet Explorer and type http://127.0.0.1/whatever/ ; ----------------------------------------------------------------------------- ; For example, if you have a file called hotpr0n.html in the above folder, ; you'd type 127.0.0.1/hotpr0n.html into your browser... ; ----------------------------------------------------------------------------- ; (Note: 127.0.0.1 is always the local PC. If you're on a network, you can run ; IE on another PC and replace 127.0.0.1 with the actual IP address of the ; PC this server is running on.) ; ----------------------------------------------------------------------------- ; Connection list type... ; ----------------------------------------------------------------------------- Type Connection Field number ; Stream identifier Field stream ; Stream handle End Type ; ----------------------------------------------------------------------------- ; Create HTTP server (always on port 80)... ; ----------------------------------------------------------------------------- server = CreateTCPServer (80) If server Print Print "BlitzServe: awaiting incoming connections..." Print Repeat ; ------------------------------------------------------------------------- ; See if there's been an incoming connection attempt... ; ------------------------------------------------------------------------- tstream = AcceptTCPStream (server) If tstream ; --------------------------------------------------------------------- ; Got one? OK, create a new Connection entry... ; --------------------------------------------------------------------- Print Print "Got new connection..." Print c.Connection = New Connection c\number = count c\stream = tstream ; --------------------------------------------------------------------- ; A HTTP request end with a blank line, so we read until we get that... ; --------------------------------------------------------------------- Repeat ; ----------------------------------------------------------------- ; Read a line from an incoming HTTP request... ; ----------------------------------------------------------------- ; The format of an incoming request line is: ; "Command" [space] "parameters" ; Examples... ; "GET /thisfile.txt" ; "User-Agent: AcmeBrowse" incoming$ = ReadLine (c\stream) ; DebugLog "Stream " + c\number + ": " + incoming$ If incoming$ <> "" ; ------------------------------------------------------------- ; Got a line? Let's parse! Split command and parameter(s)... ; ------------------------------------------------------------- eoc = Instr (incoming$, " ") ; End of command part of incoming$ command$ = Lower (Left (incoming$, eoc)) ; Command part of incoming$ parameter$ = Mid (incoming$, eoc + 1) ; Parameter part of incoming$ EndIf ; ----------------------------------------------------------------- ; Let's see what command we've got... ; ----------------------------------------------------------------- Select command$ Case "get " ; --------------------------------------------------------- ; Got a HTTP file request! ; --------------------------------------------------------- ; Format of GET is: "GET /thisfile.txt" eop = Instr (parameter$, " ") ; End of first parameter ("GET") file$ = Mid (parameter$, 1, eop - 1) ; First parameter ("GET") http$ = Mid (parameter$, eop + 1) ; Second parameter ("/thisfile.txt") ; --------------------------------------------------------- ; Requesting program's name/identifier... ; --------------------------------------------------------- Case "user-agent: " program$ = Mid (incoming$, eoc + 1) End Select Until incoming$ = "" ; Got blank line after headers, all done here... ; --------------------------------------------------------------------- ; Lessee what we've got... ; --------------------------------------------------------------------- Print "Requested file: " + file$ Print "Requested by: " + program$ Print "Requested HTTP version: " + http$ ; --------------------------------------------------------------------- ; 'K, we barely know what we're doing as it is, so only HTTP 1.1... ; --------------------------------------------------------------------- If http$ <> "HTTP/1.1" WriteLine c\stream, "HTTP/1.1 505 This server only accepts HTTP version 1.1" WriteLine c\stream, "" CloseTCPStream c\stream: Delete c Else ; ----------------------------------------------------------------- ; It was a HTTP 1.1 request... ; ----------------------------------------------------------------- If file$ <> "" ; Convert any %xx (hex) codes in URL to Chr (ascii) character... ; (Eg. %20 is ascii 57, ie. Chr (57), ie. a Space.) file$ = UnHexURL (file$) Print Print "Attempting to send " + file$ + "..." Print If Left (file$, 1) <> "/" file$ = "/" + file$ ; Strip leading "/" if any... EndIf ; ------------------------------------------------------------- ; Does the requested file exist in our 'site' folder? ; ------------------------------------------------------------- Select FileType (folder$ + file$) Case 0 ; File does not exist... WriteLine c\stream, "HTTP/1.1 404 Not found" WriteLine c\stream, "" ; ----------------------------------------------------- ; Close the stream and free the Connection... ; ----------------------------------------------------- CloseTCPStream c\stream Delete c Case 1 ; File exists! Print "Writing file..." Print ; ----------------------------------------------------- ; Send the file. This part sucks. ; ----------------------------------------------------- ; It's slow and needs to be performed as a separate thread, ; since it holds program flow up! We also don't reply with a ; polite HTTP response... writing = ReadFile (folder$ + file$) If writing While Not Eof (writing) WriteByte c\stream, ReadByte (writing) Wend Print "Sent!" Print CloseFile writing WriteLine c\stream, "" ; ------------------------------------------------- ; Close the stream and free the Connection... ; ------------------------------------------------- CloseTCPStream c\stream Delete c EndIf Case 2 ; Folder... WriteLine c\stream, "That's a folder, dummy..." WriteLine c\stream, "" ; ----------------------------------------------------- ; Close the stream and free the Connection... ; ----------------------------------------------------- CloseTCPStream c\stream Delete c End Select EndIf EndIf count = count + 1 ; Just the Connection number parameter for the next Connection... EndIf ; ------------------------------------------------------------------------- ; Don't wanna hog CPU... ; ------------------------------------------------------------------------- Delay 100 Until KeyHit (1) ; ----------------------------------------------------------------------------- ; Free any open TCP streams... ; ----------------------------------------------------------------------------- For c.Connection = Each Connection CloseTCPStream c\stream Delete c Next ; ----------------------------------------------------------------------------- ; Freeze! FBI! We're shutting this server down! ; ----------------------------------------------------------------------------- CloseTCPServer server Else Print "Couldn't create server! Press ENTER to exit..." Repeat: Delay 100: Until KeyHit (28) EndIf End Function UnHexURL$ (url$) Repeat pos = Instr (url$, "%") If pos hexx$ = Mid (url$, pos, 3) url$ = Replace (url$, hexx$, Chr (HexToDec (hexx$))) EndIf Until pos = 0 Return url$ End Function ; From PureBasic code by 'PB'... ; (h$ can be 0-FFFFFFF) Function HexToDec (h$) If Left (h$, 1) = "%" Then h$ = Right (h$, Len (h$) - 1) h$ = Upper (h$) For r=1 To Len (h$) d = d Shl 4: a$ = Mid (h$, r, 1) If Asc (a$) > 60 d = d + Asc (a$) - 55 Else d = d + Asc (a$) - 48 EndIf Next Return d End Function |
Comments
| ||
Rock on Dude. Superb stuff , Ive managed to evolve this thing into responding to HTML forms and I'm chuffed to little mince balls, about the size of marbles. A trillion thanks. |
| ||
Can you post your update? :P Maybe? Please :§ |
Code Archives Forum