123 lines
		
	
	
		
			2.0 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			123 lines
		
	
	
		
			2.0 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
package websocket
 | 
						|
 | 
						|
import (
 | 
						|
	"fmt"
 | 
						|
	"io"
 | 
						|
 | 
						|
	ws "code.google.com/p/go.net/websocket"
 | 
						|
)
 | 
						|
 | 
						|
const channelBufSize = 100
 | 
						|
 | 
						|
var maxId int = 0
 | 
						|
 | 
						|
type MsgFunc func(c *Client, msg *Message)
 | 
						|
 | 
						|
// Chat client.
 | 
						|
type Client struct {
 | 
						|
	id     int
 | 
						|
	ws     *ws.Conn
 | 
						|
	server *Server
 | 
						|
	ch     chan *Message
 | 
						|
	doneCh chan bool
 | 
						|
 | 
						|
	onMessage MsgFunc
 | 
						|
}
 | 
						|
 | 
						|
// Create new chat client.
 | 
						|
func NewClient(ws *ws.Conn, server *Server) *Client {
 | 
						|
 | 
						|
	if ws == nil {
 | 
						|
		panic("ws cannot be nil")
 | 
						|
	}
 | 
						|
 | 
						|
	if server == nil {
 | 
						|
		panic("server cannot be nil")
 | 
						|
	}
 | 
						|
 | 
						|
	maxId++
 | 
						|
	ch := make(chan *Message, channelBufSize)
 | 
						|
	doneCh := make(chan bool)
 | 
						|
 | 
						|
	return &Client{maxId, ws, server, ch, doneCh, nil}
 | 
						|
}
 | 
						|
 | 
						|
func (c *Client) Id() int {
 | 
						|
	return c.id
 | 
						|
}
 | 
						|
 | 
						|
func (c *Client) Conn() *ws.Conn {
 | 
						|
	return c.ws
 | 
						|
}
 | 
						|
 | 
						|
func (c *Client) Write(data interface{}, seed int) {
 | 
						|
	msg := &Message{Seed: seed, Data: data}
 | 
						|
	select {
 | 
						|
	case c.ch <- msg:
 | 
						|
	default:
 | 
						|
		c.server.Del(c)
 | 
						|
		err := fmt.Errorf("client %d is disconnected.", c.id)
 | 
						|
		c.server.Err(err)
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
func (c *Client) Done() {
 | 
						|
	c.doneCh <- true
 | 
						|
}
 | 
						|
 | 
						|
// Listen Write and Read request via chanel
 | 
						|
func (c *Client) Listen() {
 | 
						|
	go c.listenWrite()
 | 
						|
	c.listenRead()
 | 
						|
}
 | 
						|
 | 
						|
// Listen write request via chanel
 | 
						|
func (c *Client) listenWrite() {
 | 
						|
	wslogger.Debugln("Listening write to client")
 | 
						|
	for {
 | 
						|
		select {
 | 
						|
 | 
						|
		// send message to the client
 | 
						|
		case msg := <-c.ch:
 | 
						|
			wslogger.Debugln("Send:", msg)
 | 
						|
			ws.JSON.Send(c.ws, msg)
 | 
						|
 | 
						|
		// receive done request
 | 
						|
		case <-c.doneCh:
 | 
						|
			c.server.Del(c)
 | 
						|
			c.doneCh <- true // for listenRead method
 | 
						|
			return
 | 
						|
		}
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
// Listen read request via chanel
 | 
						|
func (c *Client) listenRead() {
 | 
						|
	wslogger.Debugln("Listening read from client")
 | 
						|
	for {
 | 
						|
		select {
 | 
						|
 | 
						|
		// receive done request
 | 
						|
		case <-c.doneCh:
 | 
						|
			c.server.Del(c)
 | 
						|
			c.doneCh <- true // for listenWrite method
 | 
						|
			return
 | 
						|
 | 
						|
		// read data from ws connection
 | 
						|
		default:
 | 
						|
			var msg Message
 | 
						|
			err := ws.JSON.Receive(c.ws, &msg)
 | 
						|
			if err == io.EOF {
 | 
						|
				c.doneCh <- true
 | 
						|
			} else if err != nil {
 | 
						|
				c.server.Err(err)
 | 
						|
			} else {
 | 
						|
				wslogger.Debugln(&msg)
 | 
						|
				if c.onMessage != nil {
 | 
						|
					c.onMessage(c, &msg)
 | 
						|
				}
 | 
						|
			}
 | 
						|
		}
 | 
						|
	}
 | 
						|
}
 |