Rev 3703 | Rev 4020 | Go to most recent revision | Only display areas with differences | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 3703 | Rev 3704 | ||
---|---|---|---|
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 | 163 | ||
164 | mcall 40, 1 shl 7 ; + 7 |
164 | mcall 40, 1 shl 7 ; + 7 |
165 | call [con_cls] |
165 | call [con_cls] |
166 | 166 | ||
167 | mcall 18, 7 |
167 | mcall 18, 7 |
168 | push eax |
168 | push eax |
169 | mcall 51, 1, thread, mem - 2048 |
169 | mcall 51, 1, thread, mem - 2048 |
170 | pop ecx |
170 | pop ecx |
171 | mcall 18, 3 |
171 | mcall 18, 3 |
172 | 172 | ||
173 | mainloop: |
173 | mainloop: |
174 | DEBUGF 1, 'TELNET: Waiting for events\n' |
- | |
175 | mcall 10 |
- | |
176 | DEBUGF 1, 'TELNET: EVENT %x !\n', eax |
- | |
177 | - | ||
178 | call [con_get_flags] |
174 | call [con_get_flags] |
179 | test eax, 0x200 ; con window closed? |
175 | test eax, 0x200 ; con window closed? |
180 | jnz exit |
176 | jnz exit |
181 | - | ||
182 | .check_for_data: |
177 | |
183 | mcall recv, [socketnum], buffer_ptr, BUFFERSIZE, 0 |
178 | mcall recv, [socketnum], buffer_ptr, BUFFERSIZE, 0 |
184 | cmp eax, -1 |
- | |
185 | jne .parse_data |
- | |
186 | cmp ebx, 6 ; EWOULDBLOCK |
- | |
187 | je mainloop |
179 | cmp eax, -1 |
188 | jmp closed |
- | |
189 | - | ||
190 | 180 | je closed |
|
191 | .parse_data: |
181 | |
192 | 182 | ||
193 | DEBUGF 1, 'TELNET: got %u bytes of data !\n', eax |
183 | DEBUGF 1, 'TELNET: got %u bytes of data !\n', eax |
194 | 184 | ||
195 | mov esi, buffer_ptr |
185 | mov esi, buffer_ptr |
196 | lea edi, [esi + eax] |
186 | lea edi, [esi + eax] |
197 | mov byte [edi], 0 |
187 | mov byte [edi], 0 |
198 | 188 | ||
199 | .scan_cmd: |
189 | .scan_cmd: |
200 | cmp byte [esi], 0xff ; Interpret As Command |
190 | cmp byte [esi], 0xff ; Interpret As Command |
201 | jne .no_cmd |
191 | jne .no_cmd |
202 | ; TODO: parse options, for now, we will reply with 'WONT' to everything |
192 | ; TODO: parse options, for now, we will reply with 'WONT' to everything |
203 | mov byte [esi + 1], 252 ; WONT |
193 | mov byte [esi + 1], 252 ; WONT |
204 | add esi, 3 ; a command is always 3 bytes |
194 | add esi, 3 ; a command is always 3 bytes |
205 | jmp .scan_cmd |
195 | jmp .scan_cmd |
206 | .no_cmd: |
196 | .no_cmd: |
207 | 197 | ||
208 | cmp esi, buffer_ptr |
198 | cmp esi, buffer_ptr |
209 | je .print |
199 | je .print |
210 | 200 | ||
211 | DEBUGF 1, 'TELNET: sending data\n' |
201 | DEBUGF 1, 'TELNET: sending data\n' |
212 | 202 | ||
213 | push esi edi |
203 | push esi edi |
214 | sub esi, buffer_ptr |
204 | sub esi, buffer_ptr |
215 | mcall send, [socketnum], buffer_ptr, , 0 |
205 | mcall send, [socketnum], buffer_ptr, , 0 |
216 | pop edi esi |
206 | pop edi esi |
217 | 207 | ||
218 | .print: |
208 | .print: |
219 | cmp esi, edi |
209 | cmp esi, edi |
220 | jae .check_for_data |
210 | jae mainloop |
221 | 211 | ||
222 | push esi |
212 | push esi |
223 | call [con_write_asciiz] |
213 | call [con_write_asciiz] |
224 | 214 | ||
225 | .loop: |
215 | .loop: |
226 | lodsb |
216 | lodsb |
227 | test al, al |
217 | test al, al |
228 | jz .print |
218 | jz .print |
229 | jmp .loop |
219 | jmp .loop |
230 | 220 | ||
231 | 221 | ||
232 | socket_err: |
222 | socket_err: |
233 | DEBUGF 1, "TELNET: socket error %d", ebx |
223 | DEBUGF 1, "TELNET: socket error %d", ebx |
234 | push str6 |
224 | push str6 |
235 | call [con_write_asciiz] |
225 | call [con_write_asciiz] |
236 | 226 | ||
237 | jmp prompt |
227 | jmp prompt |
238 | 228 | ||
239 | dns_error: |
229 | dns_error: |
240 | DEBUGF 1, "TELNET: DNS error %d", eax |
230 | DEBUGF 1, "TELNET: DNS error %d", eax |
241 | push str5 |
231 | push str5 |
242 | call [con_write_asciiz] |
232 | call [con_write_asciiz] |
243 | 233 | ||
244 | jmp prompt |
234 | jmp prompt |
245 | 235 | ||
246 | hostname_error: |
236 | hostname_error: |
247 | push str11 |
237 | push str11 |
248 | call [con_write_asciiz] |
238 | call [con_write_asciiz] |
249 | jmp prompt |
239 | jmp prompt |
250 | 240 | ||
251 | closed: |
241 | closed: |
252 | push str12 |
242 | push str12 |
253 | call [con_write_asciiz] |
243 | call [con_write_asciiz] |
254 | jmp prompt |
244 | jmp prompt |
255 | 245 | ||
256 | done: |
246 | done: |
257 | push 1 |
247 | push 1 |
258 | call [con_exit] |
248 | call [con_exit] |
259 | exit: |
249 | exit: |
260 | 250 | ||
261 | mcall close, [socketnum] |
251 | mcall close, [socketnum] |
262 | mcall -1 |
252 | mcall -1 |
263 | 253 | ||
264 | 254 | ||
265 | 255 | ||
266 | thread: |
256 | thread: |
267 | mcall 40, 0 |
257 | mcall 40, 0 |
268 | .loop: |
258 | .loop: |
269 | call [con_getch2] |
259 | call [con_getch2] |
270 | mov byte [send_data], al |
260 | mov byte [send_data], al |
271 | mcall send, [socketnum], send_data, 1 |
261 | mcall send, [socketnum], send_data, 1 |
272 | 262 | ||
273 | call [con_get_flags] |
263 | call [con_get_flags] |
274 | test eax, 0x200 ; con window closed? |
264 | test eax, 0x200 ; con window closed? |
275 | jz .loop |
265 | jz .loop |
276 | mcall -1 |
266 | mcall -1 |
277 | 267 | ||
278 | ; data |
268 | ; data |
279 | title db 'Telnet',0 |
269 | title db 'Telnet',0 |
280 | str1 db 'Telnet for KolibriOS',10,10,\ |
270 | str1 db 'Telnet for KolibriOS',10,10,\ |
281 | 'Please enter URL of telnet server (for example: towel.blinkenlights.nl:23)',10,10,0 |
271 | 'Please enter URL of telnet server (for example: towel.blinkenlights.nl:23)',10,10,0 |
282 | str2 db '> ',0 |
272 | str2 db '> ',0 |
283 | str3 db 'Connecting to ',0 |
273 | str3 db 'Connecting to ',0 |
284 | str4 db 10,0 |
274 | str4 db 10,0 |
285 | str8 db ' (',0 |
275 | str8 db ' (',0 |
286 | str9 db ')',10,0 |
276 | str9 db ')',10,0 |
287 | 277 | ||
288 | str5 db 'Name resolution failed.',10,10,0 |
278 | str5 db 'Name resolution failed.',10,10,0 |
289 | str6 db 'Could not open socket.',10,10,0 |
279 | str6 db 'Could not open socket.',10,10,0 |
290 | str11 db 'Invalid hostname.',10,10,0 |
280 | str11 db 'Invalid hostname.',10,10,0 |
291 | str12 db 10,'Remote host closed the connection.',10,10,0 |
281 | str12 db 10,'Remote host closed the connection.',10,10,0 |
292 | 282 | ||
293 | sockaddr1: |
283 | sockaddr1: |
294 | dw AF_INET4 |
284 | dw AF_INET4 |
295 | .port dw 0 |
285 | .port dw 0 |
296 | .ip dd 0 |
286 | .ip dd 0 |
297 | rb 10 |
287 | rb 10 |
298 | 288 | ||
299 | include_debug_strings ; ALWAYS present in data section |
289 | include_debug_strings ; ALWAYS present in data section |
300 | 290 | ||
301 | 291 | ||
302 | 292 | ||
303 | ; import |
293 | ; import |
304 | align 4 |
294 | align 4 |
305 | @IMPORT: |
295 | @IMPORT: |
306 | 296 | ||
307 | library network, 'network.obj', console, 'console.obj' |
297 | library network, 'network.obj', console, 'console.obj' |
308 | import network, \ |
298 | import network, \ |
309 | getaddrinfo, 'getaddrinfo', \ |
299 | getaddrinfo, 'getaddrinfo', \ |
310 | freeaddrinfo, 'freeaddrinfo', \ |
300 | freeaddrinfo, 'freeaddrinfo', \ |
311 | inet_ntoa, 'inet_ntoa' |
301 | inet_ntoa, 'inet_ntoa' |
312 | import console, \ |
302 | import console, \ |
313 | con_start, 'START', \ |
303 | con_start, 'START', \ |
314 | con_init, 'con_init', \ |
304 | con_init, 'con_init', \ |
315 | con_write_asciiz, 'con_write_asciiz', \ |
305 | con_write_asciiz, 'con_write_asciiz', \ |
316 | con_exit, 'con_exit', \ |
306 | con_exit, 'con_exit', \ |
317 | con_gets, 'con_gets',\ |
307 | con_gets, 'con_gets',\ |
318 | con_cls, 'con_cls',\ |
308 | con_cls, 'con_cls',\ |
319 | con_getch2, 'con_getch2',\ |
309 | con_getch2, 'con_getch2',\ |
320 | con_set_cursor_pos, 'con_set_cursor_pos',\ |
310 | con_set_cursor_pos, 'con_set_cursor_pos',\ |
321 | con_write_string, 'con_write_string',\ |
311 | con_write_string, 'con_write_string',\ |
322 | con_get_flags, 'con_get_flags' |
312 | con_get_flags, 'con_get_flags' |
323 | 313 | ||
324 | 314 | ||
325 | i_end: |
315 | i_end: |
326 | 316 | ||
327 | socketnum dd ? |
317 | socketnum dd ? |
328 | buffer_ptr rb BUFFERSIZE+1 |
318 | buffer_ptr rb BUFFERSIZE+1 |
329 | send_data rb 1 |
319 | send_data rb 1 |
330 | 320 | ||
331 | hostname rb 1024 |
321 | hostname rb 1024 |
332 | 322 | ||
333 | mem: |
323 | mem: |