I try to write Swift snippets to send commands to Telnet but I need to log in first.
On OSX I generated a Telnet service: launchctl load -F /System/Library/LaunchDaemons/telnet.plist. After that I able to connect from other computers to IP: XXX.XXX.X.XXX port 23.
For example from Windows 7:
telnet XXX.XXX.X.XXX 23
.....
Darwin/BSD (fess.local) (ttys009)
login: snaggs
Password:xxxxxx
snaggs:~ lur$
In the command line, Telnet asks me for the user and password. After that I can run any Linux commands. So far so good.
I wrote Telnet module for Android so OSX Telnet service works properly. This means that I see login: and password: outputs so I am able to handle it.
Now I'm stuck with iOS Swift, I Googled and found pretty good solution that should work in my case:
So I wrote my home work:
class TelnetClient : NSObject, NSStreamDelegate{
private var inputStream: NSInputStream!
private var outputStream: NSOutputStream!
func initNetworkCommunication(){
let host : CFString = "XXX.XXX.X.XXX"
let port : UInt32 = 23
var readstream : Unmanaged<CFReadStream>?
var writestream : Unmanaged<CFWriteStream>?
CFStreamCreatePairWithSocketToHost(kCFAllocatorDefault, host, port, &readstream, &writestream)
// var _inputStream: NSInputStream?
// var _outputStream: NSOutputStream?
// NSStream.getStreamsToHostWithName("XXX.XXX.X.XXX", port: 23, inputStream: &_inputStream, outputStream: &_outputStream)
// self.inputStream = _inputStream!
// self.outputStream = _outputStream!
self.inputStream = readstream!.takeRetainedValue()
self.outputStream = writestream!.takeRetainedValue()
self.inputStream.delegate = self
self.outputStream.delegate = self
self.inputStream.scheduleInRunLoop(NSRunLoop.currentRunLoop(), forMode: NSDefaultRunLoopMode)
self.outputStream.scheduleInRunLoop(NSRunLoop.currentRunLoop(), forMode: NSDefaultRunLoopMode)
self.inputStream.open()
self.outputStream.open()
}
func sendMessage(message:String){
let data: NSData = message.dataUsingEncoding(NSASCIIStringEncoding, allowLossyConversion: true)! //NSUTF8StringEncoding
let stream: NSInputStream = NSInputStream(data: data)
var buffer = [UInt8](count: 8, repeatedValue: 0)
stream.open()
if stream.hasBytesAvailable {
let result :Int = stream.read(&buffer, maxLength: buffer.count)
}
self.outputStream.write(&buffer, maxLength: buffer.count)
println("wrote to Server: \(message)")
}
}
Stream callback override method from NSStreamDelegate:
func stream(aStream: NSStream, handleEvent eventCode: NSStreamEvent) {
switch (eventCode){
case NSStreamEvent.ErrorOccurred:
NSLog("ErrorOccurred")
break
case NSStreamEvent.EndEncountered:
NSLog("EndEncountered")
break
case NSStreamEvent.None:
NSLog("None")
break
case NSStreamEvent.HasBytesAvailable:
NSLog("HasBytesAvaible")
// ... NEVER ENTERS HERE
var buffer = [UInt8](count: 4096, repeatedValue: 0)
if ( aStream == self.inputStream){
while (self.inputStream.hasBytesAvailable){
var len = self.inputStream.read(&buffer, maxLength: buffer.count)
if(len > 0){
var output = NSString(bytes: &buffer, length: buffer.count, encoding: NSUTF8StringEncoding)
if (output != ""){
NSLog("server said: %@", output!)
}
}
}
}
break
//case NSStreamEvent.allZeros:
// NSLog("allZeros")
// break
case NSStreamEvent.OpenCompleted:
NSLog("OpenCompleted") // <-- called on initialisation
break
case NSStreamEvent.HasSpaceAvailable:
NSLog("HasSpaceAvailable")
break
default:
NSLog("default")
break
}
}
First of all, nothing happens when I try to call initNetworkCommunication(). I expect calling of func stream or I'm wrong?. It should be NSStreamEvent.HasBytesAvailable state or I'm wrong?
When I call sendMessage("snags"), I get response in stream that falls on case NSStreamEvent.HasSpaceAvailable. What does it mean?
My expected results: on connect I should get login: output but get nothing.