func (c *client) request(cmd string, to string, payload string) (Response, error) { var r Response if c.RequestChecks { if !ssmp.IsValidIdentifier(to) { return r, ErrInvalidIdentifier } n := len(payload) if n > 0 { b := payload[0] if b >= 0 && b <= 3 { // binary payload: length prefix must match if n < 3 { return r, ErrInvalidPayload } sz := 3 + (int(b) << 8) + (int(payload[1]) & 0xff) if len(payload) != sz { return r, ErrInvalidPayload } } else if n > 1024 { return r, ErrRequestTooLarge } else if strings.ContainsAny(payload, "\x00\x01\x02\x03\n") { return r, ErrInvalidPayload } } } buf := bufPool.Get().(*bytes.Buffer) buf.Reset() buf.WriteString(cmd) if len(to) > 0 { buf.WriteByte(' ') buf.WriteString(to) } if len(payload) > 0 { buf.WriteByte(' ') buf.WriteString(payload) } buf.WriteByte('\n') _, err := c.c.Write(buf.Bytes()) bufPool.Put(buf) if err != nil { c.c.Close() return r, err } r = <-c.responses if r.Code == 0 { return r, fmt.Errorf("connection closed") } return r, nil }
func (c *client) request(cmd string, to string, payload string) (Response, error) { var r Response if c.RequestChecks { if !ssmp.IsValidIdentifier(to) { return r, ErrInvalidIdentifier } // quick size check, before allocating buffer if len(cmd)+len(to)+len(payload) > 1022 { return r, ErrRequestTooLarge } if strings.Contains(payload, "\n") { return r, ErrInvalidPayload } } buf := bufPool.Get().(*bytes.Buffer) buf.Reset() buf.WriteString(cmd) if len(to) > 0 { buf.WriteByte(' ') buf.WriteString(to) } if len(payload) > 0 { buf.WriteByte(' ') buf.WriteString(payload) } buf.WriteByte('\n') if c.RequestChecks && buf.Len() > 1024 { return r, ErrRequestTooLarge } _, err := c.c.Write(buf.Bytes()) bufPool.Put(buf) if err != nil { c.c.Close() return r, err } r = <-c.responses if r.Code == 0 { return r, fmt.Errorf("connection closed") } return r, nil }