213 lines
6.9 KiB
Text
213 lines
6.9 KiB
Text
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
;; Crossplatform(?) Web Server example using UASM's OO Language extention
|
|
;;
|
|
;; Linux Build:
|
|
;; $ uasm -elf64 websrv.asm
|
|
;; $ gcc -o websrv websrv.o -no-pie
|
|
;; With MUSL libc
|
|
;; $ musl-gcc -o websrv websrv.o -e main -nostartfiles -no-pie
|
|
;;
|
|
;; Windows Build:
|
|
;; $ uasm64 -win64 websrv.asm
|
|
;; $ link /machine:x64 /subsystem:console /release websrv.obj
|
|
;; kernel32.lib msvcrt.lib ws2_32.lib
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
|
|
option casemap:none
|
|
option literals:on ;; Usually on by default buuuuuut...
|
|
|
|
WIN64 equ 1
|
|
LIN64 equ 3
|
|
|
|
|
|
ifndef __WEBSRV_CLASS__
|
|
__WEBSERV_CLASS__ equ 1
|
|
|
|
AF_INET equ 2
|
|
SOCK_STREAM equ 1
|
|
INADDR_ANY equ 0
|
|
|
|
in_addr struct
|
|
s_addr dd ?
|
|
in_addr ends
|
|
|
|
sockaddr struct
|
|
sa_family dw ?
|
|
sa_data db 14 dup (?)
|
|
sockaddr ends
|
|
|
|
sockaddr_in struct
|
|
sin_family dw ?
|
|
sin_port dw ?
|
|
sin_addr in_addr <?>
|
|
sin_zero db 8 dup (?)
|
|
sockaddr_in ends
|
|
|
|
WSADATA struct
|
|
wVersion dw ?
|
|
wHighVersion dw ?
|
|
iMaxSockets dw ?
|
|
iMaxUdpDg dw ?
|
|
szDescription db 256 dup (?)
|
|
szSystemStatus db 128 dup (?)
|
|
lpVendorInfo dq ?
|
|
WSADATA ends
|
|
|
|
;; Platform specific requirements etc..
|
|
if @Platform eq WIN64
|
|
;;include/includelibs can be used here. But this works too.
|
|
option dllimport:<kernel32>
|
|
ExitProcess proto ucode:dword
|
|
HeapAlloc proto fd:qword, flgs:dword, hlen:qword
|
|
HeapFree proto fd:qword, flgs:dword, lpmem:qword
|
|
GetProcessHeap proto
|
|
option dllimport:<msvcrt>
|
|
printf proto fmt:qword, args:VARARG
|
|
strlen proto buff:qword
|
|
option dllimport:<ws2_32>
|
|
WSAStartup proto ver:word, wsa:qword
|
|
WSACleanup proto wsa:qword
|
|
closesocket proto fd:dword
|
|
socket proto d:dword, s:dword, prtl:dword
|
|
bind proto fd:dword, saddr:qword, slen:dword
|
|
listen proto fd:dword, blog:dword
|
|
accept proto fd:dword, caddr:qword, slen:qword
|
|
send proto fd:dword, buff:qword, blen:dword, flgs:dword
|
|
option dllimport:none
|
|
exit equ ExitProcess
|
|
close equ closesocket
|
|
elseif @Platform eq LIN64
|
|
;; Required proto from Libc stuff.
|
|
malloc proto SYSTEMV mem:qword ;; Required by the class macros.
|
|
free proto SYSTEMV mem:qword ;; It uses HeapAlloc on windows.
|
|
printf proto SYSTEMV fmt:qword, args:VARARG
|
|
strlen proto SYSTEMV buff:qword
|
|
socket proto SYSTEMV d:dword, s:dword, prtl:dword
|
|
bind proto SYSTEMV fd:dword, saddr:qword, slen:dword
|
|
listen proto SYSTEMV fd:dword, blog:dword
|
|
accept proto SYSTEMV fd:dword, saddr:qword, slen:qword
|
|
send proto SYSTEMV fd:dword, buff:qword, blen:dword, flgs:dword
|
|
close proto SYSTEMV fd:dword
|
|
exit proto SYSTEMV uexit:dword
|
|
else
|
|
;; Could do some OSX or w/e specific crap, but I don't use
|
|
;; a Mac so, I dunno shit about it's API :]
|
|
endif
|
|
|
|
;; Class definitions etc..
|
|
CLASS websrv
|
|
;; Class Method definitions
|
|
CMETHOD serve
|
|
ENDMETHODS
|
|
;; Class Variables.
|
|
if @Platform eq WIN64
|
|
wsa WSADATA <?>
|
|
endif
|
|
tmpl db "[websrv->%s] - %s",10,0
|
|
http db "HTTP/1.1 200 OK",13,10,
|
|
"Content-Type: text/html; charset=UTF-8",13,10,13,10,
|
|
"<html><head><title>Goodbye</title></head><body>Goodbye, World!</body></html>",0
|
|
sock dd 0
|
|
port dw 8080
|
|
ENDCLASS
|
|
|
|
pwebsrv typedef ptr websrv
|
|
|
|
;; Method implementation..
|
|
; Syntax:
|
|
; METHOD ClassName, MethodName, <ReturnType>, <USE extra regs for ret>, args..
|
|
METHOD websrv, Init, <VOIDARG>, <>
|
|
local x:sockaddr_in
|
|
|
|
mov rbx, thisPtr ;; Force the ThisPtr reference reg to be RBX 'cause of windoze
|
|
assume rbx:ptr websrv ;; its default is RCX, and RDI on linux. *shrugs*
|
|
invoke printf, addr [rbx].tmpl,CSTR("init"), CSTR("Starting...")
|
|
if @Platform eq WIN64
|
|
invoke WSAStartup, 200h, addr [rbx].wsa
|
|
endif
|
|
invoke socket, AF_INET, SOCK_STREAM, 0
|
|
.if rax == -1
|
|
invoke printf, addr [rbx].tmpl, CSTR("init:ERROR"), CSTR("Socket() returned < 0")
|
|
mov rax, rbx
|
|
ret
|
|
.endif
|
|
mov [rbx].sock, eax
|
|
invoke printf, CSTR("[websrv->init:socket] - %d",10), eax
|
|
mov x.sin_family, AF_INET
|
|
mov x.sin_addr.s_addr, INADDR_ANY
|
|
mov ax, [rbx].port
|
|
xchg al,ah
|
|
mov x.sin_port, ax
|
|
invoke bind, [rbx].sock, addr x, sizeof(x)
|
|
.if eax == -1
|
|
invoke printf, addr [rbx].tmpl, CSTR("init:ERROR") , CSTR("Bind failed.")
|
|
xor eax, eax
|
|
mov [rbx].sock, 0
|
|
mov rax, rbx
|
|
ret
|
|
.endif
|
|
invoke printf, addr [rbx].tmpl, CSTR("init"), CSTR("Bind successful.")
|
|
mov rax, rbx
|
|
assume rbx: nothing
|
|
ret
|
|
ENDMETHOD
|
|
|
|
METHOD websrv, serve, <VOIDARG>, <>
|
|
local tmp:qword
|
|
local cfd:dword
|
|
local x:sockaddr
|
|
|
|
mov rbx, thisPtr
|
|
assume rbx:ptr websrv
|
|
.if [rbx].sock == 0
|
|
ret
|
|
.endif
|
|
invoke printf, addr [rbx].tmpl,CSTR("serve"), CSTR("Listening for incomming connections")
|
|
invoke listen, [rbx].sock, 5
|
|
.if rax == -1
|
|
invoke printf, addr [rbx].tmpl, CSTR("serve:ERROR"), CSTR("Listen() returned -1")
|
|
ret
|
|
.endif
|
|
|
|
.while(1)
|
|
mov tmp, sizeof(x)
|
|
invoke accept, [rbx].sock, addr x, addr tmp
|
|
.if eax == -1
|
|
invoke printf, addr [rbx].tmpl, CSTR("serve:ERROR"), CSTR("Accept() returned -1")
|
|
ret
|
|
.endif
|
|
mov cfd, eax
|
|
invoke printf, addr [rbx].tmpl, CSTR("serve"), CSTR("Connection established.")
|
|
invoke strlen, addr [rbx].http
|
|
invoke send, cfd, addr [rbx].http, eax , 0
|
|
invoke close, cfd
|
|
.endw
|
|
assume rbx:nothing
|
|
ret
|
|
ENDMETHOD
|
|
|
|
METHOD websrv, Destroy, <VOIDARG>, <>
|
|
mov rbx, thisPtr
|
|
assume rbx:ptr websrv
|
|
invoke printf, addr [rbx].tmpl,CSTR("destroy"), CSTR("Calling Close and exit.")
|
|
invoke close, [rbx].sock
|
|
if @Platform eq WIN64
|
|
invoke WSACleanup, addr [rbx].wsa
|
|
endif
|
|
assume rbx:nothing
|
|
invoke exit, 0
|
|
ret
|
|
ENDMETHOD
|
|
endif ;; __WEBSRV_CLASS__
|
|
|
|
;; Start of main run code...
|
|
.code
|
|
main proc
|
|
local server:ptr websrv
|
|
|
|
mov server, _NEW(websrv)
|
|
server->serve()
|
|
_DELETE(server)
|
|
ret
|
|
main endp
|
|
end
|