kolibrios-fun/programs/network/telnet/telnet.asm
hidnplayr 026a30e72b Telnet: code cleanup, no semantic changes.
git-svn-id: svn://kolibrios.org@5858 a494cfbc-eb01-0410-851d-a64ba20cac60
2015-10-25 12:04:33 +00:00

290 lines
7.6 KiB
NASM

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2010-2015. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;; telnet.asm - Telnet client for KolibriOS ;;
;; ;;
;; Written by hidnplayr@kolibrios.org ;;
;; ;;
;; GNU GENERAL PUBLIC LICENSE ;;
;; Version 2, June 1991 ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
format binary as ""
BUFFERSIZE = 4096
use32
; standard header
db 'MENUET01' ; signature
dd 1 ; header version
dd start ; entry point
dd i_end ; initialized size
dd mem+4096 ; required memory
dd mem+4096 ; stack pointer
dd hostname ; parameters
dd 0 ; path
include '../../macros.inc'
purge mov,add,sub
include '../../proc32.inc'
include '../../dll.inc'
include '../../network.inc'
; entry point
start:
; load libraries
stdcall dll.Load, @IMPORT
test eax, eax
jnz exit
; initialize console
invoke con_start, 1
invoke con_init, 80, 25, 80, 25, title
; Check for parameters
cmp byte[hostname], 0
jne resolve
main:
invoke con_cls
; Welcome user
invoke con_write_asciiz, str1
prompt:
; write prompt
invoke con_write_asciiz, str2
; read string (wait for input)
mov esi, hostname
invoke con_gets, esi, 256
; check for exit
test eax, eax
jz done
cmp byte[esi], 10
jz done
resolve:
mov [sockaddr1.port], 23 shl 8 ; Port is in network byte order
; delete terminating newline from URL and parse port, if any.
mov esi, hostname
@@:
lodsb
cmp al, ':'
je .do_port
cmp al, 0x20
ja @r
mov byte[esi-1], 0
jmp .done
.do_port:
xor eax, eax
xor ebx, ebx
mov byte[esi-1], 0
.portloop:
lodsb
cmp al, ' '
jbe .port_done
sub al, '0'
jb hostname_error
cmp al, 9
ja hostname_error
lea ebx, [ebx*4+ebx]
shl ebx, 1
add ebx, eax
jmp .portloop
.port_done:
xchg bl, bh
mov [sockaddr1.port], bx
.done:
; resolve name
push esp ; reserve stack place
invoke getaddrinfo, hostname, 0, 0, esp
pop esi
; test for error
test eax, eax
jnz dns_error
invoke con_cls
invoke con_write_asciiz, str3
invoke con_write_asciiz, hostname
; write results
invoke con_write_asciiz, str8
; convert IP address to decimal notation
mov eax, [esi+addrinfo.ai_addr]
mov eax, [eax+sockaddr_in.sin_addr]
mov [sockaddr1.ip], eax
invoke inet_ntoa, eax
; write result
invoke con_write_asciiz, eax
; free allocated memory
invoke freeaddrinfo, esi
invoke con_write_asciiz, str9
mcall socket, AF_INET4, SOCK_STREAM, 0
cmp eax, -1
jz socket_err
mov [socketnum], eax
mcall connect, [socketnum], sockaddr1, 18
test eax, eax
jnz socket_err
mcall 40, EVM_STACK
invoke con_cls
mcall 18, 7
push eax
mcall 51, 1, thread, mem - 2048
pop ecx
mcall 18, 3
mainloop:
invoke con_get_flags
test eax, 0x200 ; con window closed?
jnz exit
mcall recv, [socketnum], buffer_ptr, BUFFERSIZE, 0
cmp eax, -1
je closed
mov esi, buffer_ptr
lea edi, [esi+eax]
mov byte[edi], 0
.scan_cmd:
cmp byte[esi], 0xff ; Interpret As Command
jne .no_cmd
; TODO: parse options
; for now, we will reply with 'WONT' to everything
mov byte[esi+1], 252 ; WONT
add esi, 3 ; a command is always 3 bytes
jmp .scan_cmd
.no_cmd:
cmp esi, buffer_ptr
je .print
push esi edi
sub esi, buffer_ptr
mcall send, [socketnum], buffer_ptr, , 0
pop edi esi
.print:
cmp esi, edi
jae mainloop
invoke con_write_asciiz, esi
.loop:
lodsb
test al, al
jz .print
jmp .loop
socket_err:
invoke con_write_asciiz, str6
jmp prompt
dns_error:
invoke con_write_asciiz, str5
jmp prompt
hostname_error:
invoke con_write_asciiz, str11
jmp prompt
closed:
invoke con_write_asciiz, str12
jmp prompt
done:
invoke con_exit, 1
exit:
mcall close, [socketnum]
mcall -1
thread:
mcall 40, 0
.loop:
invoke con_getch2
mov [send_data], ax
xor esi, esi
inc esi
test al, al
jnz @f
inc esi
@@:
mcall send, [socketnum], send_data
invoke con_get_flags
test eax, 0x200 ; con window closed?
jz .loop
mcall -1
; data
title db 'Telnet',0
str1 db 'Telnet for KolibriOS',10,10,\
'Please enter URL of telnet server (host:port)',10,10,\
'fun stuff:',10,\
'telehack.com - arpanet simulator',10,\
'towel.blinkenlights.nl - ASCII Star Wars',10,\
'nyancat.dakko.us - Nyan cat',10,10,0
str2 db '> ',0
str3 db 'Connecting to ',0
str4 db 10,0
str8 db ' (',0
str9 db ')',10,0
str5 db 'Name resolution failed.',10,10,0
str6 db 'Could not open socket.',10,10,0
str11 db 'Invalid hostname.',10,10,0
str12 db 10,'Remote host closed the connection.',10,10,0
sockaddr1:
dw AF_INET4
.port dw 0
.ip dd 0
rb 10
align 4
@IMPORT:
library network, 'network.obj', console, 'console.obj'
import network, \
getaddrinfo, 'getaddrinfo', \
freeaddrinfo, 'freeaddrinfo', \
inet_ntoa, 'inet_ntoa'
import console, \
con_start, 'START', \
con_init, 'con_init', \
con_write_asciiz, 'con_write_asciiz', \
con_exit, 'con_exit', \
con_gets, 'con_gets',\
con_cls, 'con_cls',\
con_getch2, 'con_getch2',\
con_set_cursor_pos, 'con_set_cursor_pos',\
con_write_string, 'con_write_string',\
con_get_flags, 'con_get_flags'
i_end:
socketnum dd ?
buffer_ptr rb BUFFERSIZE+1
send_data dw ?
hostname rb 1024
mem: