forked from KolibriOS/kolibrios
0ceaac39cf
git-svn-id: svn://kolibrios.org@661 a494cfbc-eb01-0410-851d-a64ba20cac60
1516 lines
32 KiB
NASM
1516 lines
32 KiB
NASM
;
|
|
; HTTPC.ASM
|
|
;
|
|
; Compile with FASM for Menuet ( v1.40 for DOS )
|
|
;
|
|
; This program implements a very simple web browser
|
|
;
|
|
; Version 0.4 2nd December 2003 Mike Hibbett
|
|
; Enabled lowercase/uppcase characters in URL
|
|
; Version 0.3 30th November 2003 Mike Hibbett
|
|
; Fixed bug with tcp socket opne - uses unique port
|
|
; Version 0.2 27th November 2003 Mike Hibbett
|
|
; Added user entry of url, and implements url -> IP address
|
|
; resolution through DNS
|
|
;
|
|
; Version 0.1 Ville Mikael Turjanmaa
|
|
; Original version
|
|
|
|
|
|
; Enabling debugging puts stuff to the debug board
|
|
DEBUGGING_ENABLED equ 1
|
|
DEBUGGING_DISABLED equ 0
|
|
DEBUGGING_STATE equ DEBUGGING_DISABLED
|
|
|
|
use32
|
|
org 0x0
|
|
db 'MENUET01' ; header
|
|
dd 0x01 ; header version
|
|
dd START ; entry point
|
|
dd I_END ; image size
|
|
dd 0x100000 ; required memory
|
|
dd 0x100000 ; esp
|
|
dd 0x0 , 0x0 ; I_Param , I_Path
|
|
|
|
include 'lang.inc'
|
|
include 'macros.inc'
|
|
;include "DEBUG.INC"
|
|
|
|
URLMAXLEN equ 50 ; maximum length of url string
|
|
|
|
; Memory usage
|
|
; webpage source file at 0x10000
|
|
; decoded text page at 0x20000
|
|
; text attribute 0x30000 (1 = normal, 2 = bold, 128+ = link)
|
|
|
|
START: ; start of execution
|
|
|
|
;dps <"Program started",13,10>
|
|
|
|
mov eax,40 ; Report events
|
|
mov ebx,10000111b ; Stack 8 + defaults
|
|
mcall
|
|
|
|
red: ; redraw
|
|
call draw_window
|
|
|
|
still:
|
|
mov eax,23 ; wait here for event
|
|
mov ebx,1
|
|
mcall
|
|
|
|
cmp eax,1 ; redraw request ?
|
|
je red
|
|
cmp eax,2 ; key in buffer ?
|
|
je key
|
|
cmp eax,3 ; button in buffer ?
|
|
je button
|
|
|
|
; Get the web page data from the remote server
|
|
call read_incoming_data
|
|
|
|
mov eax,[status]
|
|
mov [prev_status],eax
|
|
|
|
mov eax,53
|
|
mov ebx,6
|
|
mov ecx,[socket]
|
|
mcall
|
|
|
|
mov [status],eax
|
|
|
|
cmp [prev_status],4
|
|
jge no_send
|
|
cmp [status],4
|
|
jne no_send
|
|
|
|
mov [onoff],1
|
|
|
|
call send_request
|
|
|
|
no_send:
|
|
call print_status
|
|
|
|
cmp [prev_status],4
|
|
jne no_close
|
|
cmp [status],4 ; connection closed by server
|
|
jbe no_close ; respond to connection close command
|
|
; draw page
|
|
|
|
call read_incoming_data
|
|
|
|
mov eax,53
|
|
mov ebx,8
|
|
mov ecx,[socket]
|
|
mcall
|
|
|
|
call draw_page
|
|
|
|
mov [onoff],0
|
|
|
|
no_close:
|
|
jmp still
|
|
|
|
key: ; key
|
|
mov eax,2 ; just read it and ignore
|
|
mcall
|
|
shr eax,8
|
|
cmp eax,184
|
|
jne no_down
|
|
cmp [display_from],25
|
|
jb no_down
|
|
sub [display_from],25
|
|
call display_page
|
|
|
|
no_down:
|
|
cmp eax,183
|
|
jne no_up
|
|
add [display_from],25
|
|
call display_page
|
|
|
|
no_up:
|
|
jmp still
|
|
|
|
button: ; button
|
|
;dps <"Button pressed",13,10>
|
|
mov eax,17 ; get id
|
|
mcall
|
|
cmp ah,1 ; button id=1 ?
|
|
jne noclose
|
|
|
|
;dps "Closing socket before exit... "
|
|
|
|
mov eax, 53
|
|
mov ebx, 8
|
|
mov ecx, [socket]
|
|
mcall
|
|
|
|
;dpd eax
|
|
;dps <13,10>
|
|
|
|
exit:
|
|
or eax,-1 ; close this program
|
|
mcall
|
|
|
|
noclose:
|
|
cmp ah,31
|
|
jne noup
|
|
sub [display_from],20
|
|
call display_page
|
|
jmp still
|
|
|
|
noup:
|
|
cmp ah,32
|
|
jne nodown
|
|
add [display_from],20
|
|
call display_page
|
|
jmp still
|
|
|
|
nodown:
|
|
cmp ah, 10 ; Enter url
|
|
jne nourl
|
|
|
|
mov [addr],dword document_user
|
|
mov [ya],dword 38
|
|
mov [len],dword URLMAXLEN
|
|
|
|
mov ecx,[len]
|
|
mov edi,[addr]
|
|
mov al,' '
|
|
rep stosb
|
|
|
|
call print_text
|
|
|
|
mov edi,[addr]
|
|
|
|
f11:
|
|
mov eax,10
|
|
mcall
|
|
cmp eax,2 ; key?
|
|
jz fbu
|
|
jmp still
|
|
|
|
fbu:
|
|
mov eax,2
|
|
mcall ; get key
|
|
shr eax,8
|
|
cmp eax,8
|
|
jnz nobs
|
|
cmp edi,[addr]
|
|
jz f11
|
|
sub edi,1
|
|
mov [edi],byte ' '
|
|
call print_text
|
|
jmp f11
|
|
|
|
nobs:
|
|
cmp eax, dword 10
|
|
je retkey
|
|
cmp eax, dword 13
|
|
je retkey
|
|
|
|
cmp eax,dword 31
|
|
jbe f11
|
|
|
|
; Removed in v0.4
|
|
; cmp eax,dword 95
|
|
; jb keyok
|
|
; sub eax,32
|
|
|
|
keyok:
|
|
mov [edi],al
|
|
|
|
call print_text
|
|
|
|
add edi,1
|
|
mov esi,[addr]
|
|
add esi,URLMAXLEN
|
|
cmp esi,edi
|
|
jnz f11
|
|
|
|
jmp still
|
|
|
|
retkey:
|
|
mov ah, 22 ; start load
|
|
|
|
nourl:
|
|
call socket_commands ; opens or closes the connection
|
|
jmp still
|
|
|
|
|
|
;****************************************************************************
|
|
; Function
|
|
; send_request
|
|
;
|
|
; Description
|
|
; Transmits the GET request to the server.
|
|
; This is done as GET then URL then HTTP/1.0',13,10,13,10 in 3 packets
|
|
;
|
|
;****************************************************************************
|
|
send_request:
|
|
pusha
|
|
mov eax,53 ; 'GET '
|
|
mov ebx,7
|
|
mov ecx,[socket]
|
|
mov edx,4
|
|
mov esi,string0
|
|
mcall
|
|
|
|
mov edx,0
|
|
|
|
next_edx:
|
|
; Determine the length of the url to send in the GET request
|
|
inc edx
|
|
cmp [edx+document],byte ' '
|
|
jne next_edx
|
|
|
|
mov eax,53 ; document_user
|
|
mov ebx,7
|
|
mov ecx,[socket]
|
|
mov esi,document
|
|
mcall
|
|
|
|
mov eax,53 ; ' HTTP/1.0 .. '
|
|
mov ebx,7
|
|
mov ecx,[socket]
|
|
mov edx,stringh_end-stringh
|
|
mov esi,stringh
|
|
mcall
|
|
|
|
popa
|
|
ret
|
|
|
|
|
|
;****************************************************************************
|
|
; Function
|
|
; print_status
|
|
;
|
|
; Description
|
|
; displays the socket/data received status information
|
|
;
|
|
;****************************************************************************
|
|
print_status:
|
|
pusha
|
|
|
|
mov eax,26
|
|
mov ebx,9
|
|
mcall
|
|
|
|
cmp eax,[nextupdate]
|
|
jb status_return
|
|
|
|
add eax,25
|
|
|
|
mov [nextupdate],eax
|
|
|
|
mov eax,13
|
|
mov ebx,5*65536+100
|
|
mov ecx,[winys]
|
|
shl ecx,16
|
|
add ecx,-18*65536+10
|
|
mov edx,0xffffff
|
|
mcall
|
|
|
|
mov eax,47
|
|
mov ebx,3*65536
|
|
mov ecx,[status]
|
|
mov edx,12*65536-18
|
|
add edx,[winys]
|
|
mov esi,0x000000
|
|
mcall
|
|
|
|
mov eax,47
|
|
mov ebx,6*65536
|
|
mov ecx,[pos]
|
|
mov edx,40*65536-18
|
|
add edx,[winys]
|
|
mov esi,0x000000
|
|
mcall
|
|
|
|
status_return:
|
|
popa
|
|
ret
|
|
|
|
|
|
;****************************************************************************
|
|
; Function
|
|
; read_incoming_data
|
|
;
|
|
; Description
|
|
; receive the web page from the server, storing it without processing
|
|
;
|
|
;****************************************************************************
|
|
read_incoming_data:
|
|
cmp [onoff],1
|
|
je rid
|
|
ret
|
|
|
|
rid:
|
|
mov ecx,-1
|
|
|
|
newbyteread:
|
|
mov eax, 53
|
|
mov ebx, 2
|
|
mov ecx, [socket]
|
|
mcall
|
|
|
|
cmp eax,0
|
|
je no_more_data
|
|
|
|
read_more:
|
|
mov eax, 53
|
|
mov ebx, 3
|
|
mov ecx, [socket]
|
|
mcall
|
|
|
|
yesm:
|
|
inc [pos]
|
|
mov ecx,[pos]
|
|
mov [0x10000+ecx],bl
|
|
|
|
call print_status
|
|
|
|
cmp eax,0
|
|
jne read_more
|
|
|
|
mov eax,5
|
|
mov ebx,50
|
|
mcall
|
|
|
|
jmp newbyteread
|
|
|
|
no_more_data:
|
|
ret
|
|
|
|
|
|
;****************************************************************************
|
|
; Function
|
|
; draw_page
|
|
;
|
|
; Description
|
|
; parses the web page data, storing displayable data at 0x20000
|
|
; and attributes at 0x30000. It then calls display_page to render
|
|
; the data
|
|
;
|
|
;****************************************************************************
|
|
draw_page:
|
|
pusha
|
|
mov esi,0
|
|
mov [command_on_off],0
|
|
|
|
newlettercheck:
|
|
movzx eax,byte [esi+0x10000]
|
|
cmp al,'<'
|
|
jne no_c_on
|
|
mov [command_on_off],1
|
|
|
|
no_c_on:
|
|
cmp al,'>'
|
|
jne no_c_off
|
|
mov [command_on_off],0
|
|
|
|
no_c_off:
|
|
cmp [command_on_off],0
|
|
je no_lower_case
|
|
|
|
cmp eax,96
|
|
jg no_lower_case
|
|
cmp eax,65
|
|
jb no_lower_case
|
|
add eax,32
|
|
|
|
no_lower_case:
|
|
mov [esi+0x10000],al
|
|
inc esi
|
|
cmp esi,[pos]
|
|
jbe newlettercheck
|
|
mov edi,0x30000
|
|
mov ecx,0x10000
|
|
mov al,0
|
|
cld
|
|
rep stosb
|
|
mov [text_type],1
|
|
mov [command_on_off],0
|
|
|
|
mov esi,0
|
|
mov ecx,[pos]
|
|
|
|
; search for double lf
|
|
|
|
find_dlf:
|
|
cmp [0x10000+esi-4],dword 0x0d0a0d0a
|
|
je found_dlf
|
|
cmp [0x10000+esi-4],dword 0x0a0d0a0d
|
|
je found_dlf
|
|
cmp [0x10000+esi-2],word 0x0d0d
|
|
je found_dlf
|
|
cmp [0x10000+esi-2],word 0x0a0a
|
|
je found_dlf
|
|
|
|
cmp esi,5500
|
|
je found_dlf
|
|
|
|
inc esi
|
|
|
|
jmp find_dlf
|
|
|
|
found_dlf:
|
|
newbyte:
|
|
mov al,[esi+0x10000]
|
|
cmp al,'<'
|
|
jne no_command_on
|
|
mov [command_on_off],1
|
|
|
|
no_command_on:
|
|
cmp al,'>'
|
|
jne no_command_off
|
|
mov [command_on_off],0
|
|
jmp byte_done
|
|
|
|
no_command_off:
|
|
mov eax,[esi+0x10000] ; <!--
|
|
cmp eax,'<!--'
|
|
jne no_com2_start
|
|
mov [com2],1
|
|
|
|
no_com2_start:
|
|
mov ax,[esi+0x10000] ; -->
|
|
cmp ax,'->'
|
|
jne no_com2_end
|
|
mov [com2],0
|
|
inc esi
|
|
jmp byte_done
|
|
|
|
no_com2_end:
|
|
mov eax,[esi+0x10000] ; <script
|
|
cmp eax,'<scr'
|
|
jne no_script_start
|
|
mov [script],1
|
|
|
|
no_script_start:
|
|
mov eax,[esi+0x10000] ; /script>
|
|
cmp eax,'</sc'
|
|
jne no_script_end
|
|
mov [script],0
|
|
inc esi
|
|
jmp byte_done
|
|
|
|
no_script_end:
|
|
cmp [command_on_off],0
|
|
jne no_print
|
|
|
|
cmp [com2],0
|
|
jne no_print
|
|
|
|
cmp [script],0
|
|
jne no_print
|
|
|
|
mov al,[esi+0x10000] ; &
|
|
cmp al,'&'
|
|
jne no_nbsp
|
|
|
|
newsps:
|
|
inc esi
|
|
mov al,[esi+0x10000] ;
|
|
cmp al,';'
|
|
jne newsps
|
|
jmp byte_done
|
|
|
|
no_nbsp:
|
|
cmp al,13
|
|
jne no_lb
|
|
jmp byte_done
|
|
|
|
no_lb:
|
|
cmp al,10
|
|
jne no_lf
|
|
jmp byte_done
|
|
|
|
no_lf:
|
|
mov ebx,[pagey]
|
|
imul ebx,[pagexs]
|
|
add ebx,[pagex]
|
|
add ebx,0x20000
|
|
and eax,0xff
|
|
cmp eax,31
|
|
jbe byte_done
|
|
cmp [lastletter],al
|
|
jne letter_ok
|
|
cmp al,' '
|
|
je byte_done
|
|
|
|
letter_ok:
|
|
mov [ebx],al
|
|
mov dl,[text_type]
|
|
mov [ebx+0x10000],dl
|
|
mov [pageyinc],0
|
|
mov [lastletter],al
|
|
|
|
inc [pagex]
|
|
|
|
mov ebx,[pagex]
|
|
cmp ebx,[pagexs]
|
|
jb byte_done
|
|
mov [pagex],0
|
|
inc [pagey]
|
|
|
|
jmp byte_done
|
|
|
|
no_print:
|
|
; HTML -COMMAND
|
|
|
|
mov ax,[esi+0x10000] ; b> bold
|
|
cmp ax,'b>'
|
|
jne no_bold_start
|
|
mov [text_type],2
|
|
|
|
no_bold_start:
|
|
mov eax,[esi+0x10000] ; /b bold end
|
|
cmp eax,'</b>'
|
|
jne no_bold_end
|
|
mov [text_type],1
|
|
add esi,2
|
|
|
|
no_bold_end:
|
|
mov ax,[esi+0x10000] ; <a
|
|
cmp ax,'a '
|
|
jne no_link_start
|
|
mov [text_type],128
|
|
add esi,2
|
|
|
|
no_link_start:
|
|
mov ax,[esi+0x10000] ; /a
|
|
cmp ax,'/a'
|
|
jne no_link_end2
|
|
mov [text_type],1
|
|
add esi,0
|
|
|
|
no_link_end2:
|
|
mov ax,[esi+0x10000]
|
|
cmp ax,'br'
|
|
jne no_br
|
|
call linefeed
|
|
inc esi
|
|
|
|
no_br:
|
|
mov ax,[esi+0x10000]
|
|
cmp ax,'td'
|
|
jne no_td
|
|
call linefeed
|
|
inc esi
|
|
|
|
no_td:
|
|
mov eax,[esi+0x10000]
|
|
cmp eax,'tabl'
|
|
jne no_table
|
|
call linefeed
|
|
add esi,3
|
|
|
|
no_table:
|
|
byte_done:
|
|
inc esi
|
|
cmp esi,[pos]
|
|
jbe newbyte
|
|
|
|
mov [display_from],0
|
|
call display_page
|
|
|
|
popa
|
|
ret
|
|
|
|
|
|
|
|
;****************************************************************************
|
|
; Function
|
|
; linefeed
|
|
;
|
|
; Description
|
|
;
|
|
;
|
|
;****************************************************************************
|
|
linefeed:
|
|
cmp [pageyinc],2
|
|
jge nolf
|
|
|
|
mov [pagex],0
|
|
inc [pagey]
|
|
inc [pageyinc]
|
|
|
|
nolf:
|
|
ret
|
|
|
|
|
|
|
|
;****************************************************************************
|
|
; Function
|
|
; display_page
|
|
;
|
|
; Description
|
|
; Renders the text decoded by draw_page
|
|
;
|
|
;****************************************************************************
|
|
display_page:
|
|
pusha
|
|
|
|
mov eax,0
|
|
mov ebx,0
|
|
|
|
newpxy:
|
|
push eax
|
|
push ebx
|
|
|
|
mov eax,13 ; background for letter
|
|
mov ebx,[esp+4]
|
|
imul ebx,6
|
|
add ebx,[dpx]
|
|
shl ebx,16
|
|
add ebx,6
|
|
mov ecx,[esp+0]
|
|
imul ecx,10
|
|
add ecx,[dpy]
|
|
shl ecx,16
|
|
add ecx,10
|
|
mov edx,0xffffff
|
|
mcall
|
|
|
|
mov eax,4
|
|
mov ebx,[esp+4]
|
|
imul ebx,6
|
|
add ebx,[dpx]
|
|
shl ebx,16
|
|
|
|
mov bx,[esp+0]
|
|
imul bx,10
|
|
add bx,word [dpy]
|
|
|
|
mov esi,[esp]
|
|
imul esi,[pagexs]
|
|
add esi,[esp+4]
|
|
|
|
mov edx,[display_from]
|
|
imul edx,[pagexs]
|
|
add edx,0x20000
|
|
add edx,esi
|
|
|
|
movzx ecx,byte [edx+0x10000]
|
|
cmp ecx,1
|
|
jne noecx1
|
|
mov ecx,0x000000
|
|
|
|
noecx1:
|
|
movzx ecx,byte [edx+0x10000]
|
|
cmp ecx,2
|
|
jne noecx2
|
|
mov ecx,0xff0000
|
|
|
|
noecx2:
|
|
cmp ecx,128
|
|
jne noecx128
|
|
mov ecx,0x0000ff
|
|
|
|
noecx128:
|
|
mov esi,1
|
|
|
|
mcall
|
|
|
|
pop ebx
|
|
pop eax
|
|
|
|
inc eax
|
|
cmp eax,[pagexs]
|
|
jb newpxy
|
|
mov eax,0
|
|
inc ebx
|
|
cmp ebx,30
|
|
jb newpxy
|
|
|
|
popa
|
|
ret
|
|
|
|
|
|
|
|
|
|
;****************************************************************************
|
|
; Function
|
|
; socket_commands
|
|
;
|
|
; Description
|
|
; opens or closes the socket
|
|
;
|
|
;****************************************************************************
|
|
socket_commands:
|
|
cmp ah,22 ; open socket
|
|
jnz tst3
|
|
|
|
; Clear all page memory
|
|
mov edi,0x10000
|
|
mov ecx,0x30000
|
|
mov al,0
|
|
cld
|
|
rep stosb
|
|
|
|
; Parse the entered url
|
|
call parse_url
|
|
|
|
; Get a free port number
|
|
mov ecx, 1000 ; local port starting at 1000
|
|
getlp1:
|
|
inc ecx
|
|
push ecx
|
|
mov eax, 53
|
|
mov ebx, 9
|
|
mcall
|
|
pop ecx
|
|
cmp eax, 0 ; is this local port in use?
|
|
jz getlp1 ; yes - so try next
|
|
|
|
mov eax,53
|
|
mov ebx,5
|
|
mov edx,80
|
|
mov esi,dword [server_ip]
|
|
mov edi,1
|
|
mcall
|
|
mov [socket], eax
|
|
|
|
mov [pos],0
|
|
mov [pagex],0
|
|
mov [pagey],0
|
|
mov [pagexs],80
|
|
mov [command_on_off],0
|
|
|
|
ret
|
|
|
|
tst3:
|
|
cmp ah,24 ; close socket
|
|
jnz no_24
|
|
|
|
mov eax,53
|
|
mov ebx,8
|
|
mov ecx,[socket]
|
|
mcall
|
|
|
|
call draw_page
|
|
|
|
ret
|
|
|
|
no_24:
|
|
ret
|
|
|
|
|
|
|
|
;****************************************************************************
|
|
; Function
|
|
; parse_url
|
|
;
|
|
; Description
|
|
; parses the full url typed in by the user into a web address ( that
|
|
; can be turned into an IP address by DNS ) and the page to display
|
|
; DNS will be used to translate the web address into an IP address, if
|
|
; needed.
|
|
; url is at document_user and will be space terminated.
|
|
; web address goes to webAddr and is space terminated.
|
|
; ip address goes to server_ip
|
|
; page goes to document and is space terminated.
|
|
;
|
|
; Supported formats:
|
|
; <protocol://>address<page>
|
|
; <protocol> is optional, removed and ignored - only http supported
|
|
; <address> is required. It can be an ip address or web address
|
|
; <page> is optional and must start with a leading / character
|
|
;
|
|
;****************************************************************************
|
|
parse_url:
|
|
; First, reset destination variables
|
|
cld
|
|
mov al, ' '
|
|
mov edi, document
|
|
mov ecx,URLMAXLEN
|
|
rep stosb
|
|
mov edi, webAddr
|
|
mov ecx,URLMAXLEN
|
|
rep stosb
|
|
mov al, '/'
|
|
mov [document], al
|
|
|
|
mov esi, document_user
|
|
; remove any leading protocol text
|
|
mov ecx, URLMAXLEN
|
|
mov ax, '//'
|
|
|
|
pu_000:
|
|
cmp [esi], byte ' ' ; end of text?
|
|
je pu_002 ; yep, so not found
|
|
cmp word [esi], ax
|
|
je pu_001 ; Found it, so esi+2 is start
|
|
inc esi
|
|
loop pu_000
|
|
|
|
pu_002:
|
|
; not found, so reset esi to start
|
|
mov esi, document_user -2
|
|
|
|
pu_001:
|
|
add esi, 2
|
|
|
|
mov ebx, esi ; save address of start of web address
|
|
mov edi, document_user + URLMAXLEN ; end of string
|
|
|
|
; look for page delimiter - it's a '/' character
|
|
pu_003:
|
|
cmp [esi], byte ' ' ; end of text?
|
|
je pu_004 ; yep, so none found
|
|
cmp esi, edi ; end of string?
|
|
je pu_004 ; yep, so none found
|
|
cmp [esi], byte '/' ; delimiter?
|
|
je pu_005 ; yep - process it
|
|
inc esi
|
|
jmp pu_003
|
|
|
|
pu_005:
|
|
; copy page to document address
|
|
; esi = delimiter
|
|
push esi
|
|
inc esi
|
|
mov ecx, edi ; end of document_user
|
|
mov edi, document
|
|
cld
|
|
|
|
pu_006:
|
|
movsb
|
|
cmp esi, ecx
|
|
je pu_007 ; end of string?
|
|
cmp [esi], byte ' ' ; end of text
|
|
je pu_007
|
|
jmp pu_006
|
|
|
|
pu_007:
|
|
pop esi ; point esi to '/' delimiter
|
|
|
|
pu_004:
|
|
; copy web address to webAddr
|
|
; start in ebx, end in esi-1
|
|
mov ecx, esi
|
|
mov esi, ebx
|
|
mov edi, webAddr
|
|
cld
|
|
|
|
pu_008:
|
|
movsb
|
|
cmp esi, ecx
|
|
je pu_009
|
|
jmp pu_008
|
|
|
|
pu_009:
|
|
; For debugging, display resulting strings
|
|
|
|
if DEBUGGING_STATE = DEBUGGING_ENABLED
|
|
mov esi, document_user
|
|
call debug_print_string
|
|
mov esi, webAddr
|
|
call debug_print_string
|
|
mov esi, document
|
|
call debug_print_string
|
|
end if
|
|
|
|
; Look up the ip address, or was it specified?
|
|
mov al, [webAddr]
|
|
cmp al, '0'
|
|
jb pu_010 ; Resolve address
|
|
cmp al, '9'
|
|
ja pu_010 ; Resolve address
|
|
|
|
|
|
if DEBUGGING_STATE = DEBUGGING_ENABLED
|
|
mov esi, str2 ; print gotip
|
|
call debug_print_string
|
|
end if
|
|
|
|
; Convert address
|
|
mov esi,webAddr-1
|
|
mov edi,server_ip
|
|
xor eax,eax
|
|
ip1:
|
|
inc esi
|
|
cmp [esi],byte '0'
|
|
jb ip2
|
|
cmp [esi],byte '9'
|
|
jg ip2
|
|
imul eax,10
|
|
movzx ebx,byte [esi]
|
|
sub ebx,48
|
|
add eax,ebx
|
|
jmp ip1
|
|
ip2:
|
|
mov [edi],al
|
|
xor eax,eax
|
|
inc edi
|
|
cmp edi,server_ip+3
|
|
jbe ip1
|
|
|
|
jmp pu_011
|
|
|
|
pu_010:
|
|
|
|
if DEBUGGING_STATE = DEBUGGING_ENABLED
|
|
mov esi, str1 ; print resolving
|
|
call debug_print_string
|
|
end if
|
|
|
|
; Resolve Address
|
|
call translateData ; Convert domain & DNS IP address
|
|
call resolveDomain ; get ip address
|
|
|
|
if DEBUGGING_STATE = DEBUGGING_ENABLED
|
|
mov esi, str3
|
|
call debug_print_string
|
|
end if
|
|
|
|
pu_011:
|
|
|
|
; Done
|
|
ret
|
|
|
|
|
|
;***************************************************************************
|
|
; Function
|
|
; translateData
|
|
;
|
|
; Description
|
|
; Coverts the domain name and DNS IP address typed in by the user into
|
|
; a format suitable for the IP layer.
|
|
;
|
|
; The ename, in query, is converted and stored in dnsMsg
|
|
;
|
|
;***************************************************************************
|
|
translateData:
|
|
|
|
; first, get the IP address of the DNS server
|
|
; Then, build up the request string.
|
|
|
|
|
|
; Build the request string
|
|
|
|
|
|
mov eax, 0x00010100
|
|
mov [dnsMsg], eax
|
|
mov eax, 0x00000100
|
|
mov [dnsMsg+4], eax
|
|
mov eax, 0x00000000
|
|
mov [dnsMsg+8], eax
|
|
|
|
; domain name goes in at dnsMsg+12
|
|
mov esi, dnsMsg + 12 ; location of label length
|
|
mov edi, dnsMsg + 13 ; label start
|
|
mov edx, webAddr
|
|
mov ecx, 12 ; total string length so far
|
|
|
|
td002:
|
|
mov [esi], byte 0
|
|
inc ecx
|
|
|
|
td0021:
|
|
mov al, [edx]
|
|
cmp al, ' '
|
|
je td001 ; we have finished the string translation
|
|
cmp al, '.' ; we have finished the label
|
|
je td004
|
|
|
|
inc byte [esi]
|
|
inc ecx
|
|
mov [edi], al
|
|
inc edi
|
|
inc edx
|
|
jmp td0021
|
|
|
|
td004:
|
|
mov esi, edi
|
|
inc edi
|
|
inc edx
|
|
jmp td002
|
|
|
|
|
|
|
|
; write label len + label text
|
|
|
|
td001:
|
|
mov [edi], byte 0
|
|
inc ecx
|
|
inc edi
|
|
mov [edi], dword 0x01000100
|
|
add ecx, 4
|
|
|
|
mov [dnsMsgLen], ecx
|
|
|
|
ret
|
|
|
|
|
|
|
|
|
|
|
|
;***************************************************************************
|
|
; Function
|
|
; resolveDomain
|
|
;
|
|
; Description
|
|
; Sends a question to the dns server
|
|
; works out the IP address from the response from the DNS server
|
|
;
|
|
;***************************************************************************
|
|
resolveDomain:
|
|
; Get a free port number
|
|
mov ecx, 1000 ; local port starting at 1000
|
|
getlp:
|
|
inc ecx
|
|
push ecx
|
|
mov eax, 53
|
|
mov ebx, 9
|
|
mcall
|
|
pop ecx
|
|
cmp eax, 0 ; is this local port in use?
|
|
jz getlp ; yes - so try next
|
|
|
|
; First, open socket
|
|
mov eax, 53
|
|
mov ebx, 0
|
|
mov edx, 53 ; remote port - dns
|
|
mov esi, dword [dns_ip]
|
|
mcall
|
|
|
|
mov [socketNum], eax
|
|
|
|
; write to socket ( request DNS lookup )
|
|
mov eax, 53
|
|
mov ebx, 4
|
|
mov ecx, [socketNum]
|
|
mov edx, [dnsMsgLen]
|
|
mov esi, dnsMsg
|
|
mcall
|
|
|
|
; Setup the DNS response buffer
|
|
|
|
mov eax, dnsMsg
|
|
mov [dnsMsgLen], eax
|
|
|
|
; now, we wait for
|
|
; UI redraw
|
|
; UI close
|
|
; or data from remote
|
|
|
|
ctr001:
|
|
mov eax,10 ; wait here for event
|
|
mcall
|
|
|
|
cmp eax,1 ; redraw request ?
|
|
je ctr003
|
|
cmp eax,2 ; key in buffer ?
|
|
je ctr004
|
|
cmp eax,3 ; button in buffer ?
|
|
je ctr005
|
|
|
|
|
|
; Any data in the UDP receive buffer?
|
|
mov eax, 53
|
|
mov ebx, 2
|
|
mov ecx, [socketNum]
|
|
mcall
|
|
|
|
cmp eax, 0
|
|
je ctr001
|
|
|
|
; we have data - this will be the response
|
|
ctr002:
|
|
mov eax, 53
|
|
mov ebx, 3
|
|
mov ecx, [socketNum]
|
|
mcall ; read byte - block (high byte)
|
|
|
|
; Store the data in the response buffer
|
|
mov eax, [dnsMsgLen]
|
|
mov [eax], bl
|
|
inc dword [dnsMsgLen]
|
|
|
|
mov eax, 53
|
|
mov ebx, 2
|
|
mov ecx, [socketNum]
|
|
mcall ; any more data?
|
|
|
|
cmp eax, 0
|
|
jne ctr002 ; yes, so get it
|
|
|
|
; close socket
|
|
mov eax, 53
|
|
mov ebx, 1
|
|
mov ecx, [socketNum]
|
|
mcall
|
|
|
|
mov [socketNum], dword 0xFFFF
|
|
|
|
; Now parse the message to get the host IP
|
|
; Man, this is complicated. It's described in
|
|
; RFC 1035
|
|
|
|
if DEBUGGING_STATE = DEBUGGING_ENABLED
|
|
mov esi, str4
|
|
call debug_print_string
|
|
end if
|
|
|
|
; 1) Validate that we have an answer with > 0 responses
|
|
; 2) Find the answer record with TYPE 0001 ( host IP )
|
|
; 3) Finally, copy the IP address to the display
|
|
; Note: The response is in dnsMsg
|
|
; The end of the buffer is pointed to by [dnsMsgLen]
|
|
|
|
; Clear the IP address text
|
|
mov [server_ip], dword 0
|
|
|
|
mov esi, dnsMsg
|
|
|
|
; Is this a response to my question?
|
|
mov al, [esi+2]
|
|
and al, 0x80
|
|
cmp al, 0x80
|
|
jne ctr002a
|
|
|
|
; Were there any errors?
|
|
mov al, [esi+3]
|
|
and al, 0x0F
|
|
cmp al, 0x00
|
|
jne ctr002a
|
|
|
|
; Is there ( at least 1 ) answer?
|
|
mov ax, [esi+6]
|
|
cmp ax, 0x00
|
|
je ctr002a
|
|
|
|
; Header validated. Scan through and get my answer
|
|
|
|
if DEBUGGING_STATE = DEBUGGING_ENABLED
|
|
pusha
|
|
mov esi, str4
|
|
call debug_print_string
|
|
popa
|
|
end if
|
|
|
|
add esi, 12 ; Skip to the question field
|
|
|
|
; Skip through the question field
|
|
call skipName
|
|
add esi, 4 ; skip past the questions qtype, qclass
|
|
|
|
ctr002z:
|
|
; Now at the answer. There may be several answers,
|
|
; find the right one ( TYPE = 0x0001 )
|
|
call skipName
|
|
mov ax, [esi]
|
|
cmp ax, 0x0100 ; Is this the IP address answer?
|
|
jne ctr002c
|
|
|
|
; Yes! Point esi to the first byte of the IP address
|
|
add esi, 10
|
|
|
|
mov eax, [esi]
|
|
mov [server_ip], eax
|
|
ret
|
|
|
|
|
|
ctr002c: ; Skip through the answer, move to the next
|
|
add esi, 8
|
|
movzx eax, byte [esi+1]
|
|
mov ah, [esi]
|
|
add esi, eax
|
|
add esi, 2
|
|
|
|
; Have we reached the end of the msg?
|
|
; This is an error condition, should not happen
|
|
cmp esi, [dnsMsgLen]
|
|
jl ctr002z ; Check next answer
|
|
jmp ctr002a ; abort
|
|
|
|
ctr002a:
|
|
jmp ctr001
|
|
|
|
ctr003: ; redraw
|
|
call draw_window
|
|
jmp ctr001
|
|
|
|
ctr004: ; key
|
|
mov eax,2 ; just read it and ignore
|
|
mcall
|
|
jmp ctr001
|
|
|
|
ctr005: ; button
|
|
mov eax,17 ; get id
|
|
mcall
|
|
|
|
mov dl, ah
|
|
|
|
; close socket
|
|
mov eax, 53
|
|
mov ebx, 1
|
|
mov ecx, [socketNum]
|
|
mcall
|
|
|
|
cmp dl, 1
|
|
je exit
|
|
|
|
mov [socketNum], dword 0xFFFF
|
|
mov [server_ip], dword 0
|
|
|
|
ret
|
|
|
|
|
|
|
|
;***************************************************************************
|
|
; Function
|
|
; skipName
|
|
;
|
|
; Description
|
|
; Increment esi to the first byte past the name field
|
|
; Names may use compressed labels. Normally do.
|
|
; RFC 1035 page 30 gives details
|
|
;
|
|
;***************************************************************************
|
|
skipName:
|
|
mov al, [esi]
|
|
cmp al, 0
|
|
je sn_exit
|
|
and al, 0xc0
|
|
cmp al, 0xc0
|
|
je sn001
|
|
|
|
movzx eax, byte [esi]
|
|
inc eax
|
|
add esi, eax
|
|
jmp skipName
|
|
|
|
sn001:
|
|
add esi, 2 ; A pointer is always at the end
|
|
ret
|
|
|
|
sn_exit:
|
|
inc esi
|
|
ret
|
|
|
|
|
|
|
|
if DEBUGGING_STATE = DEBUGGING_ENABLED
|
|
|
|
;****************************************************************************
|
|
; Function
|
|
; debug_print_string
|
|
;
|
|
; Description
|
|
; prints a string to the debug board, in quotes
|
|
;
|
|
; esi holds ptr to msg to display, which is space or 0 terminated
|
|
;
|
|
; Nothing preserved; I'm assuming a pusha/popa is done before calling
|
|
;
|
|
;****************************************************************************
|
|
debug_print_string:
|
|
push esi
|
|
mov cl, '"'
|
|
mov eax,63
|
|
mov ebx, 1
|
|
mcall
|
|
pop esi
|
|
|
|
dps_000:
|
|
mov cl, [esi]
|
|
cmp cl, 0
|
|
je dps_exit
|
|
cmp cl, ' '
|
|
je dps_exit
|
|
jmp dps_001
|
|
|
|
dps_exit:
|
|
mov cl, '"'
|
|
mov eax,63
|
|
mov ebx, 1
|
|
mcall
|
|
mov cl, 13
|
|
mov eax,63
|
|
mov ebx, 1
|
|
mcall
|
|
mov cl, 10
|
|
mov eax,63
|
|
mov ebx, 1
|
|
mcall
|
|
ret
|
|
|
|
dps_001:
|
|
mov eax,63
|
|
mov ebx, 1
|
|
push esi
|
|
mcall
|
|
|
|
pop esi
|
|
inc esi
|
|
jmp dps_000
|
|
end if
|
|
|
|
|
|
;****************************************************************************
|
|
; Function
|
|
; print_text
|
|
;
|
|
; Description
|
|
; display the url (full path) text
|
|
;
|
|
;****************************************************************************
|
|
print_text:
|
|
; Draw a bar to blank out previous text
|
|
mov eax,13
|
|
mov ebx,30*65536+URLMAXLEN*6 ; 50 should really be [len], and 103 [xa]
|
|
mov ecx,[ya]
|
|
shl ecx,16
|
|
mov cx,9
|
|
mov edx,0xFFFFFF
|
|
mcall
|
|
|
|
; write text
|
|
mov eax,4
|
|
mov ebx,30*65536
|
|
add ebx,[ya]
|
|
mov ecx,0x000000
|
|
mov edx,[addr]
|
|
mov esi,URLMAXLEN
|
|
mcall
|
|
|
|
ret
|
|
|
|
; *********************************************
|
|
; ******* WINDOW DEFINITIONS AND DRAW ********
|
|
; *********************************************
|
|
|
|
draw_window:
|
|
mov eax,12 ; function 12:tell os about windowdraw
|
|
mov ebx,1 ; 1, start of draw
|
|
mcall
|
|
|
|
; DRAW WINDOW
|
|
mov eax,0 ; function 0 : define and draw window
|
|
mov ebx,50*65536+550 ; [x start] *65536 + [x size]
|
|
mov ecx,50*65536+400 ; [y start] *65536 + [y size]
|
|
mov edx,0x14ffffff ; color of work area RRGGBB,8->color gl
|
|
mov edi,title ; WINDOW LABEL
|
|
mcall
|
|
|
|
|
|
mov esi, URLMAXLEN ; URL
|
|
mov eax,4 ; function 4 : write text to window
|
|
mov ebx,30*65536+38 ; [x start] *65536 + [y start]
|
|
mov ecx,0x000000 ; color of text RRGGBB
|
|
mov edx,document_user ; pointer to text beginning
|
|
mcall
|
|
|
|
mov eax,38
|
|
mov ebx,5*65536+545
|
|
mov ecx,60*65536+60
|
|
mov edx,0x000000
|
|
mcall
|
|
|
|
;mov eax,38
|
|
;mov ebx,5*65536+545
|
|
mov ecx,[winys]
|
|
shl ecx,16
|
|
add ecx,[winys]
|
|
sub ecx,26*65536+26
|
|
;mov edx,0x000000
|
|
mcall
|
|
; RELOAD
|
|
mov eax,8 ; function 8 : define and draw button
|
|
mov ebx,388*65536+50 ; [x start] *65536 + [x size]
|
|
mov ecx,34*65536+14 ; [y start] *65536 + [y size]
|
|
mov edx,22 ; button id
|
|
mov esi,0x5588dd ; button color RRGGBB
|
|
mcall
|
|
|
|
; URL
|
|
;mov eax,8 ; function 8 : define and draw button
|
|
mov ebx,10*65536+12 ; [x start] *65536 + [x size]
|
|
mov ecx,34*65536+12 ; [y start] *65536 + [y size]
|
|
mov edx,10 ; button id
|
|
;mov esi,0x5588dd ; button color RRGGBB
|
|
mcall
|
|
|
|
; STOP
|
|
;mov eax,8 ; function 8 : define and draw button
|
|
mov ebx,443*65536+50 ; [x start] *65536 + [x size]
|
|
mov ecx,34*65536+14 ; [y start] *65536 + [y size]
|
|
mov edx,24 ; button id
|
|
;mov esi,0x5588dd ; button color RRGGBB
|
|
mcall
|
|
|
|
; BUTTON TEXT
|
|
mov eax,4 ; function 4 : write text to window
|
|
mov ebx,390*65536+38 ; [x start] *65536 + [y start]
|
|
mov ecx,0xffffff ; color of text RRGGBB
|
|
mov edx,button_text ; pointer to text beginning
|
|
mov esi,20 ; text length
|
|
mcall
|
|
|
|
call display_page
|
|
|
|
mov eax,12 ; function 12:tell os about windowdraw
|
|
mov ebx,2 ; 2, end of draw
|
|
mcall
|
|
|
|
ret
|
|
|
|
|
|
if DEBUGGING_STATE = DEBUGGING_ENABLED
|
|
str1: db "Resolving...",0
|
|
str3: db "Resolved",0
|
|
str2: db "GotIP",0
|
|
str4: db "GotResponse",0
|
|
end if
|
|
|
|
button_text db ' RELOAD STOP '
|
|
dpx dd 25 ; x - start of html page in pixels in window
|
|
dpy dd 65 ; for y
|
|
lastletter db 0
|
|
pageyinc dd 0
|
|
display_from dd 20
|
|
pos dd 0x0
|
|
pagex dd 0x0
|
|
pagey dd 0x0
|
|
pagexs dd 80
|
|
command_on_off dd 0x0
|
|
text_type db 1
|
|
com2 dd 0x0
|
|
script dd 0x0
|
|
socket dd 0x0
|
|
|
|
addr dd 0x0
|
|
ya dd 0x0
|
|
len dd 0x00
|
|
|
|
title db 'HTTPC - PgUp/PgDown',0
|
|
|
|
server_ip: db 207,44,212,20
|
|
dns_ip: db 194,145,128,1
|
|
webAddr: times 128 db ' '
|
|
document_user: db 'Click on the button to the left to enter a URL',0
|
|
times 100 db 0x0
|
|
document: db '/'
|
|
times 100 db ' '
|
|
|
|
string0: db 'GET '
|
|
|
|
stringh: db ' HTTP/1.0',13,10,13,10
|
|
stringh_end:
|
|
|
|
status dd 0x0
|
|
prev_status dd 0x0
|
|
|
|
onoff dd 0x0
|
|
|
|
nextupdate: dd 0
|
|
winys: dd 400
|
|
|
|
dnsMsgLen: dd 0
|
|
socketNum: dd 0xFFFF
|
|
dnsMsg:
|
|
I_END:
|