;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; ______ __ _ _ _ _ _ _ _ ;
; /#####/\ /###| /#/\ /#/\ /#/\ /########/\ ;
; /#/\_\_\/ /#/|#| /#/\/ /#/\//#/\/ /#/\/ /#/\/ ;
; /#/\/ /#/ |#| /#/\/ /#/\//#/\/ /#/\/ /#/\/ ;
; /#####/\ /#/\/|#|/#/\/ /######/_/ /#/\/ /#/\/ ;
; /#/\_\_\/ /#/\/ |# #/\/ /#/\/ \#\ /#/\/ /#/\/ ;
; /#/\/ /#/\/ |##/\/ /#/\/ \#\ /#/\/_ /#/\/ ;
; /#/\/______/#/\/___|#/\/ /#/\/_____\#\//########/\/ ;
; /#################################################/\ ;
; \_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\/ ;
; ;
;-------------------------------------------------------------------------------
; Project: small http file server
; Version: 1.0.0.0
; Description: a smal http server that can handle the GET method only.
; Date: 15/10/08
; Autor: enkoreaver@gmail.com
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
format PE Console
entry start
include '%fasminc%/win32a.inc'
include '%fasminc%/macro/if.inc'
MAX_QUEUE equ 100 ;max namber of pending connections
BUFFER_SIZE equ 2048 ;max size of the header sended by the client
MAX_URL_SIZE equ 1024 ;max size of url in the header sended
SHOW_DETAILED_MSG equ TRUE ;set TRUE if want to see the full client message
section '.data' data readable writeable
wsa WSADATA
port dd 80
szPause db "PAUSE",0
h404 db "HTTP/1.1 404 Not Found",13,10,"Server: EnkoHttpServer 1.0.0.0 ",13,10,13,10,"
404 Not Found",13,10
.size = $ - h404
h200 db "HTTP/1.1 200 OK",13,10,"Server: EnkoHttpServer 1.0.0.0 ",13,10,"Allow: GET",13,10,13,10
.size = $ - h200
szRoot db "D:\Documentos\Enko\Assembly\Projects\httpServer",0
szSlashes db '/\',0
szSlash db '\',0
szTockens db " ",13,10,0
szError db "ERROR: %i",13,10,0
szDot db ".",0
szFileNotExists db "File Not Exists",13,10,0
szInt db "%i",0
szFile db "FILE: %s",13,10,0
szClient db "Client IP: %s",13,10,0
szRequest db "REQUEST: %s",13,10,0
szStatus db "STATUS: %s",13,10,0
szString db "%s",0
szEndLine db 13,10,0
.size = $ - szEndLine
szBr db "
",0
szIndex db "index.html",0
szFileSended db "File sended ok",13,10,0
.size = $ - szBr
wSocketVersion dd 0x0101
transmiteBuffer dd h200,h200.size,NULL,NULL
thread dd ?
peer dd ?
peerAddr sockaddr_in
sizePeerAddr dd sizeof.sockaddr_in
sock dd ?
sock_addr sockaddr_in
szBuffer db 32 dup ?
szIp db 16 dup ?
section '.code' code readable executable
start:
;inti the socket
invoke WSAStartup, [wSocketVersion], wsa
invoke socket,AF_INET,SOCK_STREAM,NULL
mov [sock],eax
mov [sock_addr.sin_family], AF_INET
invoke htons,[port]
mov [sock_addr.sin_port],ax
mov [sock_addr.sin_addr],NULL
invoke bind, [sock], sock_addr,sizeof.sockaddr_in
.if eax <> 0
invoke WSAGetLastError
cinvoke printf, szError, eax
.endif
invoke listen, [sock],MAX_QUEUE
accepted:
;socket listening
invoke accept, [sock],peerAddr,sizePeerAddr
mov [peer],eax
stdcall ipToString,[peerAddr.sin_addr],szIp
cinvoke printf, szClient,szIp
;new thread for each connection
invoke CreateThread, NULL,NULL, resolveConnection,[peer],NULL,NULL
jmp accepted
invoke ExitProcess,0
;the connection manager
proc resolveConnection, lpParam
local lpeer: DWORD, lbuffer: DWORD, lurl: DWORD, lfile: DWORD
mov eax, [lpParam]
mov [lpeer],eax
cinvoke malloc, BUFFER_SIZE
mov [lbuffer],eax
invoke recv, [lpeer],[lbuffer],BUFFER_SIZE,0
;if there is a message then continue
.if eax <> 0
mov ebx,[lbuffer]
mov byte [ebx+eax],0
.if SHOW_DETAILED_MSG
cinvoke printf,szRequest, [lbuffer]
.endif
cinvoke strtok, [lbuffer], szTockens
.if eax <> 0
;handling the GET message
.if dword[eax] = "GET"
;url sring allocation
;getting the URL from GET message
cinvoke malloc, MAX_URL_SIZE
mov [lurl],eax
cinvoke strcpy, [lurl],szRoot
cinvoke strtok, NULL, szTockens
cinvoke strcat,[lurl],eax
mov ebx,eax
cinvoke strlen, eax
mov edx,eax
dec edx
.repeat
dec eax
cmp byte[ebx+eax],"/"
.if ZERO?
mov byte[ebx+eax],"\"
.endif
.until eax = 0
.if byte[ebx+edx] = "\"
cinvoke strcat,[lurl],szIndex
.endif
cinvoke printf, szFile, [lurl]
;opening the file to send to browser
invoke CreateFile,[lurl],GENERIC_READ,FILE_SHARE_READ,0,OPEN_EXISTING,FILE_ATTRIBUTE_ARCHIVE,0
;file exists, sending,,,,
.if eax <> INVALID_HANDLE_VALUE
mov [lfile],eax
invoke GetFileSize, [lfile],NULL
invoke TransmitFile, [lpeer],[lfile],eax,NULL,NULL,transmiteBuffer,NULL
.if eax
cinvoke printf, szStatus, szFileSended
.endif
invoke CloseHandle, [lfile]
.else
cinvoke printf, szStatus, szFileNotExists
invoke send, [lpeer], h404, h404.size, 0
.endif
cinvoke free, [lurl]
.endif
.endif
.endif
.exit:
cinvoke free, [lbuffer]
invoke CloseHandle, [lpeer]
invoke ExitThread
ret
endp
;convert DWORD ip to ip sring for displaying later
proc ipToString, ip, string
local buffer: DWORD
mov ebx, [ip]
mov esi,4
mov eax,[string]
mov byte [eax],0
.repeat
xor eax,eax
mov al,bl
cinvoke sprintf,[buffer],szInt,eax
cinvoke strcat,[string],[buffer]
cinvoke strcat,[string],szDot
shr ebx,8
dec esi
.until esi=0
cinvoke strlen, [string]
mov ebx, [string]
mov byte[ebx+eax-1],0
mov byte[buffer],0
ret
endp
section '.idata' import data readable writeable
library kernel32,'KERNEL32.DLL',\
user32,'USER32.DLL',\
msvcrt,'msvcrt.dll',\
wsock32, 'WSOCK32.DLL'
include '%fasminc%\apia\kernel32.inc'
include '%fasminc%\apia\user32.inc'
include '%fasminc%\apia\msvcrt.inc'
include '%fasminc%\apia\wsock32.inc'