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) 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 TestBackend(t *testing.T) { l, err := net.Listen("tcp", "127.0.0.1:0") assert.MustNoError(err) defer l.Close() addr := l.Addr().String() reqc := make(chan *Request, 16384) go func() { bc := NewBackendConn(addr) defer bc.Close() defer close(reqc) var resp = redis.NewBulkBytes(make([]byte, 4096)) for i := 0; i < cap(reqc); i++ { r := &Request{ Resp: resp, Wait: &sync.WaitGroup{}, } r.Wait.Add(1) bc.PushBack(r) reqc <- r } }() go func() { c, err := l.Accept() assert.MustNoError(err) defer c.Close() conn := redis.NewConn(c) time.Sleep(time.Millisecond * 300) for i := 0; i < cap(reqc); i++ { _, err := conn.Reader.Decode() assert.MustNoError(err) resp := redis.NewString([]byte(strconv.Itoa(i))) assert.MustNoError(conn.Writer.Encode(resp, true)) } }() var n int for r := range reqc { r.Wait.Wait() assert.Must(string(r.Response.Resp.Value) == strconv.Itoa(n)) n++ } assert.Must(n == cap(reqc)) }
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.Set(usnow / 1e6) r := &Request{ Owner: s, OpSeq: s.Ops.Incr(), OpStr: opstr, Start: usnow, Wait: &sync.WaitGroup{}, Resp: resp, } switch opstr { case "QUIT": s.quit = true fallthrough case "AUTH", "SELECT": r.Response.Resp = redis.NewString([]byte("OK")) return r, nil 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) handleQuit(r *Request) (*Request, error) { s.quit = true r.Response.Resp = redis.NewString([]byte("OK")) return r, nil }
func (s *Session) handlePing(r *Request) (*Request, error) { r.Response.Resp = redis.NewString([]byte("PONG")) return r, nil }