socket: Start overhaul of sockets and writing

This commit is contained in:
Daniel Oaks 2017-03-13 23:53:21 +10:00
parent 73d406ccd6
commit de4db1c6ef
2 changed files with 59 additions and 12 deletions

View File

@ -75,6 +75,7 @@ type Client struct {
func NewClient(server *Server, conn net.Conn, isTLS bool) *Client { func NewClient(server *Server, conn net.Conn, isTLS bool) *Client {
now := time.Now() now := time.Now()
socket := NewSocket(conn) socket := NewSocket(conn)
go socket.RunSocketWriter()
client := &Client{ client := &Client{
atime: now, atime: now,
authorized: server.password == nil, authorized: server.password == nil,

View File

@ -10,9 +10,11 @@ import (
"crypto/tls" "crypto/tls"
"encoding/hex" "encoding/hex"
"errors" "errors"
"fmt"
"io" "io"
"net" "net"
"strings" "strings"
"sync"
"time" "time"
) )
@ -27,6 +29,10 @@ type Socket struct {
Closed bool Closed bool
conn net.Conn conn net.Conn
reader *bufio.Reader reader *bufio.Reader
lineToSendExists chan bool
linesToSend []string
linesToSendMutex sync.Mutex
} }
// NewSocket returns a new Socket. // NewSocket returns a new Socket.
@ -34,16 +40,14 @@ func NewSocket(conn net.Conn) Socket {
return Socket{ return Socket{
conn: conn, conn: conn,
reader: bufio.NewReader(conn), reader: bufio.NewReader(conn),
lineToSendExists: make(chan bool),
} }
} }
// Close stops a Socket from being able to send/receive any more data. // Close stops a Socket from being able to send/receive any more data.
func (socket *Socket) Close() { func (socket *Socket) Close() {
if socket.Closed {
return
}
socket.Closed = true socket.Closed = true
socket.conn.Close() // socket will close once all data has been sent
} }
// CertFP returns the fingerprint of the certificate provided by the client. // CertFP returns the fingerprint of the certificate provided by the client.
@ -104,13 +108,55 @@ func (socket *Socket) Write(data string) error {
return io.EOF return io.EOF
} }
socket.linesToSendMutex.Lock()
socket.linesToSend = append(socket.linesToSend, data)
socket.linesToSendMutex.Unlock()
go socket.fillLineToSendExists()
return nil
}
// fillLineToSendExists only exists because you can't goroutine single statements.
func (socket *Socket) fillLineToSendExists() {
socket.lineToSendExists <- true
}
// RunSocketWriter starts writing messages to the outgoing socket.
func (socket *Socket) RunSocketWriter() {
var errOut bool
for {
// wait for new lines
select {
case <-socket.lineToSendExists:
socket.linesToSendMutex.Lock()
// get data
data := socket.linesToSend[0]
if len(socket.linesToSend) > 1 {
socket.linesToSend = socket.linesToSend[1:]
} else {
socket.linesToSend = []string{}
}
// write data // write data
_, err := socket.conn.Write([]byte(data)) _, err := socket.conn.Write([]byte(data))
if err != nil { if err != nil {
socket.Close() errOut = true
return err fmt.Println(err.Error())
break
}
socket.linesToSendMutex.Unlock()
}
if errOut {
// error out, bad stuff happened
break
}
}
//TODO(dan): empty socket.lineToSendExists queue
socket.conn.Close()
if !socket.Closed {
socket.Closed = true
} }
return nil
} }
// WriteLine writes the given line out of Socket. // WriteLine writes the given line out of Socket.