128 lines
		
	
	
		
			2.1 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			128 lines
		
	
	
		
			2.1 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| package websocket
 | |
| 
 | |
| import (
 | |
| 	"net/http"
 | |
| 
 | |
| 	"github.com/ethereum/go-ethereum/ethlog"
 | |
| 
 | |
| 	ws "code.google.com/p/go.net/websocket"
 | |
| )
 | |
| 
 | |
| var logger = ethlog.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() {
 | |
| 	logger.Debugln("Serving http", s.httpServ)
 | |
| 	err := http.ListenAndServe(s.httpServ, nil)
 | |
| 
 | |
| 	logger.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() {
 | |
| 	logger.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)
 | |
| 	})
 | |
| 	logger.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:
 | |
| 			logger.Debugln("Error:", err.Error())
 | |
| 
 | |
| 		case <-s.doneCh:
 | |
| 			return
 | |
| 		}
 | |
| 	}
 | |
| }
 |