128 lines
		
	
	
		
			2.2 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			128 lines
		
	
	
		
			2.2 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
package websocket
 | 
						|
 | 
						|
import (
 | 
						|
	"net/http"
 | 
						|
 | 
						|
	"github.com/ethereum/go-ethereum/logger"
 | 
						|
 | 
						|
	ws "code.google.com/p/go.net/websocket"
 | 
						|
)
 | 
						|
 | 
						|
var wslogger = logger.NewLogger("WS")
 | 
						|
 | 
						|
// Chat server.
 | 
						|
type Server struct {
 | 
						|
	httpServ  string
 | 
						|
	pattern   string
 | 
						|
	messages  []*Message
 | 
						|
	clients   map[int]*Client
 | 
						|
	addCh     chan *Client
 | 
						|
	delCh     chan *Client
 | 
						|
	sendAllCh chan string
 | 
						|
	doneCh    chan bool
 | 
						|
	errCh     chan error
 | 
						|
	msgFunc   MsgFunc
 | 
						|
}
 | 
						|
 | 
						|
// Create new chat server.
 | 
						|
func NewServer(pattern, httpServ string) *Server {
 | 
						|
	clients := make(map[int]*Client)
 | 
						|
	addCh := make(chan *Client)
 | 
						|
	delCh := make(chan *Client)
 | 
						|
	sendAllCh := make(chan string)
 | 
						|
	doneCh := make(chan bool)
 | 
						|
	errCh := make(chan error)
 | 
						|
 | 
						|
	return &Server{
 | 
						|
		httpServ,
 | 
						|
		pattern,
 | 
						|
		nil,
 | 
						|
		clients,
 | 
						|
		addCh,
 | 
						|
		delCh,
 | 
						|
		sendAllCh,
 | 
						|
		doneCh,
 | 
						|
		errCh,
 | 
						|
		nil,
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
func (s *Server) Add(c *Client) {
 | 
						|
	s.addCh <- c
 | 
						|
}
 | 
						|
 | 
						|
func (s *Server) Del(c *Client) {
 | 
						|
	s.delCh <- c
 | 
						|
}
 | 
						|
 | 
						|
func (s *Server) SendAll(msg string) {
 | 
						|
	s.sendAllCh <- msg
 | 
						|
}
 | 
						|
 | 
						|
func (s *Server) Done() {
 | 
						|
	s.doneCh <- true
 | 
						|
}
 | 
						|
 | 
						|
func (s *Server) Err(err error) {
 | 
						|
	s.errCh <- err
 | 
						|
}
 | 
						|
 | 
						|
func (s *Server) servHTTP() {
 | 
						|
	wslogger.Debugln("Serving http", s.httpServ)
 | 
						|
	err := http.ListenAndServe(s.httpServ, nil)
 | 
						|
 | 
						|
	wslogger.Warnln(err)
 | 
						|
}
 | 
						|
 | 
						|
func (s *Server) MessageFunc(f MsgFunc) {
 | 
						|
	s.msgFunc = f
 | 
						|
}
 | 
						|
 | 
						|
// Listen and serve.
 | 
						|
// It serves client connection and broadcast request.
 | 
						|
func (s *Server) Listen() {
 | 
						|
	wslogger.Debugln("Listening server...")
 | 
						|
 | 
						|
	// ws handler
 | 
						|
	onConnected := func(ws *ws.Conn) {
 | 
						|
		defer func() {
 | 
						|
			err := ws.Close()
 | 
						|
			if err != nil {
 | 
						|
				s.errCh <- err
 | 
						|
			}
 | 
						|
		}()
 | 
						|
 | 
						|
		client := NewClient(ws, s)
 | 
						|
		client.onMessage = s.msgFunc
 | 
						|
		s.Add(client)
 | 
						|
		client.Listen()
 | 
						|
	}
 | 
						|
	// Disable Origin check. Request don't need to come necessarily from origin.
 | 
						|
	http.HandleFunc(s.pattern, func(w http.ResponseWriter, req *http.Request) {
 | 
						|
		s := ws.Server{Handler: ws.Handler(onConnected)}
 | 
						|
		s.ServeHTTP(w, req)
 | 
						|
	})
 | 
						|
	wslogger.Debugln("Created handler")
 | 
						|
 | 
						|
	go s.servHTTP()
 | 
						|
 | 
						|
	for {
 | 
						|
		select {
 | 
						|
 | 
						|
		// Add new a client
 | 
						|
		case c := <-s.addCh:
 | 
						|
			s.clients[c.id] = c
 | 
						|
 | 
						|
		// del a client
 | 
						|
		case c := <-s.delCh:
 | 
						|
			delete(s.clients, c.id)
 | 
						|
 | 
						|
		case err := <-s.errCh:
 | 
						|
			wslogger.Debugln("Error:", err.Error())
 | 
						|
 | 
						|
		case <-s.doneCh:
 | 
						|
			return
 | 
						|
		}
 | 
						|
	}
 | 
						|
}
 |