go-sonic/sonic/connection.go
2019-11-16 11:32:04 +02:00

101 lines
1.7 KiB
Go

package sonic
import (
"bufio"
"bytes"
"errors"
"fmt"
"io"
"net"
"strconv"
"strings"
"unicode"
)
type connection struct {
reader *bufio.Reader
conn net.Conn
cmdMaxBytes int
closed bool
}
func newConnection(d *driver) (*connection, error) {
c := &connection{}
c.close()
conn, err := net.Dial("tcp", fmt.Sprintf("%s:%d", d.Host, d.Port))
if err != nil {
return nil, err
}
c.closed = false
c.conn = conn
c.reader = bufio.NewReader(c.conn)
err = c.write(fmt.Sprintf("START %s %s", d.channel, d.Password))
if err != nil {
return nil, err
}
_, err = c.read()
_, err = c.read()
if err != nil {
return nil, err
}
return c, nil
}
func (c *connection) read() (string, error) {
if c.closed {
return "", ErrClosed
}
buffer := bytes.Buffer{}
for {
line, isPrefix, err := c.reader.ReadLine()
buffer.Write(line)
if err != nil {
if err == io.EOF {
c.close()
}
return "", err
}
if !isPrefix {
break
}
}
str := buffer.String()
if strings.HasPrefix(str, "ERR ") {
return "", errors.New(str[4:])
}
if strings.HasPrefix(str, "STARTED ") {
ss := strings.FieldsFunc(str, func(r rune) bool {
if unicode.IsSpace(r) || r == '(' || r == ')' {
return true
}
return false
})
bufferSize, err := strconv.Atoi(ss[len(ss)-1])
if err != nil {
return "", errors.New(fmt.Sprintf("Unable to parse STARTED response: %s", str))
}
c.cmdMaxBytes = bufferSize
}
return str, nil
}
func (c connection) write(str string) error {
if c.closed {
return ErrClosed
}
_, err := c.conn.Write([]byte(str + "\r\n"))
return err
}
func (c *connection) close() {
if c.conn != nil {
_ = c.conn.Close()
c.conn = nil
}
c.closed = true
c.reader = nil
}