Rev 4020 | Go to most recent revision | Only display areas with differences | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 4020 | Rev 4743 | ||
---|---|---|---|
1 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
1 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
2 | ;; ;; |
2 | ;; ;; |
3 | ;; Copyright (C) KolibriOS team 2010-2013. All rights reserved. ;; |
3 | ;; Copyright (C) KolibriOS team 2010-2013. All rights reserved. ;; |
4 | ;; Distributed under terms of the GNU General Public License ;; |
4 | ;; Distributed under terms of the GNU General Public License ;; |
5 | ;; ;; |
5 | ;; ;; |
6 | ;; telnet.asm - Telnet client for KolibriOS ;; |
6 | ;; telnet.asm - Telnet client for KolibriOS ;; |
7 | ;; ;; |
7 | ;; ;; |
8 | ;; Written by hidnplayr@kolibrios.org ;; |
8 | ;; Written by hidnplayr@kolibrios.org ;; |
9 | ;; ;; |
9 | ;; ;; |
10 | ;; GNU GENERAL PUBLIC LICENSE ;; |
10 | ;; GNU GENERAL PUBLIC LICENSE ;; |
11 | ;; Version 2, June 1991 ;; |
11 | ;; Version 2, June 1991 ;; |
12 | ;; ;; |
12 | ;; ;; |
13 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
13 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
14 | 14 | ||
15 | format binary as "" |
15 | format binary as "" |
16 | 16 | ||
17 | __DEBUG__ = 0 |
17 | __DEBUG__ = 0 |
18 | __DEBUG_LEVEL__ = 1 |
18 | __DEBUG_LEVEL__ = 1 |
19 | BUFFERSIZE = 4096 |
19 | BUFFERSIZE = 4096 |
20 | 20 | ||
21 | use32 |
21 | use32 |
22 | ; standard header |
22 | ; standard header |
23 | db 'MENUET01' ; signature |
23 | db 'MENUET01' ; signature |
24 | dd 1 ; header version |
24 | dd 1 ; header version |
25 | dd start ; entry point |
25 | dd start ; entry point |
26 | dd i_end ; initialized size |
26 | dd i_end ; initialized size |
27 | dd mem+4096 ; required memory |
27 | dd mem+4096 ; required memory |
28 | dd mem+4096 ; stack pointer |
28 | dd mem+4096 ; stack pointer |
29 | dd hostname ; parameters |
29 | dd hostname ; parameters |
30 | dd 0 ; path |
30 | dd 0 ; path |
31 | 31 | ||
32 | include '../../macros.inc' |
32 | include '../../macros.inc' |
33 | purge mov,add,sub |
33 | purge mov,add,sub |
34 | include '../../proc32.inc' |
34 | include '../../proc32.inc' |
35 | include '../../dll.inc' |
35 | include '../../dll.inc' |
36 | include '../../debug-fdo.inc' |
36 | include '../../debug-fdo.inc' |
37 | include '../../network.inc' |
37 | include '../../network.inc' |
38 | 38 | ||
39 | ; entry point |
39 | ; entry point |
40 | start: |
40 | start: |
41 | ; load libraries |
41 | ; load libraries |
42 | stdcall dll.Load, @IMPORT |
42 | stdcall dll.Load, @IMPORT |
43 | test eax, eax |
43 | test eax, eax |
44 | jnz exit |
44 | jnz exit |
45 | ; initialize console |
45 | ; initialize console |
46 | push 1 |
46 | push 1 |
47 | call [con_start] |
47 | call [con_start] |
48 | push title |
48 | push title |
49 | push 25 |
49 | push 25 |
50 | push 80 |
50 | push 80 |
51 | push 25 |
51 | push 25 |
52 | push 80 |
52 | push 80 |
53 | call [con_init] |
53 | call [con_init] |
54 | 54 | ||
55 | ; Check for parameters |
55 | ; Check for parameters |
56 | cmp byte [hostname], 0 |
56 | cmp byte [hostname], 0 |
57 | jne resolve |
57 | jne resolve |
58 | 58 | ||
59 | main: |
59 | main: |
60 | call [con_cls] |
60 | call [con_cls] |
61 | ; Welcome user |
61 | ; Welcome user |
62 | push str1 |
62 | push str1 |
63 | call [con_write_asciiz] |
63 | call [con_write_asciiz] |
64 | 64 | ||
65 | prompt: |
65 | prompt: |
66 | ; write prompt |
66 | ; write prompt |
67 | push str2 |
67 | push str2 |
68 | call [con_write_asciiz] |
68 | call [con_write_asciiz] |
69 | ; read string |
69 | ; read string |
70 | mov esi, hostname |
70 | mov esi, hostname |
71 | push 256 |
71 | push 256 |
72 | push esi |
72 | push esi |
73 | call [con_gets] |
73 | call [con_gets] |
74 | ; check for exit |
74 | ; check for exit |
75 | test eax, eax |
75 | test eax, eax |
76 | jz done |
76 | jz done |
77 | cmp byte [esi], 10 |
77 | cmp byte [esi], 10 |
78 | jz done |
78 | jz done |
79 | 79 | ||
80 | resolve: |
80 | resolve: |
81 | 81 | ||
82 | mov [sockaddr1.port], 23 shl 8 |
82 | mov [sockaddr1.port], 23 shl 8 |
83 | 83 | ||
84 | ; delete terminating '\n' |
84 | ; delete terminating '\n' |
85 | mov esi, hostname |
85 | mov esi, hostname |
86 | @@: |
86 | @@: |
87 | lodsb |
87 | lodsb |
88 | cmp al, ':' |
88 | cmp al, ':' |
89 | je .do_port |
89 | je .do_port |
90 | cmp al, 0x20 |
90 | cmp al, 0x20 |
91 | ja @r |
91 | ja @r |
92 | mov byte [esi-1], 0 |
92 | mov byte [esi-1], 0 |
93 | jmp .done |
93 | jmp .done |
94 | 94 | ||
95 | .do_port: |
95 | .do_port: |
96 | xor eax, eax |
96 | xor eax, eax |
97 | xor ebx, ebx |
97 | xor ebx, ebx |
98 | mov byte [esi-1], 0 |
98 | mov byte [esi-1], 0 |
99 | .portloop: |
99 | .portloop: |
100 | lodsb |
100 | lodsb |
101 | cmp al, 0x20 |
101 | cmp al, 0x20 |
102 | jbe .port_done |
102 | jbe .port_done |
103 | sub al, '0' |
103 | sub al, '0' |
104 | jb hostname_error |
104 | jb hostname_error |
105 | cmp al, 9 |
105 | cmp al, 9 |
106 | ja hostname_error |
106 | ja hostname_error |
107 | lea ebx, [ebx*4 + ebx] |
107 | lea ebx, [ebx*4 + ebx] |
108 | shl ebx, 1 |
108 | shl ebx, 1 |
109 | add ebx, eax |
109 | add ebx, eax |
110 | jmp .portloop |
110 | jmp .portloop |
111 | 111 | ||
112 | .port_done: |
112 | .port_done: |
113 | xchg bl, bh |
113 | xchg bl, bh |
114 | mov [sockaddr1.port], bx |
114 | mov [sockaddr1.port], bx |
115 | 115 | ||
116 | .done: |
116 | .done: |
117 | 117 | ||
118 | ; resolve name |
118 | ; resolve name |
119 | push esp ; reserve stack place |
119 | push esp ; reserve stack place |
120 | push esp ; ptr to result |
120 | push esp ; ptr to result |
121 | push 0 ; addrinfo hints |
121 | push 0 ; addrinfo hints |
122 | push 0 ; servname |
122 | push 0 ; servname |
123 | push hostname; hostname |
123 | push hostname; hostname |
124 | call [getaddrinfo] |
124 | call [getaddrinfo] |
125 | pop esi |
125 | pop esi |
126 | ; test for error |
126 | ; test for error |
127 | test eax, eax |
127 | test eax, eax |
128 | jnz dns_error |
128 | jnz dns_error |
129 | 129 | ||
130 | call [con_cls] |
130 | call [con_cls] |
131 | push str3 |
131 | push str3 |
132 | call [con_write_asciiz] |
132 | call [con_write_asciiz] |
133 | push hostname |
133 | push hostname |
134 | call [con_write_asciiz] |
134 | call [con_write_asciiz] |
135 | 135 | ||
136 | ; write results |
136 | ; write results |
137 | push str8 |
137 | push str8 |
138 | call [con_write_asciiz] |
138 | call [con_write_asciiz] |
139 | ; mov edi, esi |
139 | ; mov edi, esi |
140 | 140 | ||
141 | ; convert IP address to decimal notation |
141 | ; convert IP address to decimal notation |
142 | mov eax, [esi+addrinfo.ai_addr] |
142 | mov eax, [esi+addrinfo.ai_addr] |
143 | mov eax, [eax+sockaddr_in.sin_addr] |
143 | mov eax, [eax+sockaddr_in.sin_addr] |
144 | mov [sockaddr1.ip], eax |
144 | mov [sockaddr1.ip], eax |
145 | push eax |
145 | push eax |
146 | call [inet_ntoa] |
146 | call [inet_ntoa] |
147 | ; write result |
147 | ; write result |
148 | push eax |
148 | push eax |
149 | call [con_write_asciiz] |
149 | call [con_write_asciiz] |
150 | ; free allocated memory |
150 | ; free allocated memory |
151 | push esi |
151 | push esi |
152 | call [freeaddrinfo] |
152 | call [freeaddrinfo] |
153 | 153 | ||
154 | push str9 |
154 | push str9 |
155 | call [con_write_asciiz] |
155 | call [con_write_asciiz] |
156 | 156 | ||
157 | mcall socket, AF_INET4, SOCK_STREAM, 0 |
157 | mcall socket, AF_INET4, SOCK_STREAM, 0 |
158 | cmp eax, -1 |
158 | cmp eax, -1 |
159 | jz socket_err |
159 | jz socket_err |
160 | mov [socketnum], eax |
160 | mov [socketnum], eax |
161 | 161 | ||
162 | mcall connect, [socketnum], sockaddr1, 18 |
162 | mcall connect, [socketnum], sockaddr1, 18 |
163 | test eax, eax |
163 | test eax, eax |
164 | jnz socket_err |
164 | jnz socket_err |
165 | 165 | ||
166 | mcall 40, 1 shl 7 ; + 7 |
166 | mcall 40, 1 shl 7 ; + 7 |
167 | call [con_cls] |
167 | call [con_cls] |
168 | 168 | ||
169 | mcall 18, 7 |
169 | mcall 18, 7 |
170 | push eax |
170 | push eax |
171 | mcall 51, 1, thread, mem - 2048 |
171 | mcall 51, 1, thread, mem - 2048 |
172 | pop ecx |
172 | pop ecx |
173 | mcall 18, 3 |
173 | mcall 18, 3 |
174 | 174 | ||
175 | mainloop: |
175 | mainloop: |
176 | call [con_get_flags] |
176 | call [con_get_flags] |
177 | test eax, 0x200 ; con window closed? |
177 | test eax, 0x200 ; con window closed? |
178 | jnz exit |
178 | jnz exit |
179 | 179 | ||
180 | mcall recv, [socketnum], buffer_ptr, BUFFERSIZE, 0 |
180 | mcall recv, [socketnum], buffer_ptr, BUFFERSIZE, 0 |
181 | cmp eax, -1 |
181 | cmp eax, -1 |
182 | je closed |
182 | je closed |
183 | 183 | ||
184 | 184 | ||
185 | DEBUGF 1, 'TELNET: got %u bytes of data !\n', eax |
185 | DEBUGF 1, 'TELNET: got %u bytes of data !\n', eax |
186 | 186 | ||
187 | mov esi, buffer_ptr |
187 | mov esi, buffer_ptr |
188 | lea edi, [esi + eax] |
188 | lea edi, [esi + eax] |
189 | mov byte [edi], 0 |
189 | mov byte [edi], 0 |
190 | 190 | ||
191 | .scan_cmd: |
191 | .scan_cmd: |
192 | cmp byte [esi], 0xff ; Interpret As Command |
192 | cmp byte [esi], 0xff ; Interpret As Command |
193 | jne .no_cmd |
193 | jne .no_cmd |
194 | ; TODO: parse options, for now, we will reply with 'WONT' to everything |
194 | ; TODO: parse options, for now, we will reply with 'WONT' to everything |
195 | mov byte [esi + 1], 252 ; WONT |
195 | mov byte [esi + 1], 252 ; WONT |
196 | add esi, 3 ; a command is always 3 bytes |
196 | add esi, 3 ; a command is always 3 bytes |
197 | jmp .scan_cmd |
197 | jmp .scan_cmd |
198 | .no_cmd: |
198 | .no_cmd: |
199 | 199 | ||
200 | cmp esi, buffer_ptr |
200 | cmp esi, buffer_ptr |
201 | je .print |
201 | je .print |
202 | 202 | ||
203 | DEBUGF 1, 'TELNET: sending data\n' |
203 | DEBUGF 1, 'TELNET: sending data\n' |
204 | 204 | ||
205 | push esi edi |
205 | push esi edi |
206 | sub esi, buffer_ptr |
206 | sub esi, buffer_ptr |
207 | mcall send, [socketnum], buffer_ptr, , 0 |
207 | mcall send, [socketnum], buffer_ptr, , 0 |
208 | pop edi esi |
208 | pop edi esi |
209 | 209 | ||
210 | .print: |
210 | .print: |
211 | cmp esi, edi |
211 | cmp esi, edi |
212 | jae mainloop |
212 | jae mainloop |
213 | 213 | ||
214 | push esi |
214 | push esi |
215 | call [con_write_asciiz] |
215 | call [con_write_asciiz] |
216 | 216 | ||
217 | .loop: |
217 | .loop: |
218 | lodsb |
218 | lodsb |
219 | test al, al |
219 | test al, al |
220 | jz .print |
220 | jz .print |
221 | jmp .loop |
221 | jmp .loop |
222 | 222 | ||
223 | 223 | ||
224 | socket_err: |
224 | socket_err: |
225 | DEBUGF 1, "TELNET: socket error %d", ebx |
225 | DEBUGF 1, "TELNET: socket error %d", ebx |
226 | push str6 |
226 | push str6 |
227 | call [con_write_asciiz] |
227 | call [con_write_asciiz] |
228 | 228 | ||
229 | jmp prompt |
229 | jmp prompt |
230 | 230 | ||
231 | dns_error: |
231 | dns_error: |
232 | DEBUGF 1, "TELNET: DNS error %d", eax |
232 | DEBUGF 1, "TELNET: DNS error %d", eax |
233 | push str5 |
233 | push str5 |
234 | call [con_write_asciiz] |
234 | call [con_write_asciiz] |
235 | 235 | ||
236 | jmp prompt |
236 | jmp prompt |
237 | 237 | ||
238 | hostname_error: |
238 | hostname_error: |
239 | push str11 |
239 | push str11 |
240 | call [con_write_asciiz] |
240 | call [con_write_asciiz] |
241 | jmp prompt |
241 | jmp prompt |
242 | 242 | ||
243 | closed: |
243 | closed: |
244 | push str12 |
244 | push str12 |
245 | call [con_write_asciiz] |
245 | call [con_write_asciiz] |
246 | jmp prompt |
246 | jmp prompt |
247 | 247 | ||
248 | done: |
248 | done: |
249 | push 1 |
249 | push 1 |
250 | call [con_exit] |
250 | call [con_exit] |
251 | exit: |
251 | exit: |
252 | 252 | ||
253 | mcall close, [socketnum] |
253 | mcall close, [socketnum] |
254 | mcall -1 |
254 | mcall -1 |
255 | 255 | ||
256 | 256 | ||
257 | 257 | ||
258 | thread: |
258 | thread: |
259 | mcall 40, 0 |
259 | mcall 40, 0 |
260 | .loop: |
260 | .loop: |
261 | call [con_getch2] |
261 | call [con_getch2] |
262 | mov [send_data], ax |
262 | mov [send_data], ax |
263 | xor esi, esi |
263 | xor esi, esi |
264 | inc esi |
264 | inc esi |
265 | test al, al |
265 | test al, al |
266 | jnz @f |
266 | jnz @f |
267 | inc esi |
267 | inc esi |
268 | @@: |
268 | @@: |
269 | mcall send, [socketnum], send_data |
269 | mcall send, [socketnum], send_data |
270 | 270 | ||
271 | call [con_get_flags] |
271 | call [con_get_flags] |
272 | test eax, 0x200 ; con window closed? |
272 | test eax, 0x200 ; con window closed? |
273 | jz .loop |
273 | jz .loop |
274 | mcall -1 |
274 | mcall -1 |
275 | 275 | ||
276 | ; data |
276 | ; data |
277 | title db 'Telnet',0 |
277 | title db 'Telnet',0 |
278 | str1 db 'Telnet for KolibriOS',10,10,\ |
278 | str1 db 'Telnet for KolibriOS',10,10,\ |
279 | 'Please enter URL of telnet server (host:port)',10,10,\ |
279 | 'Please enter URL of telnet server (host:port)',10,10,\ |
280 | 'fun stuff:',10,\ |
280 | 'fun stuff:',10,\ |
281 | 'telehack.com - arpanet simulator',10,\ |
281 | 'telehack.com - arpanet simulator',10,\ |
282 | 'towel.blinkenlights.nl - ASCII Star Wars',10,\ |
282 | 'towel.blinkenlights.nl - ASCII Star Wars',10,\ |
283 | 'miku.acm.uiuc.edu - Nyan cat',10,10,0 |
283 | 'nyancat.dakko.us - Nyan cat',10,10,0 |
284 | str2 db '> ',0 |
284 | str2 db '> ',0 |
285 | str3 db 'Connecting to ',0 |
285 | str3 db 'Connecting to ',0 |
286 | str4 db 10,0 |
286 | str4 db 10,0 |
287 | str8 db ' (',0 |
287 | str8 db ' (',0 |
288 | str9 db ')',10,0 |
288 | str9 db ')',10,0 |
289 | 289 | ||
290 | str5 db 'Name resolution failed.',10,10,0 |
290 | str5 db 'Name resolution failed.',10,10,0 |
291 | str6 db 'Could not open socket.',10,10,0 |
291 | str6 db 'Could not open socket.',10,10,0 |
292 | str11 db 'Invalid hostname.',10,10,0 |
292 | str11 db 'Invalid hostname.',10,10,0 |
293 | str12 db 10,'Remote host closed the connection.',10,10,0 |
293 | str12 db 10,'Remote host closed the connection.',10,10,0 |
294 | 294 | ||
295 | sockaddr1: |
295 | sockaddr1: |
296 | dw AF_INET4 |
296 | dw AF_INET4 |
297 | .port dw 0 |
297 | .port dw 0 |
298 | .ip dd 0 |
298 | .ip dd 0 |
299 | rb 10 |
299 | rb 10 |
300 | 300 | ||
301 | include_debug_strings ; ALWAYS present in data section |
301 | include_debug_strings ; ALWAYS present in data section |
302 | 302 | ||
303 | 303 | ||
304 | 304 | ||
305 | ; import |
305 | ; import |
306 | align 4 |
306 | align 4 |
307 | @IMPORT: |
307 | @IMPORT: |
308 | 308 | ||
309 | library network, 'network.obj', console, 'console.obj' |
309 | library network, 'network.obj', console, 'console.obj' |
310 | import network, \ |
310 | import network, \ |
311 | getaddrinfo, 'getaddrinfo', \ |
311 | getaddrinfo, 'getaddrinfo', \ |
312 | freeaddrinfo, 'freeaddrinfo', \ |
312 | freeaddrinfo, 'freeaddrinfo', \ |
313 | inet_ntoa, 'inet_ntoa' |
313 | inet_ntoa, 'inet_ntoa' |
314 | import console, \ |
314 | import console, \ |
315 | con_start, 'START', \ |
315 | con_start, 'START', \ |
316 | con_init, 'con_init', \ |
316 | con_init, 'con_init', \ |
317 | con_write_asciiz, 'con_write_asciiz', \ |
317 | con_write_asciiz, 'con_write_asciiz', \ |
318 | con_exit, 'con_exit', \ |
318 | con_exit, 'con_exit', \ |
319 | con_gets, 'con_gets',\ |
319 | con_gets, 'con_gets',\ |
320 | con_cls, 'con_cls',\ |
320 | con_cls, 'con_cls',\ |
321 | con_getch2, 'con_getch2',\ |
321 | con_getch2, 'con_getch2',\ |
322 | con_set_cursor_pos, 'con_set_cursor_pos',\ |
322 | con_set_cursor_pos, 'con_set_cursor_pos',\ |
323 | con_write_string, 'con_write_string',\ |
323 | con_write_string, 'con_write_string',\ |
324 | con_get_flags, 'con_get_flags' |
324 | con_get_flags, 'con_get_flags' |
325 | 325 | ||
326 | 326 | ||
327 | i_end: |
327 | i_end: |
328 | 328 | ||
329 | socketnum dd ? |
329 | socketnum dd ? |
330 | buffer_ptr rb BUFFERSIZE+1 |
330 | buffer_ptr rb BUFFERSIZE+1 |
331 | send_data dw ? |
331 | send_data dw ? |
332 | 332 | ||
333 | hostname rb 1024 |
333 | hostname rb 1024 |
334 | 334 | ||
335 | mem: |
335 | mem: |