telnetStatus of little use?

I'm trying to create a device driver which communicates via telnet. It would be very useful if I could know if a connection is successful, if it got dropped, if the other end isn't responding, etc.

The docs say:

  • telnetStatus(String message) - This method is called with any status messages from the telnet connection (disconnections, errors during connect, etc)

I have basically this in my code:

def telnetStatus(String status) {
    log.debug "telnetStatus: ${status}"
    ...
}

...and the only log message I ever see is "telnetStatus: receive error: Stream is closed". And, that appears on a successfully opened connection! Disconnect the other end (power off), nothing - try to send to it, nothing. But if I reset a host which is connected (to force the connection closed from the far side), I will also get that message when trying to send. So apparently "receive error: Stream is closed" means both a successful connection and only sometimes a failed one.

If I try to open telnet to a non-existent host...

try {
        telnetConnect([terminalType: 'VT100', termChars:[13]], "${ipaddress}", 4998, null, null)
    } catch(e) {
		log.warn "Initialize Error: ${e.message}"

I'll get an error (Initialize Error: No route to host (Host unreachable)) back from the connect, but nothing sent to telnetStatus.

So, the one and only message I ever get to telnetStatus is incorrect. Is it me? Am I doing something wrong, or is the telnet interface simply not working as documented?

1 Like

@bobbyD Any comment? If the telnet driver isn't working as documented, when can a fix be expected?

@Hubitat_Staff

@bravenel

Sorry, I don't know much about this that would be of help. We use telnet for our Lutron integration, and it works reliably -- can't speak to the documentation. I do know that "receive error: Stream is closed" means that telnet is starting up, and that we give the connection 1000 msecs after calling telnetConnect for the connection to start up.

Bruce, aren't the the head guy? How can you not "know much about this that would be of help" and why can't you "speak to the documentation?" If not you, who at Hubitat?

"receive error: Stream is closed" means that telnet is starting up

Which makes absolutely no sense. Reporting "error" for a successful connection? Nonsense.

Yes, it does "work" as long as there are zero issues - no network problems, the other end doesn't get reset, etc. But it's not robust and reliable.

1 Like

Thanks for your feedback. As the documentation says, this error should occur only when the connection drops. There is no successful connection generated by the platform. We passed your feedback to our engineers for further review, but with upcoming major release, this review is not a high priority at the moment.

3 Likes

If a connection fails during a receive read, you'll get a "receive error: Stream is closed" message. This is a legacy/compatibility message, the code explicitly send that exact string regardless of actual cause. In fact, there's this explicit comment in our source code:

// keep "receive error: Stream is closed" EXACTLY as it is - there's tons of code out there expecting it!

If there is an existing connection, and telnet call reopens it, previous connection's closing will result in a "receive error: Stream is closed" message as well. You're correct that it doesn't make a lot of sense on connect. Got to see if changing that logic results in any failures.

If a connection fails during a send operation, you'll get a "send error: <actual_description_here>" message.

For connect failure, there is no feedback in telnetStatus, it just fails during connect call and throws whatever exception occurs right away.

3 Likes

LOL, who could possibly know everything about the hub? I know somethings quite well, but many topics I have only 'user' level knowledge or experience. I don't study the documentation to see if it is all correct and makes sense, although I do have a high level of confidence in the person who does the documentation. I'm not sure what you were expecting when you tagged me, but evidently you got the answers you need from others.

9 Likes

If you need an example of telnet, you can look at Denny Page UPS NUT driver.

I still think Bruce knows everything. He is just shy.

3 Likes

makes no sense in our context becuase that message is coming out whenever a telnet connection even implicitly with telnetclose is closed.. and there is no way to capture it so there reallly is no way to handle it as far as i can tell.. it would be nice to get rid of it.. or at least an option to turn it off. the assumption is that telnet should always be open but that is simply not true there are many uses of telnet where you open a connection .. do some stuff and close and then you will get that message like it is an error.

so removing it should not break anything because there is no way to sense it or handle it anyway.

2 Likes

I did some more testing.

  1. Open a telnet connection, power off remote host. Let it sit idle for over 30 minutes. Nothing happens, the connection remains open.

  2. Open a connection, power off remote host. Send something to the dead host. After about 15 minutes (TCP ack timeout?), "receive error: Stream is closed" is received. For a modern network, it does seem a bit long, though. This is good, but means the driver would have to poll occasionally to avoid an idle connection in order to discover a dead host. Better to fix #1.

  3. Open a connection and reboot remote host (which means it doesn't know about the open connection, but is listening for new ones). Send something. "receive error: Stream is closed" is immediately received. Presumably, it's from getting a "connection refused."

I'd bet that in case 1, it would sit there with the connection open forever. The solution at the telnet layer may be to send a telnet NOP on occasion, assuming the receive error in #2 is coming from the lack of a TCP ack. Telnet won't get a response, but TCP should close the connection due to an ack timeout. Or better still, at the TCP level, implement TCP keep-alives (which should also cover other connection oriented protocols - websocket, raw sockets, ?).

For cases 2 and 3, the message received is the same as what's received on a successful connection. That causes grief. In order to use it, the driver would have to ignore the first such message after each connect. Better to eliminate the message when opening a connection. Better yet to provide a "telnet connected" message.

Here's an interesting blog discussing zombie TCP sockets.

I've never seen one of those. Perhaps a send failure can only occur if the hub's network connection is down.