func onDisconnectCleanup(c *Channel) {
	c.server.channelsLock.Lock()
	defer c.server.channelsLock.Unlock()
	cn := c.server.channels
	byRoom, ok := c.server.rooms[c]
	if ok {
		for room := range byRoom {
			if curRoom, ok := cn[room]; ok {
				delete(curRoom, c)
				if len(curRoom) == 0 {
					delete(cn, room)
				}
			}
		}
		delete(c.server.rooms, c)
	}
	c.server.sidsLock.Lock()
	defer c.server.sidsLock.Unlock()
	delete(c.server.sids, c.Id())
}
On disconnection system handler, clean joins and sid
package gosocketio
import (
	"bytes"
	"crypto/md5"
	"encoding/base64"
	"encoding/json"
	"errors"
	"fmt"
	"github.com/mcoo/OPQBot/golang-socketio-edit/protocol"
	"github.com/mcoo/OPQBot/golang-socketio-edit/transport"
	"math/rand"
	"net/http"
	"sync"
	"time"
)
const (
	HeaderForward = "X-Forwarded-For"
)
var (
	ErrorServerNotSet       = errors.New("Server not set")
	ErrorConnectionNotFound = errors.New("Connection not found")
)
type Server struct {
	methods
	http.Handler
	channels     map[string]map[*Channel]struct{}
	rooms        map[*Channel]map[string]struct{}
	channelsLock sync.RWMutex
	sids     map[string]*Channel
	sidsLock sync.RWMutex
	tr transport.Transport
}
func (c *Channel) Close() {
	if c.server != nil {
		closeChannel(c, &c.server.methods)
	}
}
func (c *Channel) Ip() string {
	forward := c.RequestHeader().Get(HeaderForward)
	if forward != "" {
		return forward
	}
	return c.ip
}
func (c *Channel) RequestHeader() http.Header {
	return c.requestHeader
}
func (s *Server) GetChannel(sid string) (*Channel, error) {
	s.sidsLock.RLock()
	defer s.sidsLock.RUnlock()
	c, ok := s.sids[sid]
	if !ok {
		return nil, ErrorConnectionNotFound
	}
	return c, nil
}
func (c *Channel) Join(room string) error {
	if c.server == nil {
		return ErrorServerNotSet
	}
	c.server.channelsLock.Lock()
	defer c.server.channelsLock.Unlock()
	cn := c.server.channels
	if _, ok := cn[room]; !ok {
		cn[room] = make(map[*Channel]struct{})
	}
	byRoom := c.server.rooms
	if _, ok := byRoom[c]; !ok {
		byRoom[c] = make(map[string]struct{})
	}
	cn[room][c] = struct{}{}
	byRoom[c][room] = struct{}{}
	return nil
}
func (c *Channel) Leave(room string) error {
	if c.server == nil {
		return ErrorServerNotSet
	}
	c.server.channelsLock.Lock()
	defer c.server.channelsLock.Unlock()
	cn := c.server.channels
	if _, ok := cn[room]; ok {
		delete(cn[room], c)
		if len(cn[room]) == 0 {
			delete(cn, room)
		}
	}
	byRoom := c.server.rooms
	if _, ok := byRoom[c]; ok {
		delete(byRoom[c], room)
	}
	return nil
}
func (c *Channel) Amount(room string) int {
	if c.server == nil {
		return 0
	}
	return c.server.Amount(room)
}
func (s *Server) Amount(room string) int {
	s.channelsLock.RLock()
	defer s.channelsLock.RUnlock()
	roomChannels, _ := s.channels[room]
	return len(roomChannels)
}
func (c *Channel) List(room string) []*Channel {
	if c.server == nil {
		return []*Channel{}
	}
	return c.server.List(room)
}
func (s *Server) List(room string) []*Channel {
	s.channelsLock.RLock()
	defer s.channelsLock.RUnlock()
	roomChannels, ok := s.channels[room]
	if !ok {
		return []*Channel{}
	}
	i := 0
	roomChannelsCopy := make([]*Channel, len(roomChannels))
	for channel := range roomChannels {
		roomChannelsCopy[i] = channel
		i++
	}
	return roomChannelsCopy
}
func (c *Channel) BroadcastTo(room, method string, args interface{}) {
	if c.server == nil {
		return
	}
	c.server.BroadcastTo(room, method, args)
}
func (s *Server) BroadcastTo(room, method string, args interface{}) {
	s.channelsLock.RLock()
	defer s.channelsLock.RUnlock()
	roomChannels, ok := s.channels[room]
	if !ok {
		return
	}
	for cn := range roomChannels {
		if cn.IsAlive() {
			go cn.Emit(method, args)
		}
	}
}
func (s *Server) BroadcastToAll(method string, args interface{}) {
	s.sidsLock.RLock()
	defer s.sidsLock.RUnlock()
	for _, cn := range s.sids {
		if cn.IsAlive() {
			go cn.Emit(method, args)
		}
	}
}
func generateNewId(custom string) string {
	hash := fmt.Sprintf("%s %s %n %n", custom, time.Now(), rand.Uint32(), rand.Uint32())
	buf := bytes.NewBuffer(nil)
	sum := md5.Sum([]byte(hash))
	encoder := base64.NewEncoder(base64.URLEncoding, buf)
	encoder.Write(sum[:])
	encoder.Close()
	return buf.String()[:20]
}
func onConnectStore(c *Channel) {
	c.server.sidsLock.Lock()
	defer c.server.sidsLock.Unlock()
	c.server.sids[c.Id()] = c
}