Small bugfixes and improvements for FTP client

git-svn-id: svn://kolibrios.org@3789 a494cfbc-eb01-0410-851d-a64ba20cac60
This commit is contained in:
hidnplayr 2013-07-09 20:19:08 +00:00
parent 3e750a39ab
commit 75cac16296
3 changed files with 101 additions and 163 deletions

View File

@ -14,8 +14,6 @@
format binary as "" format binary as ""
__DEBUG__ = 0
__DEBUG_LEVEL__ = 1
BUFFERSIZE = 1024 BUFFERSIZE = 1024
STATUS_CONNECTING = 0 STATUS_CONNECTING = 0
@ -38,7 +36,6 @@ include '../../macros.inc'
purge mov,add,sub purge mov,add,sub
include '../../proc32.inc' include '../../proc32.inc'
include '../../dll.inc' include '../../dll.inc'
include '../../debug-fdo.inc'
include '../../network.inc' include '../../network.inc'
include 'usercommands.inc' include 'usercommands.inc'
@ -47,39 +44,32 @@ include 'servercommands.inc'
; entry point ; entry point
start: start:
DEBUGF 1, "hello" mcall 40, 0
; load libraries ; load libraries
stdcall dll.Load, @IMPORT stdcall dll.Load, @IMPORT
test eax, eax test eax, eax
jnz exit jnz exit
; initialize console ; initialize console
push 1 invoke con_start, 1
call [con_start] invoke con_init, 80, 25, 80, 25, title
push title
push 25
push 80
push 25
push 80
call [con_init]
; Check for parameters ; Check for parameters
cmp byte [s], 0 cmp byte [s], 0
jne resolve jne resolve
main: main:
call [con_cls] invoke con_cls
; Welcome user ; Welcome user
push str1 invoke con_write_asciiz, str1
call [con_write_asciiz]
; write prompt ; write prompt
push str2 invoke con_set_flags, 0x0a
call [con_write_asciiz] invoke con_write_asciiz, str2
; read string ; read string
mov esi, s mov esi, s
push 256 invoke con_gets, esi, 256
push esi invoke con_write_asciiz, str4 ; newline
call [con_gets] invoke con_set_flags, 0x07
; check for exit ; check for exit
test eax, eax test eax, eax
jz done jz done
@ -87,7 +77,6 @@ main:
jz done jz done
resolve: resolve:
; delete terminating '\n' ; delete terminating '\n'
mov esi, s mov esi, s
@@: @@:
@ -96,120 +85,90 @@ resolve:
ja @r ja @r
mov byte [esi-1], 0 mov byte [esi-1], 0
; call [con_cls] invoke con_write_asciiz, str3
push str3 invoke con_write_asciiz, s
call [con_write_asciiz]
push s
call [con_write_asciiz]
; resolve name ; resolve name
push esp ; reserve stack place push esp ; reserve stack place
push esp ; fourth parameter invoke getaddrinfo, s, 0, 0, esp
push 0 ; third parameter
push 0 ; second parameter
push s ; first parameter
call [getaddrinfo]
pop esi pop esi
; test for error ; test for error
test eax, eax test eax, eax
jnz fail jnz fail
; write results ; write results
push str8 invoke con_write_asciiz, str8
call [con_write_asciiz]
; mov edi, esi ; mov edi, esi
; convert IP address to decimal notation ; convert IP address to decimal notation
mov eax, [esi+addrinfo.ai_addr] mov eax, [esi+addrinfo.ai_addr]
mov eax, [eax+sockaddr_in.sin_addr] mov eax, [eax+sockaddr_in.sin_addr]
mov [sockaddr1.ip], eax mov [sockaddr1.ip], eax
push eax
call [inet_ntoa] invoke inet_ntoa, eax
; write result ; write result
push eax invoke con_write_asciiz, eax
call [con_write_asciiz]
; free allocated memory ; free allocated memory
push esi invoke freeaddrinfo, esi
call [freeaddrinfo]
push str9
call [con_write_asciiz]
invoke con_write_asciiz, str9
mcall socket, AF_INET4, SOCK_STREAM, 0 mcall socket, AF_INET4, SOCK_STREAM, 0
cmp eax, -1 cmp eax, -1
je fail2 je socket_error
mov [socketnum], eax mov [socketnum], eax
push str11 invoke con_write_asciiz, str11
call [con_write_asciiz]
mcall connect, [socketnum], sockaddr1, 18 mcall connect, [socketnum], sockaddr1, 18
mcall 40, EVM_STACK
mov [status], STATUS_CONNECTING mov [status], STATUS_CONNECTING
mov [offset], buffer_ptr
push str12 invoke con_write_asciiz, str12
call [con_write_asciiz]
wait_for_serverdata: wait_for_servercommand:
mcall 10
call [con_get_flags] ; invoke con_write_asciiz, str_dbg
test eax, 0x200 ; con window closed?
jnz exit
; receive socket data ; receive socket data
mcall recv, [socketnum], [offset], BUFFERSIZE, MSG_DONTWAIT mcall recv, [socketnum], buffer_ptr, BUFFERSIZE, 0
inc eax inc eax
jz wait_for_serverdata jz socket_error
dec eax dec eax
jz wait_for_serverdata jz wait_for_servercommand
; invoke con_write_asciiz, str_dbg2
; extract commands, copy them to "s" buffer ; extract commands, copy them to "s" buffer
add eax, buffer_ptr ; eax = end pointer lea ecx, [eax + buffer_ptr] ; ecx = end pointer
mov esi, buffer_ptr ; esi = current pointer mov esi, buffer_ptr ; esi = current pointer
.nextcommand:
mov edi, s mov edi, s
.byteloop: .byteloop:
cmp esi, eax cmp esi, ecx
jae wait_for_serverdata jae wait_for_servercommand
lodsb lodsb
cmp al, 10 ; excellent, we might have a command cmp al, 10 ; excellent, we might have a command
je .got_command je .got_command
cmp al, 13 ; just ignore this crap cmp al, 13 ; just ignore this byte
je .byteloop je .byteloop
stosb stosb
jmp .byteloop jmp .byteloop
.got_command: ; we have a newline check if its a command
; we have a newline check if its a command
.got_command:
xor al, al xor al, al
stosb stosb
; push esi eax
; print it to the screen
pushd s
call [con_write_asciiz]
pushd str4 ; newline
call [con_write_asciiz]
; cmp byte[s+2], " "
; jne .not_command
lea ecx, [edi - s]
call server_parser
; .not_command:
; pop eax esi
; jmp .nextcommand
sub edi, s ; length
push edi
invoke con_set_flags, 0x03 ; change color
invoke con_write_asciiz, s ; print servercommand
invoke con_write_asciiz, str4 ; newline
invoke con_set_flags, 0x07
pop ecx
jmp server_parser ; parse command
wait_for_usercommand: wait_for_usercommand:
invoke con_set_flags, 0x0a
cmp [status], STATUS_CONNECTED cmp [status], STATUS_CONNECTED
je .connected je .connected
@ -217,17 +176,11 @@ wait_for_usercommand:
je .needpass je .needpass
; write prompt ; write prompt
push str2 invoke con_write_asciiz, str2
call [con_write_asciiz]
; read string ; read string
mov esi, s mov esi, s
push 256 invoke con_gets, esi, 256
push esi invoke con_set_flags, 0x07
call [con_gets]
call [con_get_flags]
test eax, 0x200 ; con window closed?
jnz exit
cmp dword[s], "list" cmp dword[s], "list"
je cmd_list je cmd_list
@ -235,54 +188,39 @@ wait_for_usercommand:
cmp dword[s], "help" cmp dword[s], "help"
je cmd_help je cmd_help
push str_unkown invoke con_write_asciiz, str_unknown
call [con_write_asciiz]
jmp wait_for_usercommand jmp wait_for_usercommand
.connected: .connected:
push str_user invoke con_write_asciiz, str_user
call [con_write_asciiz]
mov dword[s], "USER" mov dword[s], "USER"
mov byte[s+4], " " mov byte[s+4], " "
; mov [status], STATUS_NEEDPASSWORD
inc [status]
jmp .send jmp .send
.needpass: .needpass:
push str_pass
call [con_write_asciiz]
invoke con_write_asciiz, str_pass
mov dword[s], "PASS" mov dword[s], "PASS"
mov byte[s+4], " " mov byte[s+4], " "
; mov [status], STATUS_LOGGED_IN
inc [status]
.send: .send:
; read string ; read string
mov esi, s+5 mov esi, s+5
push 256 invoke con_gets, esi, 256
push esi
call [con_gets]
mov edi, s+5 mov edi, s+5
mov ecx, 256 mov ecx, 256
xor al, al xor al, al
repne scasb repne scasb
lea esi, [edi-s-1] lea esi, [edi-s-1]
mcall send, [socketnum], s mcall send, [socketnum], s, , 0
jmp wait_for_usercommand
invoke con_write_asciiz, str4 ; newline
invoke con_set_flags, 0x07
jmp wait_for_servercommand
@ -292,37 +230,30 @@ open_dataconnection:
mov dword[s], "PASV" mov dword[s], "PASV"
mov byte[s+4], 10 mov byte[s+4], 10
mcall send, [socketnum], s, 5 mcall send, [socketnum], s, 5, 0
ret ret
.fail: .fail:
push str6 invoke con_write_asciiz, str6
call [con_write_asciiz]
ret ret
fail2:
push str6
call [con_write_asciiz]
socket_error:
invoke con_write_asciiz, str6
jmp fail.wait jmp fail.wait
fail: fail:
push str5 invoke con_write_asciiz, str5
call [con_write_asciiz]
.wait: .wait:
push str10 invoke con_write_asciiz, str10
call [con_write_asciiz] invoke con_getch2
call [con_getch2]
jmp main jmp main
done: done:
push 1 invoke con_exit, 1
call [con_exit]
exit:
exit:
mcall close, [socketnum] mcall close, [socketnum]
mcall -1 mcall -1
@ -330,7 +261,7 @@ exit:
; data ; data
title db 'FTP client',0 title db 'FTP client',0
str1 db 'FTP client for KolibriOS v0.01',10,10,'Please enter ftp server address.',10,0 str1 db 'FTP client for KolibriOS v0.02',10,10,'Please enter ftp server address.',10,0
str2 db '> ',0 str2 db '> ',0
str3 db 'Resolving ',0 str3 db 'Resolving ',0
str4 db 10,0 str4 db 10,0
@ -339,16 +270,19 @@ str6 db 10,'Socket error.',10,0
str8 db ' (',0 str8 db ' (',0
str9 db ')',10,0 str9 db ')',10,0
str10 db 'Push any key to continue.',0 str10 db 'Push any key to continue.',0
str11 db 'Connecting',10,0 str11 db 'Connecting...',10,0
str12 db 'Connected!',10,0 str12 db 'Waiting for welcome message.',10,0
str_user db "username: ",0 str_user db "username: ",0
str_pass db "password: ",0 str_pass db "password: ",0
str_unkown db "unkown command",10,0 str_unknown db "unknown command",10,0
str_help db "available commands:",10,10 str_help db "available commands:",10,10
db "help list",10,0 db "help list",10,0
str_open db "opening data socket",10,0 str_open db "opening data socket",10,0
str_dbg db 'debug',10,0
str_dbg2 db 'debug2',10,0
sockaddr1: sockaddr1:
dw AF_INET4 dw AF_INET4
.port dw 0x1500 ; 21 .port dw 0x1500 ; 21
@ -361,9 +295,6 @@ sockaddr2:
.ip dd 0 .ip dd 0
rb 10 rb 10
include_debug_strings ; ALWAYS present in data section
; import ; import
align 4 align 4
@ -386,7 +317,8 @@ import console, \
con_getch2, 'con_getch2',\ con_getch2, 'con_getch2',\
con_set_cursor_pos, 'con_set_cursor_pos',\ con_set_cursor_pos, 'con_set_cursor_pos',\
con_write_string, 'con_write_string',\ con_write_string, 'con_write_string',\
con_get_flags, 'con_get_flags' con_get_flags, 'con_get_flags', \
con_set_flags, 'con_set_flags'
i_end: i_end:
@ -396,7 +328,6 @@ socketnum dd ?
datasocket dd ? datasocket dd ?
buffer_ptr rb 2*BUFFERSIZE buffer_ptr rb 2*BUFFERSIZE
status db ? status db ?
offset dd ?
s rb 1024 s rb 1024

View File

@ -3,7 +3,7 @@ server_parser:
; Commands are always 3 numbers and followed by a space ; Commands are always 3 numbers and followed by a space
; If a server decides it needs multiline output, ; If a server decides it needs multiline output,
; first lines will have a dash instead of space after numbers, ; first lines will have a dash instead of space after numbers,
; thus they are simply ignored. ; thus they are simply ignored in this simple command parser.
cmp dword[s], "150 " cmp dword[s], "150 "
je data_ok je data_ok
@ -11,6 +11,9 @@ server_parser:
cmp dword[s], "220 " cmp dword[s], "220 "
je welcome je welcome
cmp dword[s], "226 "
; je list_ok
cmp dword[s], "227 " cmp dword[s], "227 "
je pasv_ok je pasv_ok
@ -20,25 +23,31 @@ server_parser:
cmp dword[s], "331 " cmp dword[s], "331 "
je pass je pass
ret cmp dword[s], "421 "
; je timeout
cmp dword[s], "530" ; password incorrect
je welcome
jmp wait_for_usercommand
welcome: welcome:
mov [status], STATUS_CONNECTED mov [status], STATUS_CONNECTED
ret jmp wait_for_usercommand
pass: pass:
mov [status], STATUS_NEEDPASSWORD mov [status], STATUS_NEEDPASSWORD
ret jmp wait_for_usercommand
login_ok: login_ok:
mov [status], STATUS_LOGGED_IN mov [status], STATUS_LOGGED_IN
ret jmp wait_for_usercommand
pasv_ok: pasv_ok:
@ -64,18 +73,16 @@ pasv_ok:
call ascii_dec call ascii_dec
mov byte[sockaddr2.ip+3], bl mov byte[sockaddr2.ip+3], bl
call ascii_dec
mov byte[sockaddr2.port+1], bl
call ascii_dec call ascii_dec
mov byte[sockaddr2.port+0], bl mov byte[sockaddr2.port+0], bl
call ascii_dec
mov byte[sockaddr2.port+1], bl
push str_open invoke con_write_asciiz, str_open
call [con_write_asciiz]
mcall connect, [datasocket], sockaddr2, 18 mcall connect, [datasocket], sockaddr2, 18
.fail: .fail:
ret jmp wait_for_servercommand
data_ok: data_ok:
@ -85,27 +92,27 @@ data_ok:
jz .fail jz .fail
dec eax dec eax
jz .fail jz .fail
mov byte[buffer_ptr + eax], 0 mov byte[buffer_ptr + eax], 0
pushd buffer_ptr
call [con_write_asciiz] invoke con_write_asciiz, buffer_ptr
.fail: .fail:
ret mcall close, [datasocket]
jmp wait_for_servercommand
ascii_dec: ascii_dec:
xor ebx, ebx xor ebx, ebx
mov cl, 3 mov cl, 4 ; max length is 3 digits + 1 separator
.loop: .loop:
lodsb lodsb
sub al, '0' sub al, '0'
jb .done jb .done
cmp al, 9 cmp al, 9
ja .done ja .done
lea ebx, [ebx*4+ebx] lea ebx, [ebx*4+ebx] ; ebx *5
shl ebx, 1 shl ebx, 1 ; ebx *2
add bl, al add bl, al
dec cl dec cl
jnz .loop jnz .loop

View File

@ -3,10 +3,10 @@ cmd_list:
call open_dataconnection call open_dataconnection
mov dword[s], "LIST" mov dword[s], "LIST"
mov word[s+4], 0x0d0a mov byte[s+4], 0x0a
mcall send, [socketnum], s, 6 mcall send, [socketnum], s, 5
jmp wait_for_serverdata jmp wait_for_servercommand
cmd_help: cmd_help: