func (s *Session) handleSelect(r *Request) (*Request, error) { if len(r.Resp.Array) != 2 { r.Response.Resp = redis.NewError([]byte("ERR wrong number of arguments for 'SELECT' command")) return r, nil } if db, err := strconv.Atoi(string(r.Resp.Array[1].Value)); err != nil { r.Response.Resp = redis.NewError([]byte("ERR invalid DB index")) return r, nil } else if db != 0 { r.Response.Resp = redis.NewError([]byte("ERR invalid DB index, only accept DB 0")) return r, nil } else { r.Response.Resp = redis.NewString([]byte("OK")) return r, nil } }
func (s *Session) handlePing(r *Request) (*Request, error) { if len(r.Resp.Array) != 1 { r.Response.Resp = redis.NewError([]byte("ERR wrong number of arguments for 'PING' command")) return r, nil } r.Response.Resp = redis.NewString([]byte("PONG")) return r, nil }
func (s *Session) handleAuth(r *Request) (*Request, error) { if len(r.Resp.Array) != 2 { r.Response.Resp = redis.NewError([]byte("ERR wrong number of arguments for 'AUTH' command")) return r, nil } if s.auth == "" { r.Response.Resp = redis.NewError([]byte("ERR Client sent AUTH, but no password is set")) return r, nil } if s.auth != string(r.Resp.Array[1].Value) { s.authorized = false r.Response.Resp = redis.NewError([]byte("ERR invalid password")) return r, nil } else { s.authorized = true r.Response.Resp = redis.NewString([]byte("OK")) return r, nil } }
func (s *Session) handleRequest(resp *redis.Resp, d Dispatcher) (*Request, error) { opstr, err := getOpStr(resp) if err != nil { return nil, err } if isNotAllowed(opstr) { return nil, errors.New(fmt.Sprintf("command <%s> is not allowed", opstr)) } usnow := microseconds() s.LastOpUnix = usnow / 1e6 s.Ops++ r := &Request{ OpStr: opstr, Start: usnow, Resp: resp, Wait: &sync.WaitGroup{}, Failed: &s.failed, } if opstr == "QUIT" { return s.handleQuit(r) } if opstr == "AUTH" { return s.handleAuth(r) } if !s.authorized { if s.auth != "" { r.Response.Resp = redis.NewError([]byte("NOAUTH Authentication required.")) return r, nil } s.authorized = true } switch opstr { case "SELECT": return s.handleSelect(r) case "PING": return s.handlePing(r) case "MGET": return s.handleRequestMGet(r, d) case "MSET": return s.handleRequestMSet(r, d) case "DEL": return s.handleRequestMDel(r, d) } return r, d.Dispatch(r) }
func (s *Session) handleRequestMSet(r *Request, d Dispatcher) (*Request, error) { nblks := len(r.Resp.Array) - 1 if nblks <= 2 { return r, d.Dispatch(r) } if nblks%2 != 0 { r.Response.Resp = redis.NewError([]byte("ERR wrong number of arguments for MSET")) return r, nil } var sub = make([]*Request, nblks/2) for i := 0; i < len(sub); i++ { sub[i] = &Request{ Owner: r.Owner, OpSeq: -r.OpSeq, OpStr: r.OpStr, Start: r.Start, Wait: r.Wait, Resp: redis.NewArray([]*redis.Resp{ r.Resp.Array[0], r.Resp.Array[i*2+1], r.Resp.Array[i*2+2], }), } if err := d.Dispatch(sub[i]); err != nil { return nil, err } } r.Coalesce = func() error { for _, x := range sub { if err := x.Response.Err; err != nil { return err } resp := x.Response.Resp if resp == nil { return ErrRespIsRequired } if !resp.IsString() { return errors.New(fmt.Sprintf("bad mset resp: %s value.len = %d", resp.Type, len(resp.Value))) } r.Response.Resp = resp } return nil } return r, nil }