synchronize on last writes to client sockets

This commit is contained in:
Jeremy Latt 2014-02-19 18:46:46 -08:00
parent af6a8ee6f0
commit 9c385ededd
1 changed files with 33 additions and 18 deletions

View File

@ -17,6 +17,7 @@ type Client struct {
awayMessage string awayMessage string
channels ChannelSet channels ChannelSet
ctime time.Time ctime time.Time
doneWriting chan bool
flags map[UserMode]bool flags map[UserMode]bool
hasQuit bool hasQuit bool
hops uint hops uint
@ -27,7 +28,7 @@ type Client struct {
phase Phase phase Phase
quitTimer *time.Timer quitTimer *time.Timer
realname string realname string
replies chan Reply replies chan string
server *Server server *Server
socket *Socket socket *Socket
username string username string
@ -36,15 +37,16 @@ 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()
client := &Client{ client := &Client{
atime: now, atime: now,
channels: make(ChannelSet), channels: make(ChannelSet),
ctime: now, ctime: now,
flags: make(map[UserMode]bool), doneWriting: make(chan bool),
hostname: AddrLookupHostname(conn.RemoteAddr()), flags: make(map[UserMode]bool),
phase: server.InitPhase(), hostname: AddrLookupHostname(conn.RemoteAddr()),
server: server, phase: server.InitPhase(),
socket: NewSocket(conn), server: server,
replies: make(chan Reply), socket: NewSocket(conn),
replies: make(chan string),
} }
client.loginTimer = time.AfterFunc(LOGIN_TIMEOUT, client.connectionTimeout) client.loginTimer = time.AfterFunc(LOGIN_TIMEOUT, client.connectionTimeout)
@ -94,9 +96,11 @@ func (client *Client) connectionClosed() {
// //
func (client *Client) writeReplies() { func (client *Client) writeReplies() {
for reply := range client.replies { for line := range client.replies {
client.socket.Write(reply.Format(client)...) client.socket.Write(line)
} }
client.socket.Close()
client.doneWriting <- true
} }
// //
@ -155,12 +159,13 @@ func (client *Client) Register() {
client.Touch() client.Touch()
} }
func (client *Client) Destroy() { func (client *Client) destroy() {
// clean up self // clean up self
client.socket.Close() close(client.replies)
<-client.doneWriting
client.loginTimer.Stop() client.loginTimer.Stop()
if client.idleTimer != nil { if client.idleTimer != nil {
client.idleTimer.Stop() client.idleTimer.Stop()
} }
@ -184,7 +189,15 @@ func (client *Client) Destroy() {
} }
func (client *Client) Reply(reply Reply) { func (client *Client) Reply(reply Reply) {
client.replies <- reply if client.hasQuit {
if DEBUG_CLIENT {
log.Printf("%s dropping %s", client, reply)
}
return
}
for _, line := range reply.Format(client) {
client.replies <- line
}
} }
func (client *Client) IdleTime() time.Duration { func (client *Client) IdleTime() time.Duration {
@ -273,11 +286,13 @@ func (client *Client) Quit(message string) {
if client.hasQuit { if client.hasQuit {
return return
} }
client.hasQuit = true
client.Reply(RplError(client.server, client.Nick())) client.Reply(RplError(client.server, client.Nick()))
client.hasQuit = true
friends := client.Friends() friends := client.Friends()
friends.Remove(client) friends.Remove(client)
client.Destroy() client.destroy()
if len(friends) > 0 { if len(friends) > 0 {
reply := RplQuit(client, message) reply := RplQuit(client, message)