func (s *Server) dispatchWebsocket(ws *websocket.Conn, wp *bytes.Pool, wb *bytes.Buffer, ch *Channel) {
	var (
		err    error
		finish bool
		online int32
		white  = whitelist.Contains(ch.Mid)
	)
	if conf.Conf.Debug {
		log.Infof("key: %s start dispatch tcp goroutine", ch.Key)
	}
	for {
		if white {
			whitelist.Printf("key: %s wait proto ready\n", ch.Key)
		}
		var p = ch.Ready()
		if white {
			whitelist.Printf("key: %s proto ready\n", ch.Key)
		}
		if conf.Conf.Debug {
			log.Infof("key:%s dispatch msg:%s", ch.Key, p.Body)
		}
		switch p {
		case grpc.ProtoFinish:
			if white {
				whitelist.Printf("key: %s receive proto finish\n", ch.Key)
			}
			if conf.Conf.Debug {
				log.Infof("key: %s wakeup exit dispatch goroutine", ch.Key)
			}
			finish = true
			goto failed
		case grpc.ProtoReady:
			// fetch message from svrbox(client send)
			for {
				if p, err = ch.CliProto.Get(); err != nil {
					break
				}
				if white {
					whitelist.Printf("key: %s start write client proto%v\n", ch.Key, p)
				}
				if p.Op == grpc.OpHeartbeatReply {
					if ch.Room != nil {
						online = ch.Room.OnlineNum()
					}
					if err = p.WriteWebsocketHeart(ws, online); err != nil {
						goto failed
					}
				} else {
					if err = p.WriteWebsocket(ws); err != nil {
						goto failed
					}
				}
				if white {
					whitelist.Printf("key: %s write client proto%v\n", ch.Key, p)
				}
				p.Body = nil // avoid memory leak
				ch.CliProto.GetAdv()
			}
		default:
			if white {
				whitelist.Printf("key: %s start write server proto%v\n", ch.Key, p)
			}
			if err = p.WriteWebsocket(ws); err != nil {
				goto failed
			}
			if white {
				whitelist.Printf("key: %s write server proto%v\n", ch.Key, p)
			}
			if conf.Conf.Debug {
				log.Infof("websocket sent a message key:%s mid:%d proto:%+v", ch.Key, ch.Mid, p)
			}
		}
		if white {
			whitelist.Printf("key: %s start flush \n", ch.Key)
		}
		// only hungry flush response
		if err = ws.Flush(); err != nil {
			break
		}
		if white {
			whitelist.Printf("key: %s flush\n", ch.Key)
		}
	}
failed:
	if white {
		whitelist.Printf("key: %s dispatch tcp error(%v)\n", ch.Key, err)
	}
	if err != nil && err != io.EOF && err != websocket.ErrMessageClose {
		log.Errorf("key: %s dispatch ws error(%v)", ch.Key, err)
	}
	ws.Close()
	wp.Put(wb)
	// must ensure all channel message discard, for reader won't blocking Signal
	for !finish {
		finish = (ch.Ready() == grpc.ProtoFinish)
	}
	if conf.Conf.Debug {
		log.Infof("key: %s dispatch goroutine exit", ch.Key)
	}
}
// dispatch accepts connections on the listener and serves requests
// for each incoming connection.  dispatch blocks; the caller typically
// invokes it in a go statement.
dispatch accepts connections on the listener and serves requests
for each incoming connection.  dispatch blocks; the caller typically
invokes it in a go statement.
// dispatch accepts connections on the listener and serves requests // for each incoming connection . dispatch blocks ; the caller typically // invokes it in a go statement .
func (s *Server) dispatchWebsocket(ws *websocket.Conn, wp *bytes.Pool, wb *bytes.Buffer, ch *Channel) {
	var (
		err    error
		finish bool
		online int32
		white  = whitelist.Contains(ch.Mid)
	)
	if conf.Conf.Debug {
		log.Infof("key: %s start dispatch tcp goroutine", ch.Key)
	}
	for {
		if white {
			whitelist.Printf("key: %s wait proto ready\n", ch.Key)
		}
		var p = ch.Ready()
		if white {
			whitelist.Printf("key: %s proto ready\n", ch.Key)
		}
		if conf.Conf.Debug {
			log.Infof("key:%s dispatch msg:%s", ch.Key, p.Body)
		}
		switch p {
		case grpc.ProtoFinish:
			if white {
				whitelist.Printf("key: %s receive proto finish\n", ch.Key)
			}
			if conf.Conf.Debug {
				log.Infof("key: %s wakeup exit dispatch goroutine", ch.Key)
			}
			finish = true
			goto failed
		case grpc.ProtoReady:
			for {
				if p, err = ch.CliProto.Get(); err != nil {
					break
				}
				if white {
					whitelist.Printf("key: %s start write client proto%v\n", ch.Key, p)
				}
				if p.Op == grpc.OpHeartbeatReply {
					if ch.Room != nil {
						online = ch.Room.OnlineNum()
					}
					if err = p.WriteWebsocketHeart(ws, online); err != nil {
						goto failed
					}
				} else {
					if err = p.WriteWebsocket(ws); err != nil {
						goto failed
					}
				}
				if white {
					whitelist.Printf("key: %s write client proto%v\n", ch.Key, p)
				}
				p.Body = nil 
				ch.CliProto.GetAdv()
			}
		default:
			if white {
				whitelist.Printf("key: %s start write server proto%v\n", ch.Key, p)
			}
			if err = p.WriteWebsocket(ws); err != nil {
				goto failed
			}
			if white {
				whitelist.Printf("key: %s write server proto%v\n", ch.Key, p)
			}
			if conf.Conf.Debug {
				log.Infof("websocket sent a message key:%s mid:%d proto:%+v", ch.Key, ch.Mid, p)
			}
		}
		if white {
			whitelist.Printf("key: %s start flush \n", ch.Key)
		}
		if err = ws.Flush(); err != nil {
			break
		}
		if white {
			whitelist.Printf("key: %s flush\n", ch.Key)
		}
	}
failed:
	if white {
		whitelist.Printf("key: %s dispatch tcp error(%v)\n", ch.Key, err)
	}
	if err != nil && err != io.EOF && err != websocket.ErrMessageClose {
		log.Errorf("key: %s dispatch ws error(%v)", ch.Key, err)
	}
	ws.Close()
	wp.Put(wb)
	for !finish {
		finish = (ch.Ready() == grpc.ProtoFinish)
	}
	if conf.Conf.Debug {
		log.Infof("key: %s dispatch goroutine exit", ch.Key)
	}
}
func ( s * Server ) dispatchWebsocket ( ws * websocket . Conn , wp * bytes . Pool , wb * bytes . Buffer , ch * Channel ) { var ( err error finish bool online int32 white = whitelist . Contains ( ch . Mid ) ) if conf . Conf . Debug { log . Infof ( " " , ch . Key ) } for { if white { whitelist . Printf ( " \n " , ch . Key ) } var p = ch . Ready ( ) if white { whitelist . Printf ( " \n " , ch . Key ) } if conf . Conf . Debug { log . Infof ( " " , ch . Key , p . Body ) } switch p { case grpc . ProtoFinish : if white { whitelist . Printf ( " \n " , ch . Key ) } if conf . Conf . Debug { log . Infof ( " " , ch . Key ) } finish = true goto failed case grpc . ProtoReady : for { if p , err = ch . CliProto . Get ( ) ; err != nil { break } if white { whitelist . Printf ( " \n " , ch . Key , p ) } if p . Op == grpc . OpHeartbeatReply { if ch . Room != nil { online = ch . Room . OnlineNum ( ) } if err = p . WriteWebsocketHeart ( ws , online ) ; err != nil { goto failed } } else { if err = p . WriteWebsocket ( ws ) ; err != nil { goto failed } } if white { whitelist . Printf ( " \n " , ch . Key , p ) } p . Body = nil ch . CliProto . GetAdv ( ) } default : if white { whitelist . Printf ( " \n " , ch . Key , p ) } if err = p . WriteWebsocket ( ws ) ; err != nil { goto failed } if white { whitelist . Printf ( " \n " , ch . Key , p ) } if conf . Conf . Debug { log . Infof ( " " , ch . Key , ch . Mid , p ) } } if white { whitelist . Printf ( " \n " , ch . Key ) } if err = ws . Flush ( ) ; err != nil { break } if white { whitelist . Printf ( " \n " , ch . Key ) } } failed : if white { whitelist . Printf ( " \n " , ch . Key , err ) } if err != nil && err != io . EOF && err != websocket . ErrMessageClose { log . Errorf ( " " , ch . Key , err ) } ws . Close ( ) wp . Put ( wb ) for ! finish { finish = ( ch . Ready ( ) == grpc . ProtoFinish ) } if conf . Conf . Debug { log . Infof ( " " , ch . Key ) } }
dispatch accepts connections on the listener and serves requests
for each incoming connection.
dispatch accepts connections on the listener and serves requests for each incoming connection .
// fetch message from svrbox(client send) // avoid memory leak // only hungry flush response // must ensure all channel message discard, for reader won't blocking Signal