func UpgradeRequest(state *State, role protocol.Role, w http.ResponseWriter, r *http.Request) (ws.IWebsocket, error) {
	isValid, err := state.auth.AuthenticateFromURL(role, r)
	if err != nil {
		return nil, err
	}
	if !isValid {
		return nil, ErrUnauthorized
	}
	return state.upgrader.Upgrade(w, r)
}
UpgradeRequest upgrades a HTTP request to ws protocol and authenticates for the role
package coordinator
import (
	"errors"
	"net/http"
	"sort"
	"time"
	"github.com/decentraland/webrtc-broker/internal/logging"
	"github.com/decentraland/webrtc-broker/internal/ws"
	"github.com/decentraland/webrtc-broker/pkg/authentication"
	protocol "github.com/decentraland/webrtc-broker/pkg/protocol"
)
const (
	defaultReportPeriod = 30 * time.Second
	pongWait            = 60 * time.Second
	pingPeriod          = 30 * time.Second
	maxMessageSize      = 5000  
)
type Stats struct {
	ServerCount int
	ClientCount int
}
var ErrUnauthorized = errors.New("unauthorized")
type IServerSelector interface {
	ServerRegistered(role protocol.Role, alias uint64)
	ServerUnregistered(alias uint64)
	GetServerAliasList(forRole protocol.Role) []uint64
	GetServerCount() int
}
type DefaultServerSelector struct {
	ServerAliases map[uint64]bool
}
func (r *DefaultServerSelector) ServerRegistered(role protocol.Role, alias uint64) {
	r.ServerAliases[alias] = true
}
func (r *DefaultServerSelector) ServerUnregistered(alias uint64) {
	delete(r.ServerAliases, alias)
}
type ByAlias []uint64
func (a ByAlias) Len() int           { return len(a) }
func (a ByAlias) Swap(i, j int)      { a[i], a[j] = a[j], a[i] }
func (a ByAlias) Less(i, j int) bool { return a[i] < a[j] }
func (r *DefaultServerSelector) GetServerAliasList(role protocol.Role) []uint64 {
	peers := make([]uint64, 0, len(r.ServerAliases))
	for alias := range r.ServerAliases {
		peers = append(peers, alias)
	}
	sort.Sort(ByAlias(peers))
	return peers
}
func (r *DefaultServerSelector) GetServerCount() int {
	return len(r.ServerAliases)
}
type inMessage struct {
	msgType protocol.MessageType
	from    *Peer
	bytes   []byte
	toAlias uint64
}
type Peer struct {
	Alias    uint64
	conn     ws.IWebsocket
	sendCh   chan []byte
	isClosed bool
	role     protocol.Role
	log      logging.Logger
}
type State struct {
	serverSelector IServerSelector
	upgrader       ws.IUpgrader
	auth           authentication.CoordinatorAuthenticator
	marshaller     protocol.IMarshaller
	log            logging.Logger
	reporter       func(stats Stats)
	reportPeriod   time.Duration
	LastPeerAlias uint64
	Peers              map[uint64]*Peer
	registerCommServer chan *Peer
	registerClient     chan *Peer
	unregister         chan *Peer
	signalingQueue     chan *inMessage
	stop               chan bool
	softStop           bool
}
type Config struct {
	Log            *logging.Logger
	ServerSelector IServerSelector
	Auth           authentication.CoordinatorAuthenticator
	Reporter       func(stats Stats)
	ReportPeriod   time.Duration
}
func MakeState(config *Config) *State {
	serverSelector := config.ServerSelector
	if serverSelector == nil {
		serverSelector = &DefaultServerSelector{
			ServerAliases: make(map[uint64]bool),
		}
	}
	reportPeriod := config.ReportPeriod
	if reportPeriod.Seconds() == 0 {
		reportPeriod = defaultReportPeriod
	}
	var log logging.Logger
	if config.Log == nil {
		log = logging.New()
	} else {
		log = *config.Log
	}
	return &State{
		serverSelector:     serverSelector,
		reporter:           config.Reporter,
		reportPeriod:       reportPeriod,
		upgrader:           ws.MakeUpgrader(),
		auth:               config.Auth,
		marshaller:         &protocol.Marshaller{},
		log:                log,
		Peers:              make(map[uint64]*Peer),
		registerCommServer: make(chan *Peer, 255),
		registerClient:     make(chan *Peer, 255),
		unregister:         make(chan *Peer, 255),
		signalingQueue:     make(chan *inMessage, 255),
		stop:               make(chan bool),
	}
}
func makePeer(state *State, conn ws.IWebsocket, role protocol.Role) *Peer {
	return &Peer{
		conn:   conn,
		sendCh: make(chan []byte, 256),
		role:   role,
		log:    state.log,
	}
}
func (p *Peer) send(state *State, msg protocol.Message) error {
	log := state.log
	bytes, err := state.marshaller.Marshal(msg)
	if err != nil {
		log.Error().Err(err).Msg("encode message failure")
		return err
	}
	p.sendCh <- bytes
	return nil
}
func (p *Peer) writePump(state *State) {
	ticker := time.NewTicker(pingPeriod)
	defer func() {
		ticker.Stop()
	}()
	log := state.log
	for {
		select {
		case bytes, ok := <-p.sendCh:
			if !ok {
				if err := p.conn.WriteCloseMessage(); err != nil {
					log.Debug().Err(err).Msg("error writing close message")
				}
				return
			}
			if err := p.conn.WriteMessage(bytes); err != nil {
				log.Error().Err(err).Msg("error writing message")
				return
			}
			n := len(p.sendCh)
			for i := 0; i < n; i++ {
				bytes, ok = <-p.sendCh
				if !ok {
					if err := p.conn.WriteCloseMessage(); err != nil {
						log.Debug().Err(err).Msg("error writing close message")
					}
					return
				}
				if err := p.conn.WriteMessage(bytes); err != nil {
					log.Error().Err(err).Msg("error writing message")
					return
				}
			}
		case <-ticker.C:
			if err := p.conn.WritePingMessage(); err != nil {
				log.Error().Err(err).Msg("error writing ping message")
				return
			}
		}
	}
}
func (p *Peer) close() {
	if !p.isClosed {
		if err := p.conn.Close(); err != nil {
			p.log.Debug().Err(err).Msg("error closing peer")
		}
		close(p.sendCh)
		p.isClosed = true
	}
}
func readPump(state *State, p *Peer) {
	defer func() {
		p.close()
		state.unregister <- p
	}()
	log := state.log
	marshaller := state.marshaller
	p.conn.SetReadLimit(maxMessageSize)
	if err := p.conn.SetReadDeadline(time.Now().Add(pongWait)); err != nil {
		log.Error().Err(err).Msg("error setting read deadline")
		return
	}
	p.conn.SetPongHandler(func(s string) error {
		err := p.conn.SetReadDeadline(time.Now().Add(pongWait))
		return err
	})
	header := &protocol.CoordinatorMessage{}
	webRtcMessage := &protocol.WebRtcMessage{}
	connectMessage := &protocol.ConnectMessage{}
	connectionRefusedMessage := &protocol.ConnectionRefusedMessage{}
	for {
		bytes, err := p.conn.ReadMessage()
		if err != nil {
			if ws.IsUnexpectedCloseError(err) {
				log.Error().Err(err).Msg("unexcepted close error")
			} else {
				log.Error().Err(err).Msg("read error")
			}
			break
		}
		if err = marshaller.Unmarshal(bytes, header); err != nil {
			log.Debug().Err(err).Msg("decode header failure")
			continue
		}
		msgType := header.GetType()
		switch msgType {
		case protocol.MessageType_WEBRTC_OFFER, protocol.MessageType_WEBRTC_ANSWER, protocol.MessageType_WEBRTC_ICE_CANDIDATE:
			bytes, err = repackageWebRtcMessage(state, p, bytes, webRtcMessage)
			if err != nil {
				continue
			}
			state.signalingQueue <- &inMessage{
				msgType: msgType,
				from:    p,
				bytes:   bytes,
				toAlias: webRtcMessage.ToAlias,
			}
		case protocol.MessageType_CONNECT:
			if err := marshaller.Unmarshal(bytes, connectMessage); err != nil {
				log.Debug().Err(err).Msg("decode connect message failure")
				continue
			}
			connectMessage.FromAlias = p.Alias
			bytes, err := marshaller.Marshal(connectMessage)
			if err != nil {
				log.Error().Err(err).Msg("cannot recode connect message")
				continue
			}
			state.signalingQueue <- &inMessage{
				msgType: msgType,
				from:    p,
				bytes:   bytes,
				toAlias: connectMessage.ToAlias,
			}
		case protocol.MessageType_CONNECTION_REFUSED:
			if err := marshaller.Unmarshal(bytes, connectionRefusedMessage); err != nil {
				log.Debug().Err(err).Msg("decode connection refused connection message failure")
				continue
			}
			connectionRefusedMessage.FromAlias = p.Alias
			bytes, err := marshaller.Marshal(connectionRefusedMessage)
			if err != nil {
				log.Error().Err(err).Msg("cannot reencode refused connection message")
				continue
			}
			state.signalingQueue <- &inMessage{
				msgType: msgType,
				from:    p,
				bytes:   bytes,
				toAlias: connectionRefusedMessage.ToAlias,
			}
		default:
			log.Debug().Str("type", msgType.String()).Msg("unhandled message")
		}
	}
}