3
0
mirror of https://github.com/ergochat/ergo.git synced 2024-11-22 20:09:41 +01:00

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 {
now := time.Now()
socket := NewSocket(conn)
go socket.RunSocketWriter()
client := &Client{
atime: now,
authorized: server.password == nil,

View File

@ -10,9 +10,11 @@ import (
"crypto/tls"
"encoding/hex"
"errors"
"fmt"
"io"
"net"
"strings"
"sync"
"time"
)
@ -27,6 +29,10 @@ type Socket struct {
Closed bool
conn net.Conn
reader *bufio.Reader
lineToSendExists chan bool
linesToSend []string
linesToSendMutex sync.Mutex
}
// NewSocket returns a new Socket.
@ -34,16 +40,14 @@ func NewSocket(conn net.Conn) Socket {
return Socket{
conn: conn,
reader: bufio.NewReader(conn),
lineToSendExists: make(chan bool),
}
}
// Close stops a Socket from being able to send/receive any more data.
func (socket *Socket) Close() {
if socket.Closed {
return
}
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.
@ -104,13 +108,55 @@ func (socket *Socket) Write(data string) error {
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
_, err := socket.conn.Write([]byte(data))
if err != nil {
socket.Close()
return err
errOut = true
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.