func (me Record) GetValue(key string, value reflect.Value) (err error) { /*stringer, ok := value.Interface().(fmt.Stringer) if ok { me.Gut(key, stringer.String()) return }*/ monolog.Debug("GetValue: %s %v", key, value) switch value.Kind() { case reflect.Int, reflect.Int32, reflect.Int64: value.SetInt(int64(me.GetIntDefault(key, 0))) case reflect.Uint, reflect.Uint32, reflect.Uint64: value.SetUint(uint64(me.GetIntDefault(key, 0))) case reflect.Float32, reflect.Float64: f, err := me.GetFloat(key) if err != nil { return err } value.SetFloat(f) case reflect.String: s, ok := me.MayGet(key) if !ok { return fmt.Errorf("Could not get string for key %s", key) } value.SetString(s) case reflect.Struct: me.GetStruct(key+".", value.Addr().Interface()) default: monolog.Warning("Don't know what to do with %v", value) } return nil }
func (me *Client) DeleteCharacterDialog() bool { extra := []AskOption{TrivialAskOption("Cancel"), TrivialAskOption("Disconnect")} els := me.AccountCharacterList() els = append(els, extra...) result := me.AskOptionList("Character to delete?", "Character?>", false, false, els) if alt, ok := result.(TrivialAskOption); ok { if string(alt) == "Disconnect" { me.Printf("Disconnecting") return false } else if string(alt) == "Cancel" { me.Printf("Canceled") return true } else { monolog.Warning("Internal error, unhandled case.") return true } } character := result.(*world.Character) /* A character that is deleted gives NEW_CHARACTER_PRICE + * level / (NEW_CHARACTER_PRICE * 2) points, but only after the delete. */ np := NEW_CHARACTER_PRICE + character.Level/(NEW_CHARACTER_PRICE*2) me.account.DeleteCharacter(me.server.DataPath(), character) me.account.Points += np return true }
// parse TERMINAL-TYPE command subnegotiation buffers func (me *Telnet) SubnegotiateTType(buffer []byte) { // make sure request is not empty if len(buffer) == 0 { monolog.Warning("Incomplete TERMINAL-TYPE request") return } fb := buffer[0] if fb != TELNET_TTYPE_IS && fb != TELNET_TTYPE_SEND { monolog.Warning("TERMINAL-TYPE request has invalid type %d (%v)", fb, buffer) return } term := string(buffer[1:]) me.SendEvent(&TTypeEvent{fb, term}) }
// Parse a subnegotiation buffer for a naws event func (me *Telnet) SubnegotiateNAWS(buffer []byte) { // Some clients, like Gnome-Mud can't even get this right. Grrr! if buffer == nil || len(buffer) != 4 { monolog.Warning("Bad NAWS negotiation: #{buffer}") return } var w int = (int(buffer[0]) << 8) + int(buffer[1]) var h int = (int(buffer[2]) << 8) + int(buffer[3]) me.SendEvent(&NAWSEvent{w, h}) }
// Deletes the character itself from disk func (me *Character) Delete(dirname string) bool { path := SavePathFor(dirname, "character", me.ID) if err := os.Remove(path); err != nil { monolog.Warning("Could not delete character: %v %s: %s", me, path, err.Error()) return false } me.Account = nil monolog.Info("Character deleted: %s", me.ID) return true }
// Delete a character from this account. func (me *Account) DeleteCharacter(dirname string, character *Character) bool { if i := me.FindCharacter(character); i < 0 { monolog.Warning("Could not find character: %v %d", character, i) return false } else { copy(me.characters[i:], me.characters[i+1:]) newlen := len(me.characters) - 1 me.characters[newlen] = nil me.characters = me.characters[:newlen] } /// Save self so the deletion is correctly recorded. me.Save(dirname) return character.Delete(dirname) }
func (me *Telnet) DoNegotiate(state TelnetState, telopt byte) bool { switch me.state { case will_state: me.SendEvent(&WillEvent{telopt}) case wont_state: me.SendEvent(&WontEvent{telopt}) case do_state: me.SendEvent(&DoEvent{telopt}) case dont_state: me.SendEvent(&DontEvent{telopt}) default: monolog.Warning("State not vvalid in telnet negotiation.") } me.state = data_state return false }
// process an MSSP subnegotiation buffer func (me *Telnet) SubnegotiateMSSP(buffer []byte) { if len(buffer) < 1 { return } fb := buffer[0] // first byte must be a valid command if fb != TELNET_MSSP_VAR { monolog.Warning("telopt MSSP subneg data not valid") return } variables := make(map[string]string) var variable []byte var value []byte mstate := MSTATE_NONE for index := 0; index < len(buffer); index++ { c := buffer[index] switch c { case TELNET_MSSP_VAR: mstate = MSTATE_VAR if mstate == MSTATE_VAR { variables[string(variable)] = string(value) variable = nil value = nil } case TELNET_MSSP_VAL: mstate = MSTATE_VAL default: if mstate == MSTATE_VAL { variable = append(variable, c) } else { value = append(value, c) } } } me.SendEvent(&MSSPEvent{fb, variables}) }
// Process a byte in the IAC received when processing subnegotiation data state func (me *Telnet) sbdataiacStateProcessByte(bin byte) bool { switch bin { //end subnegotiation case TELNET_SE: me.state = data_state // process subnegotiation compress := me.DoSubnegotiate(me.buffer) // if compression was negotiated, the rest of the stream is compressed // and processing it requires decompressing it. Return true to signal // this. me.buffer = nil if compress { return true } // escaped IAC byte case TELNET_IAC: // push IAC into buffer me.appendByte(bin) me.state = sb_data_state // something else -- protocol error. attempt to process // content in subnegotiation buffer, then evaluate the // given command as an IAC code. default: monolog.Warning("Unexpected byte after IAC inside SB: %d", bin) me.state = iac_state // subnegotiate with the buffer anyway, even though it's an error compress := me.DoSubnegotiate(me.buffer) // if compression was negotiated, the rest of the stream is compressed // and processing it requires decompressing it. Return true to signal // this. me.buffer = nil if compress { return true } } return false }
func (me *Client) AccountDialog() bool { login := me.AskLogin() if login == nil { return false } var err error if me.server.World.GetAccount(string(login)) != nil { me.Printf("Account already logged in!\n") me.Printf("Disconnecting!\n") return false } me.account, err = me.server.World.LoadAccount(string(login)) if err != nil { monolog.Warning("Could not load account %s: %v", login, err) } if me.account != nil { return me.ExistingAccountDialog() } else { return me.NewAccountDialog(string(login)) } }
// 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 }
// process an ENVIRON/NEW-ENVIRON subnegotiation buffer func (me *Telnet) SubnegotiateEnviron(buffer []byte) { var vars []Environment var cmd []byte fb := buffer[0] // First byte must be a valid command if fb != TELNET_ENVIRON_SEND && fb != TELNET_ENVIRON_IS && fb != TELNET_ENVIRON_INFO { monolog.Warning("telopt environment subneg command not valid") } cmd = append(cmd, fb) if len(buffer) == 1 { me.SendEvent(&EnvironmentEvent{fb, vars}) return } // Second byte must be VAR or USERVAR, if present sb := buffer[1] if sb != TELNET_ENVIRON_VAR && fb != TELNET_ENVIRON_USERVAR { monolog.Warning("telopt environment subneg missing variable type") return } // ensure last byte is not an escape byte (makes parsing later easier) lb := buffer[len(buffer)-1] if lb == TELNET_ENVIRON_ESC { monolog.Warning("telopt environment subneg ends with ESC") return } /* XXX : not implemented yet var variable * Environment = nil index := 1 escape := false for index := 1 ; index < len(buffer) ; index++ { c := buffer[index] switch c { case TELNET_ENVIRON_VAR: fallthrough case TELNET_ENVIRON_VALUE: fallthrough case TELNET_ENVIRON_USERVAR: if escape { escape = false variable.Value = append(variable.Value, c) } else if (variable != nil) { vars = append(vars, variable) variable = new(Environment) variable.Type = c } else { variable = new(Environment) variable.Type = c } case TELNET_ENVIRON_ESC: escape = true default: variable.Value = append(variable.Value, c) } } // Finally send event me.SendEvent(&EnvironmentEvent{fb, vars}) */ }