OnPluginTelnetSubnegotiation

Posted by Wobou on Fri 14 Oct 2011 12:34 AM — 11 posts, 29,312 views.

#0
Greetings,

This is my first post on these forums because so far the community here has provided me with the answers to my questions without posting but it looks like I've ran in to an actual error.

Take this block of lua code:


--GMCP
local IAC, SB, SE, DO = 0xFF, 0xFA, 0xF0, 0xFD

local GMCP = 201

function Send_Telnet_Packet (what)
	SendPkt (string.char (IAC, SB, GMCP)..what..string.char (IAC, SE))
end

function OnPluginTelnetSubnegotiation (msg_type, data)
  if msg_type ~= GMCP then
    return
  end -- if not GMCP
  CallPlugin("90523793cd3b6c150f7cb6fb",'parseGMCP',data)
end
needGMCPsetup = true
if IsConnected() and needGMCPsetup then
 Send_Telnet_Packet ('Core.Supports.Set [ "Core 1", "Char 1", "Char.Name 1", "Char.Skills 1", "Char.Items 1", "Comm.Channel 1", "Redirect 1", "Room 1", "IRE.Rift 1", "IRE.Composer 1" ]') 
 needGMCPsetup = false
end
 
function OnPluginTelnetRequest (msg_type, data)

  if msg_type == GMCP and data == "WILL" then
    return true
  end -- if
  
  if msg_type == GMCP and data == "SENT_DO" then
    Send_Telnet_Packet (string.format ('Core.Hello { "client": "MUSHclient", "version": "%s" }', Version ()))
    Send_Telnet_Packet ('Core.Supports.Set [ "Core 1", "Char 1", "Char.Name 1", "Char.Skills 1", "Char.Items 1", "Comm.Channel 1", "Redirect 1", "Room 1", "IRE.Rift 1", "IRE.Composer 1" ]')
    return true
  end -- if ATCP login needed (just sent DO)
  
  return false

end -- function OnPluginTelnetRequest


This is a GMCP implementation for IRE muds. This works just fine, however I'm trying to convert it to the python below:


def Send_Telnet_Packet (what):
 world.SendPkt(u"\xff\xfa\xc9%s\xff\xf0"%(what))

def OnPluginTelnetSubnegotiation (msg_type, data):
 if msg_type == 201: 
  parseGMCP(data)
 return True
 

needGMCPsetup = True
if world.IsConnected and needGMCPsetup:
 Send_Telnet_Packet ('Core.Supports.Set [ "Core 1", "Char 1", "Char.Name 1", "Char.Skills 1", "Char.Items 1", "Comm.Channel 1", "Redirect 1", "Room 1", "IRE.Rift 1", "IRE.Composer 1" ]') 
 needGMCPsetup = False
 
def OnPluginTelnetRequest (msg_type, data):
 if msg_type == 201 and data == "WILL":  return 1 
 if msg_type == 201 and data == "SENT_DO":
  Send_Telnet_Packet ('Core.Hello { "client": "MUSHclient", "version": "%s" }'%world.Version)
  Send_Telnet_Packet ('Core.Supports.Set [ "Core 1", "Char 1", "Char.Name 1", "Char.Skills 1", "Char.Items 1", "Comm.Channel 1", "Redirect 1", "Room 1", "IRE.Rift 1", "IRE.Composer 1" ]')
  return 1
 return 0



This causes freezing almost immediately. In particular the culprit (I've found through selective commenting) is OnPluginTelnetSubnegotiation, when I comment it out the freezing stops (although obviously so does the data). Even if I replace all the logic with return 1 it freezes. If I do return 0 it immediately disconnects on connection (which I would expect).

Sorry for my ugly code. Let me know if there's any further details you need from me.
USA Global Moderator #1
Quote:
This works just fine, however I'm trying to convert it to the python

Mind if I ask why?
#2
You may indeed! I have a combat system that's written in python that I've had to ship as two modules, one python and one lua. Now the only functionality left in lua is gmcp and I'd like to get rid of the other module.
Australia Forum Administrator #3
Wobou said:

Even if I replace all the logic with return 1 it freezes. If I do return 0 it immediately disconnects on connection (which I would expect).



Why would you expect that?

Try returning 0 or 1 rather than false or true.
#4
Nick Gammon said:

Why would you expect that?

Try returning 0 or 1 rather than false or true.


I thought that perhaps it was denying a negotiation normally handled by the client itself, but looking at the documentation now it doesn't make sense.

Note that I tried these in addition to what I posted before:


def OnPluginTelnetSubnegotiation (msg_type, data):
 return 1



def OnPluginTelnetSubnegotiation (msg_type, data):
 return 0


First still causes random program lockups, second causes immediate disconnect. If I comment out the function as a whole there is no freezing.
Australia Forum Administrator #5
I can't help thinking this is a Python problem. Lua works fine, and the Lua callback handling, whilst not using Windows Script Engine, is otherwise similar.
#6
That wouldn't explain why I can use many other callbacks in python but this one particular one would cause freezing just by being defined with return 1. That's what leads me to believe that something in the callback itself isn't meshing with nonlua scripting. I'll see if I can replicate this in other languages or if it's just in python.

Thanks for the quick responses by the way!
Australia Forum Administrator #7
I've taken a closer look at the functions which are executed in this case. I notice this comment:


    // this crazy code is to get 0x00 bytes into telnet subnegotiations ;)


So, on the supposition that the "crazy code" is not perfect, I amended that slightly.

In particular I changed it so that where it was possibly using a compiler temporary object, it used a more permanent one. This may fix the problem.

I've emailed you a link to a beta test version. Please report back whether that fixes it. Thanks.
Australia Forum Administrator #8
By the way, the "crazy code" is only executed for non-Lua scripting. Effectively it is trying to get a string into the Windows Script Host which contains imbedded zeroes.
#9
The beta version works! I was able to load the code without crashing and receive the gmcp data properly.
Australia Forum Administrator #10
Glad to hear that. This will be in the next official release.