|
|
|
@ -2,6 +2,7 @@ package core
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
"bufio"
|
|
|
|
|
"bytes"
|
|
|
|
|
"io"
|
|
|
|
|
"net"
|
|
|
|
|
"time"
|
|
|
|
@ -36,7 +37,6 @@ func (c *deadlineConn) Close() error {
|
|
|
|
|
// Conn wraps a DeadlineConn with a buffer
|
|
|
|
|
type conn struct {
|
|
|
|
|
b []byte
|
|
|
|
|
br *bufio.Reader
|
|
|
|
|
bw *bufio.Writer
|
|
|
|
|
c net.Conn
|
|
|
|
|
}
|
|
|
|
@ -49,8 +49,7 @@ func wrapConn(c net.Conn) *conn {
|
|
|
|
|
wd: &connWriteDeadline,
|
|
|
|
|
}
|
|
|
|
|
return &conn{
|
|
|
|
|
b: connRequestBufferPool.Get()[:0], // reset the buffer
|
|
|
|
|
br: connBufferedReaderPool.Get(deadlineConn),
|
|
|
|
|
b: connRequestBufferPool.Get()[:0], // ensure buffer reset
|
|
|
|
|
bw: connBufferedWriterPool.Get(deadlineConn),
|
|
|
|
|
c: c,
|
|
|
|
|
}
|
|
|
|
@ -63,28 +62,35 @@ func (c *conn) Conn() net.Conn {
|
|
|
|
|
|
|
|
|
|
// ReadLine reads a single line and returns the result, or nil and error
|
|
|
|
|
func (c *conn) ReadLine() ([]byte, errors.Error) {
|
|
|
|
|
for {
|
|
|
|
|
// Attempt to read next line
|
|
|
|
|
b, isPrefix, err := c.br.ReadLine()
|
|
|
|
|
totalCount, end := 0, -1
|
|
|
|
|
for totalCount < len(c.b) {
|
|
|
|
|
// Perform a single read into the buffer
|
|
|
|
|
count, err := c.c.Read(c.b[totalCount:])
|
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, ErrConnRead.Wrap(err)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// If we hit the max request size (i.e. capacity
|
|
|
|
|
// of the request buffer), return error
|
|
|
|
|
if len(c.b)+len(b) > cap(c.b) {
|
|
|
|
|
return nil, ErrInvalidRequest
|
|
|
|
|
// Only accept up to new-line char
|
|
|
|
|
end = bytes.IndexByte(c.b[totalCount:totalCount+count], '\n')
|
|
|
|
|
if end > 0 {
|
|
|
|
|
// Remove any extra '\r'
|
|
|
|
|
if c.b[end-1] == '\r' {
|
|
|
|
|
end--
|
|
|
|
|
}
|
|
|
|
|
totalCount += end
|
|
|
|
|
break
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Add current bytes to request buffer
|
|
|
|
|
c.b = append(c.b, b...)
|
|
|
|
|
// Iter total count
|
|
|
|
|
totalCount += count
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// If we hit the end, break out
|
|
|
|
|
if !isPrefix {
|
|
|
|
|
break
|
|
|
|
|
}
|
|
|
|
|
// If end never reached, return error.
|
|
|
|
|
// Else, return slice up to end
|
|
|
|
|
if end < 0 {
|
|
|
|
|
return nil, ErrInvalidRequest
|
|
|
|
|
}
|
|
|
|
|
return c.b, nil
|
|
|
|
|
return c.b[:totalCount], nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// WriteBytes writes a byte slice to the buffer and returns error status
|
|
|
|
|