func (me *Client) SetupNegotiate(millis int, command byte, option byte, yes_event telnet.EventType, no_event telnet.EventType) (bool, telnet.Event) { me.telnet.TelnetSendNegotiate(command, option) tev, timeout, close := me.TryReadEvent(millis) if tev == nil || timeout || close { monolog.Info("Timeout or close in TryReadEvent") return false, nil } evtype := telnet.EventTypeOf(tev) if evtype == no_event { monolog.Info("Negative event no_event %v %v %v", tev, evtype, no_event) return false, tev } if evtype != yes_event { monolog.Info("Unexpected event yes_event %v %v %v", tev, evtype, yes_event) return false, tev } if tev == nil { return false, tev } return true, tev }
// Negotiate MTTS/TTYPE (TERMINAL TYPE) support func (me *Client) SetupTType() telnet.Event { me.info.terminals = nil ok, tev := me.SetupNegotiate(1000, t.TELNET_DO, t.TELNET_TELOPT_TTYPE, t.TELNET_WILL_EVENT, t.TELNET_WONT_EVENT) if !ok { return tev } var last string = "none" var now string = "" for last != now { last = now me.telnet.TelnetTTypeSend() var tev2 telnet.Event = nil // Some clients (like KildClient, but not TinTin or telnet), // insist on spamming useless NUL characters // here... So we have to retry a few times to get a ttype_is // throwing away any undesirable junk in between. GET_TTYPE: for index := 0; index < 3; index++ { tev2, _, _ = me.TryReadEvent(1000) if tev2 != nil { etyp := telnet.EventTypeOf(tev2) monolog.Info("Waiting for TTYPE: %T %v %d", tev2, tev2, etyp) if telnet.IsEventType(tev2, t.TELNET_TTYPE_EVENT) { monolog.Info("TTYPE received: %T %v %d", tev2, tev2, etyp) break GET_TTYPE } } else { // and some clients don't respond, even monolog.Info("Waiting for TTYPE: %T", tev2) } } if tev2 == nil || !telnet.IsEventType(tev2, t.TELNET_TTYPE_EVENT) { etyp := telnet.EventTypeOf(tev2) monolog.Warning("Received no TTYPE: %T %v %d", tev2, tev2, etyp) return tev2 } ttypeevent := tev2.(*telnet.TTypeEvent) now = ttypeevent.Name if !me.HasTerminal(now) { me.info.terminals = append(me.info.terminals, now) } me.info.terminal = now } monolog.Info("Client %d supports terminals %v", me.id, me.info.terminals) monolog.Info("Client %d active terminal %v", me.id, me.info.terminal) // MTTS support for i := range me.info.terminals { term := me.info.terminals[i] monolog.Info("Checking MTTS support: %s", term) if strings.HasPrefix(term, "MTTS ") { // it's an mtts terminal strnum := strings.TrimPrefix(term, "MTTS ") num, err := strconv.Atoi(strnum) if err == nil { me.info.mtts = num monolog.Info("Client %d supports mtts %d", me.id, me.info.mtts) } else { monolog.Warning("Client %d could not parse mtts %s %v", me.id, strnum, err) } } } me.info.ttype = true return nil }