Right, for anyone who read the previous post below, an update - the code now works!
It seems that when writing the stream, something was getting a bit carried away. With some assistance from Wireshark I got there in the end! Firstly, the first write request (IAC) was sending two bytes - FF and 00, even though the byte stream only had FF in it. Having tracked this down and forced it to 1 byte we got the IAC ok. Things then got worse as the second byte (IAC_COMMAND) was sending a 4k fragmented packet and the final byte (IAC_OPTION) was sending an 8k fragmented packet. Ouch! Forcing each response to a length of 1 got the right messages through (although I did notice it cocks the odd one up). Happily though it works fine with the Solaris box I am trying to get to and I get a "login:" prompt.
Remember this is not for a fully blown standards compliant Telnet type thing - just a rough job to get us logged into something and get some data back.
Hope this helps all those out there that were struggling!
So (pre-tidyup) the code now looks like (apologies for blog removing my indents):
Imports System.Net
Imports System.Net.Sockets
Public IAC As Integer = 255
Public IAC_WILL As Integer = 251
Public IAC_WONT As Integer = 252
Public IAC_DO As Integer = 253
Public IAC_DONT As Integer = 254
Dim returndata As String = Encoding.Unicode.GetString(bytes) ' data that comes back
Dim threebits As String = Chr(255) & Chr(255) & Chr(255) ' variable to keep track of the last three bytes
Dim command As Integer ' variable to store the IAC Command (well the integer equiv for CHR)
command = 0
' now a nasty while - basically we are saying that if any byte in the last three is a control byte
' (i.e. above 250) or any byte is a stream of 0's (found this needed trapping for reasons beyond me)
' we keep reading data and treating this as negotiation
While (Asc(Mid(threebits, 1, 1)) > 250 Or Asc(Mid(threebits, 2, 1)) > 250 Or Asc(Mid(threebits, 3, 1)) > 250) Or _
(Asc(Mid(threebits, 1, 1)) = 0 Or Asc(Mid(threebits, 2, 1)) = 0 Or Asc(Mid(threebits, 3, 1)) = 0)
Try ' just try it - if it fails, we'll handle it
networkStream.ReadTimeout = 1000 ' 1 second timeout (can skip this if you like but it
' does allow for interaction with the user
networkStream.Read(bytes, 0, 1) ' read 1 byte
returndata = Encoding.Unicode.GetString(bytes) ' store the byte as a string
threebits = Mid(threebits & returndata, 2, 3) ' sort out the three bytes
Catch
returndata = Chr(1) ' if we didn't get any data then let's call it chr(1)
End Try
Application.DoEvents() ' give the user some control
' I have a button called get_data that initiates the get. when it is clicked it
' changes it's text to "Stop". before any of this runs, when the user clicks it it checks
' to see what it's current text is and changs it to the inverse. So if it says
' get data, it changes it to stop and vice versa. Here in the loop (and in any other
' collection loop) we check to see if it has been changed to "get data" - if it has the
' user must have clicked stop - therefore we exit the sub
If get_data.Text = "Get data" Then
Exit Sub
End If
' now we decide on actions - basically act dumb - say no to everything!
Select Case Asc(returndata)
Case IAC_WILL ' will
command = IAC_WILL
Case IAC_WONT ' won't
command = IAC_WONT
Case IAC_DO ' do
command = IAC_WONT
Case IAC_DONT ' don't
command = IAC_WONT
Case IAC ' control req.
command = IAC
Case 1 ' this is our dummy case - ie no data read
Case Else ' traps the option value case, or plain text case
If command > 0 Then ' make sure we have a command to reply to - if not its just text
sendBytes = Encoding.Unicode.GetBytes(Chr(IAC)) ' IAC
networkStream.Write(sendBytes, 0, 1) ' 1 byte!
sendBytes = Encoding.Unicode.GetBytes(Chr(command)) ' command
networkStream.Write(sendBytes, 0, 1) ' 1 byte
sendBytes = Encoding.Unicode.GetBytes(returndata) ' return the option sent
networkStream.Write(sendBytes, 0, 1)
End If
command = 0
End Select
End While ' and loop but exit if we get three bytes of normal data
' that's the end of telnet negotiation (in the initial instance anyhow)
' and your code goes here, loop reading the data 1 byte (or more at a time) and do what you will.
' something like below might help
dim usernamedone as system.boolean = false
Do Until jobdone = True
Application.DoEvents()
If get_data.Text = "Get data" Then
Exit Sub
End If
Dim returndata As String = Encoding.Unicode.GetString(bytes)
Try
networkStream.ReadTimeout = 1000
networkStream.Read(bytes, 0, 1)
returndata = Encoding.Unicode.GetString(bytes)
Catch
returndata = ""
End Try
' outputbox is a multi-line text box on my form - shows the user the interaction in progress
' more for my diagnostics than anything else!
outputbox.Text = outputbox.Text & returndata
' note that username_prompt and password_prompt are textboxes on my form
If InStr(outputbox.Text, username_prompt.Text) and not usernamedone Then
! NOTE CHANGE TO ASCII ENCODE
sendBytes = Encoding.ASCII.GetBytes(username.Text & vbCrLf)
networkStream.Write(sendBytes, 0, sendBytes.Length)
usernamedone=true
statusupdate("Username sent")
End If
If InStr(outputbox.Text, Password_prompt.Text) Then
sendBytes = Encoding.ASCII.GetBytes(password.Text & vbCrLf)
networkStream.Write(sendBytes, 0, sendBytes.Length)
statusupdate("Password sent")
jobdone = True
End If
Loop
Subscribe to:
Post Comments (Atom)
Blog Archive
-
▼
2009
(14)
-
▼
May
(8)
- Using registry from VB.net/express
- Textbox handling control-C copy/paste
- Multiline Textbox update with autoscroll and less ...
- VB (.net/2008 express) Telnet to SUN Solaris - don...
- VB (2008/.net but anything really)- Telnet
- Sourceforge - how to upload web pages to a project...
- Todays challenge - learning C or C++ or something
- Welcome to my head - online!This is basically what...
-
▼
May
(8)
No comments:
Post a Comment