Home AMX User Forum AMXForums Archive Threads Tips and Tricks

Telnet into Nion with AMX

I'm trying to telnet into a Nion from AMX to perform an unattended reboot if it goes into fault, but having no luck. Seems like it would be more graceful than resetting the power. AMX diagnostics tells me the port(23) is open, but the Nion does not respond to the "root" or "shutdown -r now" command like a DOS/puTTY telnet session does. Attached is a piece of AMX code I used for testing. This is the string I'm getting back when I open the port with the "IP_Client_Open" function...
$FF$FD$18$FF$FD $FF$FD#$FF$FD'
Anyone have any ideas on what I might be doing wrong?
AMX Code

DEFINE_DEVICE

dvNION_TN_PORT = 0:4:0
dvTP = 10001:1:0   

DEFINE_VARIABLE

VOLATILE CHAR cNIONIP[15] = '10.42.51.39'  //IP ADDRESS OF NION
LONG TELNET_PORT    =    23

DEFINE_EVENT

BUTTON_EVENT[dvTP,1]
{
   Push:
   {
      IP_CLIENT_OPEN(dvNION_TN_PORT.Port, cNIONIP, TELNET_PORT ,1)
    }
}

BUTTON_EVENT[dvTP,2]
{
    Push:
    {
        SEND_STRING dvNION_TN_PORT,"'root',$0D,$0A"
    }
}

BUTTON_EVENT[dvTP,3]
{
    Push:
    {
        SEND_STRING dvNION_TN_PORT,"'shutdown -r now',$0D,$0A"
    }
}

DATA_EVENT[dvNION_TN_PORT]
{
    STRING:
    {
        SEND_STRING 0, "'NION: ',DATA.TEXT"
    }
    ONERROR:
    {
     Send_String 0, "'NION TN PORT ERROR IS ', ITOA(DATA.NUMBER)"  //Send the error number to Diagnostics
     Switch (DATA.NUMBER)//Send error message to diagnostics
     {
        CASE 2:    Send_String 0,'Onerror 2: General failure (out of memory)'
        CASE 4:    Send_String 0,'Onerror 4: Unknown host'
        CASE 6:    Send_String 0,'Onerror 6: Connection refused'
        CASE 7:    Send_String 0,'Onerror 7: Connection timed out'
        CASE 8:    Send_String 0,'Onerror 8: Unknown connection error'
        CASE 14:  Send_String 0,'Onerror 14: Local port already used'
        CASE 16:  Send_String 0,'Onerror 16: Too many open sockets'
        CASE 17:  Send_String 0,'Onerror 17: Local Port Not Open'
      }
   }
}

Comments

  • JasonSJasonS Posts: 229
    You need to negotiate your telnet options, putty does this for you automatically. The Biamp Tesira protocol document actually has a very good section that explains how to do this. The Telnet options are generally 3 bytes in length, and start with $FF. The next byte is a byte representing, usually one of 4 options, "Do", "Don't", "Will", "Won't". I don't remember what the corresponding bytes are off the top of my head. The last byte represents the option being negotiated. You can generally respond with a "Won't" to a "Do", and a "Don't" to a "Will" to finish the negotiation. You way want to send a "Do" for echo depending on your needs.
  • Telnet Protocol

    There's a nice explanation of the telnet protocol in the Microsoft KB article 231866. It doesn't cover all the possible telnet options, but there's a complete list here: http://www.iana.org/assignments/telnet-options/telnet-options.xhtml.

    However, since I have some experience working with the telnet protocol, here's a quick explanation of what the Nion is asking for, and how you should (probably) respond.

    The Nion actually sent you four telnet commands. They are (with the readable ascii written as their hex values):
    $FF,$FD,$18
    $FF,$FD,$20
    $FF,$FD,$23
    $FF,$FD,$27

    Or in decimal (since that's how the telnet protocol is written):
    255,253,24
    255,253,32
    255,253,35
    255,253,39

    What the values equate to:
    255 ($FF): Interpret as command (IAC)
    253 ($FD): DO; Literally, "Do This"
    24 ($18): Terminal Type; "Tell me what type of terminal you are so I can display data appropriately."
    32 ($20): Terminal Speed; "Tell me what speed your equipment will operate at"
    35 ($23): X Display Location; This has something to do with the X windows system... Unix?
    39 ($27): Telnet Environment Option; "Enable passing environment variable information"

    What you should respond with:
    While you could look up the appropriate responses to some of these, replying WILL (251) thereby continuing the conversation and ensuring the Nion is set up to its liking, it generally works out to just say you WONT (252) be doing any of this (hopefully) ending the conversation and getting on with the show.

    So your response in decimal (and hex) would be:
    255,252,24 ($FF,$FC,$18): "IAC WONT TERMINAL-TYPE"
    255,252,32 ($FF,$FC,$20): "IAC WONT TERMINAL-SPEED"
    255,252,35 ($FF,$FC,$23): "IAC WONT X-DISPLAY-LOCATION"
    255,252,39 ($FF,$FC,$27): "IAC WONT TELNET-ENVIRONMENT-OPTION"

    The only thing you might want to do is tell it not to ECHO. Some telnet servers presume you will be using a simple graphical telnet terminal and you would like it to echo each character you send back so you can display it in your window. In that case you would send:
    255,254,1 ($FF,$FE,$01): "IAC DONT ECHO"

    And the Nion will probably respond with:
    255,252,1 ($FF,$FC,$01): "IAC WONT ECHO"

    Good luck!
  • Getting Some Response, but...

    Was out of town so I couldn't try your recommendations till now, but tried your recommended commands and getting the following response:
    $FF$FB$03$FF$FD$01$FF$FD$1F$FF$FB$05$FF$FD!

    This is what I come up with:
    255,251,3 ($FF$FB$03): IAC WILL SUPPRESS GO AHEAD
    255,253,1 ($FF$FD$01): IAC DO ECHO
    255,253,31 ($FF$FD$1F): IAC DO WINDOW SIZE
    255,253,5 ($FF$FB$05): IAC DO STATUS
    255,253, ($FF$FD! ): IAC DO (not sure what the ! is)

    Tried sending the logon command / shutdown command but getting no response.
    Kind of at a loss now as to what it's asking for and what to try next.
  • viningvining Posts: 4,368
    ! = $21 or decimal 33 which should be flow control xon xoff. Masters will always print a printable ascii chararcter if one exists for that value otherwise it prints $hex value.
  • RaphayoRaphayo Posts: 111
    Hi,

    i have check the command we use with Biamp Tesira when doing Telnet communication. This code have not been tested yet, you could try include it into your logic.
        string:
        {
    	STACK_VAR CHAR    cCmd[200]
    	stack_var integer nbusy
    	stack_var char    cHeader[3] // 3 Byte Message
    	
    	cCmd = "cCmd,data.text" //adding incomming data to the variable
    	while(length_string(cCmd)>0) // loop until variable is empty
    	{
    	    if(find_string(cCmd,255,1)&&!nbusy) // find $ff
    	    {
    		nbusy=true // Turn On Semaphore
    		cHeader = remove_string(cCmd,cCmd[3],1) // Pick the first 3 byte
    		switch(cHeader[2])
    		{
    		    case $FB:
    		    {
    		    send_string 0,"$FF,$FE,CHeader[3]"
    		    }
    		    case $FE:
    		    {
    		    send_string 0,"$FF,$FB,CHeader[3]"
    		    }
    		    case $FD:
    		    {
    		    send_string 0,"$FF,$FC,CHeader[3]"
    		    }
    		    case $FC:
    		    {
    		    send_string 0,"$FF,$FD,CHeader[3]"
    		    }
    		}
    		CHeader="" // clear header
    		nbusy=false // turn off semaphore to analyze the incoming variable
    	    }
    	}
        }
    
  • chillchill Posts: 186
    I wrote the attached a few years ago and it works like a champ with Tesiras and Windows PCs (its original purpose). I have never needed to code for a Nion, so I can't speak to that.

    Usage: I #include this somewhere in the function definitions area. Then in the data_event for the device in question:
    data_event[this_device]
    {
      string :
      {
        if(find_string(data.text,"$ff",1))
          telnet_negotiate(data.text,data.device)
    
        ...and then the rest of your string handler.
    
    

    Enjoy.
    .
  • Thank you "chill" for sharing this!
    I was looking for a ready-made negotiation. I already did one on C!"#¤%&/ and it looked very similar to yours. This saved me some time porting it. Nice clean code!!!

Sign In or Register to comment.