socket: Use updated socket code

This commit is contained in:
Daniel Oaks 2016-06-15 21:21:45 +10:00
parent 5027391bff
commit 9860094020
2 changed files with 49 additions and 65 deletions

View File

@ -35,6 +35,7 @@ type Client struct {
func NewClient(server *Server, conn net.Conn) *Client { func NewClient(server *Server, conn net.Conn) *Client {
now := time.Now() now := time.Now()
socket := NewSocket(conn)
client := &Client{ client := &Client{
atime: now, atime: now,
authorized: server.password == nil, authorized: server.password == nil,
@ -44,7 +45,7 @@ func NewClient(server *Server, conn net.Conn) *Client {
ctime: now, ctime: now,
flags: make(map[UserMode]bool), flags: make(map[UserMode]bool),
server: server, server: server,
socket: NewSocket(conn), socket: &socket,
} }
client.Touch() client.Touch()
go client.run() go client.run()
@ -265,7 +266,8 @@ func (client *Client) ChangeNickname(nickname Name) {
} }
func (client *Client) Reply(reply string) error { func (client *Client) Reply(reply string) error {
return client.socket.Write(reply) //TODO(dan): We'll be passing around real message objects instead of raw strings
return client.socket.WriteLine(reply)
} }
func (client *Client) Quit(message Text) { func (client *Client) Quit(message Text) {

View File

@ -4,92 +4,74 @@ import (
"bufio" "bufio"
"io" "io"
"net" "net"
"strings"
) )
const ( // Socket represents an IRC socket.
R = '→'
W = '←'
)
type Socket struct { type Socket struct {
closed bool Closed bool
conn net.Conn conn net.Conn
scanner *bufio.Scanner reader *bufio.Reader
writer *bufio.Writer
} }
func NewSocket(conn net.Conn) *Socket { // NewSocket returns a new Socket.
return &Socket{ func NewSocket(conn net.Conn) Socket {
conn: conn, return Socket{
scanner: bufio.NewScanner(conn), conn: conn,
writer: bufio.NewWriter(conn), reader: bufio.NewReader(conn),
} }
} }
func (socket *Socket) String() string { // Close stops a Socket from being able to send/receive any more data.
return socket.conn.RemoteAddr().String()
}
func (socket *Socket) Close() { func (socket *Socket) Close() {
if socket.closed { if socket.Closed {
return return
} }
socket.closed = true socket.Closed = true
socket.conn.Close() socket.conn.Close()
Log.debug.Printf("%s closed", socket)
} }
func (socket *Socket) Read() (line string, err error) { // Read returns a single IRC line from a Socket.
if socket.closed { func (socket *Socket) Read() (string, error) {
err = io.EOF if socket.Closed {
return return "", io.EOF
} }
for socket.scanner.Scan() { lineBytes, err := socket.reader.ReadBytes('\n')
line = socket.scanner.Text()
if len(line) == 0 { // convert bytes to string
continue line := string(lineBytes[:])
}
Log.debug.Printf("%s → %s", socket, line) // read last message properly (such as ERROR/QUIT/etc), just fail next reads/writes
return if err == io.EOF {
socket.Close()
} }
err = socket.scanner.Err() if err == io.EOF && strings.TrimSpace(line) != "" {
socket.isError(err, R) // don't do anything
if err == nil { } else if err != nil {
err = io.EOF return "", err
} }
return
return strings.TrimRight(line, "\r\n"), nil
} }
func (socket *Socket) Write(line string) (err error) { // Write sends the given string out of Socket.
if socket.closed { func (socket *Socket) Write(data string) error {
err = io.EOF if socket.Closed {
return return io.EOF
} }
if _, err = socket.writer.WriteString(line); socket.isError(err, W) { // write data
return _, err := socket.conn.Write([]byte(data))
}
if _, err = socket.writer.WriteString(CRLF); socket.isError(err, W) {
return
}
if err = socket.writer.Flush(); socket.isError(err, W) {
return
}
Log.debug.Printf("%s ← %s", socket, line)
return
}
func (socket *Socket) isError(err error, dir rune) bool {
if err != nil { if err != nil {
if err != io.EOF { socket.Close()
Log.debug.Printf("%s %c error: %s", socket, dir, err) return err
}
return true
} }
return false return nil
}
// WriteLine writes the given line out of Socket.
func (socket *Socket) WriteLine(line string) error {
return socket.Write(line + "\r\n")
} }