flat assembler
Message board for the users of flat assembler.

Index > Windows > HTTP FIle server?

Goto page 1, 2  Next
Author
Thread Post new topic Reply to topic
OzzY



Joined: 19 Sep 2003
Posts: 1029
Location: Everywhere
OzzY 12 Aug 2007, 21:49
Does anyone have any clue on how to build a simple HTTP File Server, where files are stored at share/ and people can download them from their browsers by accessing http://ip?

Thanks
Post 12 Aug 2007, 21:49
View user's profile Send private message Reply with quote
vid
Verbosity in development


Joined: 05 Sep 2003
Posts: 7105
Location: Slovakia
vid 12 Aug 2007, 22:51
Do you have TCP/IP implementation you can use, and you only need HTTP on top of it?

If no, then you will probably have to write LOT of code, too much i quess Wink
Post 12 Aug 2007, 22:51
View user's profile Send private message Visit poster's website AIM Address MSN Messenger ICQ Number Reply with quote
OzzY



Joined: 19 Sep 2003
Posts: 1029
Location: Everywhere
OzzY 12 Aug 2007, 22:54
I mean using Winsock to implement a sub-set of HTTP server, able to provide a "index of" page, with files to download.

Yes, I want to code on my own for learning.
Is it too much work?
Post 12 Aug 2007, 22:54
View user's profile Send private message Reply with quote
vid
Verbosity in development


Joined: 05 Sep 2003
Posts: 7105
Location: Slovakia
vid 13 Aug 2007, 00:47
Then, it should be quite easy.

See this.
Post 13 Aug 2007, 00:47
View user's profile Send private message Visit poster's website AIM Address MSN Messenger ICQ Number Reply with quote
Chewy509



Joined: 19 Jun 2003
Posts: 297
Location: Bris-vegas, Australia
Chewy509 13 Aug 2007, 01:47
HTTP is pretty easy if you have a complete TCP/IP and socket implementation to use.

In the past I have seen a very simple HTTP server implemented in about 50 lines of Perl. However hunting the 'net can't find it.

I did find the following however: http://www.ibm.com/developerworks/library/wa-ltwebserv/index.html which contains a few links to smallish HTTP servers... Maybe you could use those as the basis?
Post 13 Aug 2007, 01:47
View user's profile Send private message Visit poster's website Reply with quote
drhowarddrfine



Joined: 10 Jul 2007
Posts: 533
drhowarddrfine 15 Aug 2007, 01:48
Look into lighttpd
Post 15 Aug 2007, 01:48
View user's profile Send private message Reply with quote
r22



Joined: 27 Dec 2004
Posts: 805
r22 15 Aug 2007, 03:28
I'm currently working on a HTTP server that has a simple dll interface to post and receive data from a dll. The purpose being, processor intensive tasks (db queries then parsing the result set, mathematical problem solving, file conversions, etc.) are best served by native code then script or VM (jsp, php, perl etc.). While CGI has a way to fork out to executables I think a more streamlined method is worth developing.

Having a server that takes a POSTed ASM file compiles it and returns the EXE/OBJ/DLL would be interesting, and useful, and possibly a security risk.

ON TOPIC portion of post:
While the HTTP protocol is relatively simple (being plain text and having a small subset of commands) implementing a reliable HTTP file server using winsock isn't.

For an HTTP server you need
- A stable Listen -> Accept -> Request loop
- Forking the Accept(ed) socket to another thread works well, but if your not familiar with threading (CreateThread api) then it just adds another level of complexity.
- To serve a directory listing where you can download files you'd need to use the file api and recursively tranverse the folder and sub folders of whatever directory you'd like to be your WWWROOT and compile a list of those file pathes and names, then create a HTML document with links.
- Now you need to parse incoming HTTP requests and have a RECV_TIMEOUT set on the socket using (setsockopt api) if you don't have this, connections that don't send any data will be able to DoS, hang or cause memory leaks on your server. Unless you use WSA (asynchronous sockets) which add another level of complication if your not familiar with them.
- Finally you need to read the file that you parsed out of the HTTP header sent to your server and write it to the socket after a properly formated HTTP reply header.

- More specifically Ozzy wants to serve files over HTTP so he'd need to research (or packet sniff) the correct header attributes like content type, chunking and/or content length.

- Ignoring security and configuration options for the server would help developement time. But you'd end up with something only suitable for personal use.


CALL [Calculate_PI_To_Final_Digit]
MOV [Rant],eax
RET 0
Post 15 Aug 2007, 03:28
View user's profile Send private message AIM Address Yahoo Messenger Reply with quote
gunblade



Joined: 19 Feb 2004
Posts: 209
gunblade 15 Aug 2007, 21:49
Code:
format PE console
use32
entry start

PORT = 80

include '%fasminc%\win32a.inc'

macro print msg,msglen
{ common
    invoke WriteConsole,[stdout],msg,msglen,NULL,NULL
}

macro tcpsend msg,msglen
{ common
    invoke send,[peer],msg,msglen,NULL
}

section '.code' code readable executable

start:

invoke GetStdHandle,STD_OUTPUT_HANDLE
mov [stdout],eax
invoke WSAStartup,0101h,wsadata

mov [port], PORT

invoke socket,AF_INET,SOCK_STREAM,NULL
mov [sockfd], eax

mov eax, [port]
and eax, 0xffff
ror ax, 8
mov word [bindparms+2], ax
invoke bind,[sockfd],bindparms,16

invoke listen,[sockfd],50

acceptit:
invoke accept,[sockfd],peeraddr,sixteen
mov dword [peer], eax

invoke recv,[peer],buffer,bufferlen,0

mov ebx, buffer
cmp dword [ebx], 'GET '
je .1

jmp endpeer

.1:
xor ecx, ecx
inc ebx
cmp byte [ebx], '/'
je @f
jmp .1
.2:
@@:

inc ebx
cmp byte [ebx], ' '
je @f
cmp byte [ebx], '%'
je .hex
mov al, [ebx]
mov [buffer+ecx], al
inc ecx
jmp @b
@@:
mov byte [buffer+ecx], 0
cmp ecx, 0
jne @f
mov dword [buffer], 'inde'
mov dword [buffer+4], 'x.ht'
mov  word [buffer+8], 'ml'
mov  byte [buffer+10], 0
jmp @f

.hex:
inc ebx
mov dx, [ebx]
mov word [fd], dx
mov word [fd+2], 0
mov edi, fd
push ebx
mov ebx, 16
call StrToInt
pop ebx
mov [buffer+ecx], al
inc ebx
inc ecx
jmp .2

@@:
invoke CreateFile,buffer,GENERIC_READ,0,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_ARCHIVE,NULL
cmp eax, 0ffffffffh
jne @f
tcpsend h404,h404.len
jmp endpeer
@@:
mov [fd], eax

invoke TransmitFile,[peer],[fd],0,0,NULL,transmitbuffer,NULL

invoke CloseHandle,[fd]

endpeer:

invoke CloseHandle,[peer]

jmp acceptit


exit:
call WSACleanup
invoke ExitProcess,0


IntToStr:
; eax = number, ebx = base, edi = buffer
push    ecx edx
xor ecx,ecx
  .new:
xor edx,edx
div ebx
push    edx
inc ecx
test    eax,eax
jnz .new
 .loop:
pop eax
add al,30h
cmp al,'9'
jng .ok
add al,7   
 .ok:
stosb
loop    .loop
mov al,0 
stosb
pop edx ecx
ret

StrToInt:
; edi = buffer, ebx = base
push    edx edi
xor eax,eax
xor edx,edx
 .loop:
mov dl,byte [edi]
test    dl,dl
jz  .end
imul    eax,ebx
sub dl,'0'
cmp dl,9
jle .ok
sub dl,7
  .ok:
add eax,edx
inc edi
jmp .loop
  .end:
pop edi edx
ret

section '.data' data readable writeable

h404 db 'HTTP/1.1 404 Not Found',13,10,13,10,'<HTML><BODY>404 Not Found</BODY></HTML>',10,13
.len = $ - h404
h200 db 'HTTP/1.1 200 OK',13,10,13,10
.len = $ - h200

transmitbuffer dd h200,h200.len,NULL,NULL

bindparms dw 2, 0
          dd 0, 0, 0

wsadata WSADATA
stdout rd 1
peeraddr rb 16
port rd 1
strlen rd 1
multiplier rd 1
integer rd 1
sixteen dd 16
ten dd 10
sockfd rd 1
peer rd 1
fd rd 1
fdlen rd 1
buffer rb 512
bufferlen = $ - buffer

section '.idata' import data readable writeable

library kernel,'KERNEL32.DLL',\
        winsock,'WSOCK32.DLL',\
        mswsock,'MSWSOCK.DLL'

import  kernel,\
        GetStdHandle,'GetStdHandle',\
        ExitProcess,'ExitProcess',\
        WriteConsole,'WriteConsoleA',\
        CreateFile,'CreateFileA',\
        CloseHandle,'CloseHandle',\
        GetCommandLine,'GetCommandLineA'

import  winsock,\
        WSAStartup,'WSAStartup',\
        WSACleanup,'WSACleanup',\
        WSAAsyncSelect,'WSAAsyncSelect',\
        gethostbyname,'gethostbyname',\
        socket,'socket',\
        bind,'bind',\
        listen,'listen',\
        accept,'accept',\
        connect,'connect',\
        recv,'recv',\
        send,'send',\
        closesocket,'closesocket'

import  mswsock,\
        TransmitFile,'TransmitFile'
    


Some warnings:
- It's ugly, and has no comments
- It's not multithreaded, so only one connection at a time
- To change port, you'll have to modify that constant at the top and re-assemble using fasm
- those StrtoInt and IntToStr functions are not mine, i copied them from someone who posted them on this board, i'm sorry to whoever it was who wrote them, i keep forgetting your name Sad

Apart from that.. it gets the job done. I should really update it to use threads and such, but I rarely use it, i usually use the linux version (which this one was ported from), so thats gotten more of my attention.

EDIT:
Oh yeah, couple more things..
Run it from a command prompt, since it has no GUI.

Also, the directory you run it from will be the root of the webserver.
(eg: if you run it in C:\dir1, then to access c:\dir1\file.txt, you would use the address: http://127.0.0.1/file.txt). You can also of course do subdirectories, eg: http://127.0.0.1/dir2/file2.txt. And I believe this version of the httpd still has the horrible flaw of being able to do: http://127.0.0.1/../../someotherdir/yourprivatefiles.txt. This can be fixed by doing some further parsing of the URL, but I didnt need it for what i was using the httpd for, so i never implemented it. In the linux one, i was able to simply chroot() which doesnt allow you to go above a certain directory, so that worked fine, I dont think the same exists on windows though. So yeah, not to be used for hosting public stuff, unless your sure you have nothing of value or secretive on your computer.. I coded this because i needed an easy way to transfer stuff over the lan.. so it isnt secure in the slightest.

It should also handle files with spaces fine.. The only thing is files over 2GB, i dont think i included large file support, so just use ftp or something Smile

Now that i remember, this code doesnt even send the size of the file in the header. This isnt a problem, you can still send files fine without saying how big they are, the server simply closes the connection when the file is finished sending, and the client understands that as the end of file. The only thing is that you wont have a progress bar on the client end, as the program will not know the size of the full file.
Post 15 Aug 2007, 21:49
View user's profile Send private message Reply with quote
OzzY



Joined: 19 Sep 2003
Posts: 1029
Location: Everywhere
OzzY 16 Aug 2007, 17:46
Thanks gunblade! Your example works!
But I couldn't learn much, as you said this code is ugly.

I'm trying to craft a little server like this in HLL, to see if it works.
Until now, my server works this way:

Browser sends:
GET / HTTP/1.1
(and other stuff

My server answers:
HTTP/1.1 200 OK\r\n\r\n
[data of index.html]

Browser sends:
GET file.zip HTTP/1.1
My server answers:
HTTP/1.1 200 OK\r\n\r\n
[data of file.zip]

But unfortunately the index.html isn't showing on the browser.
What did I do wrong?
Post 16 Aug 2007, 17:46
View user's profile Send private message Reply with quote
gunblade



Joined: 19 Feb 2004
Posts: 209
gunblade 16 Aug 2007, 17:52
Could be several things.. you made sure you close the connection after sending the contents of index.html?

If it isnt that.. im not sure what it could be, you might want to get a network packet sniffer like wireshark, with which you would be able to look at the packet data, and make sure that you are actually sending what you think your sending.. But i still think the first thing to check is that you are closing the connection after sending the data. The client (browser) will create a new connection for each file it wants.

If that doesnt fix it, you might have to post your code, as i cant think of any other reasons without actually seeing the code.
Post 16 Aug 2007, 17:52
View user's profile Send private message Reply with quote
OzzY



Joined: 19 Sep 2003
Posts: 1029
Location: Everywhere
OzzY 16 Aug 2007, 18:23
Nevermind... I did it! Works now! Very Happy
ButI did it in Tcl, as it's a very easy scripting language.
Now, I understand the concept, I can do it in ASM.

If anyone wants to see the Tcl code before I translate it to ASM, tell me, so I can post.
Post 16 Aug 2007, 18:23
View user's profile Send private message Reply with quote
OzzY



Joined: 19 Sep 2003
Posts: 1029
Location: Everywhere
OzzY 16 Aug 2007, 18:31
And it doesn't have the security flaw ../../, because it strips everything before the name, like:
If the name is: /../something.txt
it will strip to:
something.txt
and check if file exists, and if it exists it will send it!
Very Happy
Post 16 Aug 2007, 18:31
View user's profile Send private message Reply with quote
OzzY



Joined: 19 Sep 2003
Posts: 1029
Location: Everywhere
OzzY 16 Aug 2007, 18:35
Now I have a problem:
It just sends text/ASCII files. I can't send binary files.
Any idea?
Post 16 Aug 2007, 18:35
View user's profile Send private message Reply with quote
gunblade



Joined: 19 Feb 2004
Posts: 209
gunblade 16 Aug 2007, 18:50
What do you mean you cant send binary? as in.. the browser simply displays the binary instead of actually downloading it?
Post 16 Aug 2007, 18:50
View user's profile Send private message Reply with quote
OzzY



Joined: 19 Sep 2003
Posts: 1029
Location: Everywhere
OzzY 16 Aug 2007, 19:09
No. It opens the download dialog, but it saves nothing.
Post 16 Aug 2007, 19:09
View user's profile Send private message Reply with quote
gunblade



Joined: 19 Feb 2004
Posts: 209
gunblade 16 Aug 2007, 19:21
I cant think why, the code might help if you dont mind uploading it. It's strange that text works but binary doesnt, but yeah, upload, and ill take a look.
Post 16 Aug 2007, 19:21
View user's profile Send private message Reply with quote
r22



Joined: 27 Dec 2004
Posts: 805
r22 17 Aug 2007, 00:50
Your Content-Type AND/OR content-length is probably wrong in your response HEADER.

Content-Type: application/octet-stream
Should be used, this will allow you to send bytes ad binary data.

Content-Length: 999999
should be the bytes of data your a sending
Then client will try to receive these bytes to place them in a file.
Post 17 Aug 2007, 00:50
View user's profile Send private message AIM Address Yahoo Messenger Reply with quote
OzzY



Joined: 19 Sep 2003
Posts: 1029
Location: Everywhere
OzzY 17 Aug 2007, 02:56
I made it! Very Happy
The problem was that I was not configuring the socket channel to binary translation (that's Tcl especific feature).
Now that I got it working in Tcl, I can try to make an ASM version. Very Happy
Post 17 Aug 2007, 02:56
View user's profile Send private message Reply with quote
0.1



Joined: 24 Jul 2007
Posts: 474
Location: India
0.1 27 Sep 2007, 09:18
I am waiting for ASM version ...
... and today is 7th day!
Post 27 Sep 2007, 09:18
View user's profile Send private message Reply with quote
sleepsleep



Joined: 05 Oct 2006
Posts: 12782
Location: ˛                             ⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣Posts: 0010456
sleepsleep 01 Oct 2007, 22:23
maybe a lightweight soap server?
Post 01 Oct 2007, 22:23
View user's profile Send private message Reply with quote
Display posts from previous:
Post new topic Reply to topic

Jump to:  
Goto page 1, 2  Next

< Last Thread | Next Thread >
Forum Rules:
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You can download files in this forum


Copyright © 1999-2024, Tomasz Grysztar. Also on GitHub, YouTube.

Website powered by rwasa.