func (h *Service) GetSkillTemplates(req common.CommonRequest, reply *common.CommonReply) (err error) { log.Debugf("GetSkillTemplates:req(%+v)\n", req) var args common.CommonRequest args.PlayerId = req.PlayerId args.Content = nil err = h.connector.CallByMethod("Skill.GetSkillTemplates", args, reply) reply.Type = req.Type // test Notify defer func(args common.CommonRequest, reply *common.CommonReply) { var notify struct { Type string Message string } notify.Type = "NotifyTest" notify.Message = "Just Test If The Notification Works Well" args.Content = notify ne := h.connector.CallByMethod("NotifyService.NotifyPush", args, nil) if ne != nil { log.Debugf("testNotify: %v\n", ne.Error()) } }(args, reply) return }
func (n *NotifyService) NotifyPush(args common.CommonRequest, reply *common.CommonReply) error { log.Debugf("NotifyPush\t:args(%+v)\n", args) client := net.Clients[args.PlayerId] if client == nil { log.Debugf("NotifyPush:net.Clients(%+v)\n", net.Clients) return errors.New("client connection not existed") } client.SendNotify(args.Content) return nil }
func (bs *BaseService) startBusServer() (err error) { if bs.running { return errors.New("Can not start a service twice") } if !bs.config.Valid { return errors.New("Config is not valid") } err = bs.checkIfRequestsAllAvailabe() if err != nil { return } var selfServer bus.ServerConfig selfServer.Type = bs.config.Server.Type selfServer.ServerId = bs.config.Server.Id selfServer.Host = bs.config.Server.Host selfServer.Port = bs.config.Server.Port selfServer.Name = bs.config.Server.Name selfServer.Network = bs.config.Server.Network bs.busServer, err = bus.StartBusServer(&selfServer) if err != nil { panic(err.Error()) } log.Debugf("startBusServer:busServer(%+v)\n", *bs.busServer) return }
func socketTlsListener(quit chan int, gameLogic func(*Client), portn int, readDeadline, writeDeadline time.Duration, config *tls.Config) { port := fmt.Sprintf(":%d", portn) ln, err := tls.Listen("tcp", port, config) if err != nil { log.Debugf("listen on port %d failed %s \n", port, err.Error()) quit <- 1 return } log.Debug("starting socket") for { conn, err := ln.Accept() if err != nil { log.Debug("accept connection failed") continue } client := new(Client) client.Conn = conn client.ReadDeadline = readDeadline client.WriteDeadline = writeDeadline client.Request = make(chan ClientRequest) client.Response = make([]chan ClientResponse, NetChannelCount) client.Connected = true //client.DisconnectEvents = make([]chan bool, 0) client.DisconnectHandlers = make([]*ClientDisconnectHandler, 0) for i := 0; i < NetChannelCount; i++ { client.Response[i] = make(chan ClientResponse) } go handleConnection(client) go gameLogic(client) } }
func handleConnection(client *Client) { defer func() { if x := recover(); x != nil { log.Debugf("connection from %s to %s lost\n", client.Conn.RemoteAddr().String(), client.Conn.LocalAddr().String()) log.Debug(x) client.Disconnect() go func() { for { timeout := false select { case request := <-client.Request: log.Debugf("remove tail request for account %d with request %s", client.Id, request.Content) case <-time.After(time.Second * 60): timeout = true } if timeout { break } } }() var exception struct { Type string } exception.Type = "Exception" var response ClientResponse bodybytes, _ := json.Marshal(exception) response.Content = string(bodybytes) client.Response[NetChannelPrimary] <- response } log.Debugf("Quit handleConnection : player %d\n", client.Id) }() log.Debugf("start handle connection from %s to %s \n", client.Conn.RemoteAddr().String(), client.Conn.LocalAddr().String()) go handleResponse(client) defer client.Conn.Close() for { request := <-client.Request if request.Type == "Exception" { panic(request.Content) } client.Send(request.Channel, request.Content, request.Data) } }
func (h *Service) Auth(req common.CommonRequest, reply *common.CommonReply) (err error) { reply.Type = req.Type reply.PlayerId = 10000 reply.Result = common.ResultSuccess reply.Content = common.ClientResponse{Type: reply.Type, Result: reply.Result} log.Debugf("Auth:req(%+v),reply(%+v)\n", req, *reply) return nil }
// send all requests to connector func (ls *LoginService) requestDispatch(client *net.Client, reqType, request string) { log.Debugf("requestDispatch:reqType(%v),request(%v) for playerId(%d)\n", reqType, request, client.Id) if ls.busStub == nil { panic("BusStub of LoginService doesn't exist!") } var args CommonRequest args.Type = reqType args.Service = "Service" args.Handler = reqType args.PlayerId = client.Id args.Content = request var reply CommonReply rpcCallHandle, err := ls.busStub.GoByMethod("GameService."+reqType, args, &reply) //rpcCallHandle, err := busStub.GoByType("GameCommon", "GameService."+reqType, args, &reply) if err != nil { panic(err.Error()) } if rpcCallHandle == nil { panic("rpcCallHandle nil") } // Todo:reconstruct to an independent goroutine go func(reply *CommonReply) { defer func() { if x := recover(); x != nil { var request net.ClientRequest request.Type = "Exception" request.Content = fmt.Sprint(x) client.Request <- request log.Debug(x, string(debug.Stack())) } }() for { select { case rpcReplyError := <-rpcCallHandle: if rpcReplyError != nil { panic(rpcReplyError.Error()) } client.SendResponse(reply) break case <-time.After(time.Second * RPCCallTimeOut): // Todo:mark rpc call abandoned } } }(&reply) }
func handleResponse(client *Client) { defer func() { if x := recover(); x != nil { if client.Connected { var request ClientRequest request.Type = "Exception" request.Content = fmt.Sprint(x) client.Request <- request } } log.Debugf("Quit handleResponse : player %d\n", client.Id) }() for { channel, body, bytes := client.Receive() var response ClientResponse response.Content = body response.Data = bytes log.Debugf("handleResponse:player(%d),response(%+v)\n", client.Id, response) client.Response[channel] <- response } }
func (client *Client) Send(channel uint32, sendbody string, sendbytes []byte) { client.Mutex.Lock() buf := new(bytes.Buffer) w := gzip.NewWriter(buf) if _, err := w.Write([]byte(sendbody)); err != nil { panic(err.Error()) } if err := w.Close(); err != nil { panic(err.Error()) } body := string(buf.Bytes()) log.Debugf("%d <<< ch:%d sending %d->%d body:\n%s\n", client.Id, channel, len(sendbody), len(body), sendbody) var header HEADER header.Sign = HEADERSIGN header.Channel = channel header.Bodysize = uint32(len(body)) header.ContentSize = uint32(len(sendbody)) header.DataSize = uint32(len(sendbytes)) retHeadBuf := bytes.NewBuffer(nil) binary.Write(retHeadBuf, binary.LittleEndian, &header) client.Conn.SetWriteDeadline(time.Now().Add(10 * time.Second)) n, err := client.Conn.Write(retHeadBuf.Bytes()) if err != nil || n != len(retHeadBuf.Bytes()) { panic(err.Error()) } client.Conn.SetWriteDeadline(time.Now().Add(30 * time.Second)) n, err = client.Conn.Write([]byte(body)) if err != nil || n != len([]byte(body)) { panic(err.Error()) } if header.DataSize > 0 { client.Conn.SetWriteDeadline(time.Now().Add(30 * time.Second)) n, err = client.Conn.Write(sendbytes) if err != nil || n != len(sendbytes) { panic(err.Error()) } } client.Mutex.Unlock() }
func (bs *BaseService) startBusStub() (err error) { if bs.running { return errors.New("Can not start a service twice") } if !bs.config.Valid { return errors.New("Config is not valid") } err = bs.checkIfRequestsAllAvailabe() if err != nil { return } var selfServer bus.ServerConfig selfServer.Type = bs.config.Server.Type selfServer.ServerId = bs.config.Server.Id selfServer.Host = bs.config.Server.Host selfServer.Port = bs.config.Server.Port selfServer.Name = bs.config.Server.Name selfServer.Network = bs.config.Server.Network selfServer.Requests = bs.config.Server.Requests var busServer bus.ServerConfig busServer.Type = bs.config.Connector.Type busServer.ServerId = bs.config.Connector.Id busServer.Host = bs.config.Connector.Host busServer.Port = bs.config.Connector.Port busServer.Name = bs.config.Connector.Name busServer.Network = bs.config.Connector.Network bs.busStub, err = bus.StartBusStub(&selfServer, &busServer) if err != nil { return } log.Debugf("startBusStub:busStub(%+v)\n", *bs.busStub) return }
func (client *Client) Receive() (channel uint32, body string, recvBytes []byte) { var header HEADER packetbuf := make([]byte, 20) if client.ReadDeadline > 0 { //client.Conn.SetReadDeadline(time.Now().Add(3 * HeartBeatRate * time.Second)) client.Conn.SetReadDeadline(time.Now().Add(client.ReadDeadline)) } else { client.Conn.SetReadDeadline(time.Time{}) } n, err := client.Conn.Read(packetbuf) if err != nil { panic(err.Error()) } buf := bytes.NewBuffer(packetbuf[0:n]) binary.Read(buf, binary.LittleEndian, &header) if header.Sign != HEADERSIGN { panic("header sign not match, disconnect") } channel = header.Channel bytesExpected := int(header.Bodysize) bodyBytes := make([]byte, 0) bytesRead := 0 for bytesRead < bytesExpected { bytes := make([]byte, bytesExpected-bytesRead) client.Conn.SetReadDeadline(time.Now().Add(30 * time.Second)) n, err = client.Conn.Read(bytes) if err != nil { panic(err.Error()) } bytesRead += n bodyBytes = append(bodyBytes, bytes[:n]...) } body = string(bodyBytes) { buf := new(bytes.Buffer) if _, e := buf.WriteString(body); e != nil { panic("received body gzip failed") } r, e := gzip.NewReader(buf) if e != nil { panic("received body gzip failed") } b, e := ioutil.ReadAll(r) if e != nil { panic("received body gzip failed") } body = string(b) if e := r.Close(); e != nil { panic("received body gzip failed") } } if header.ContentSize != uint32(len(body)) { panic("received body content size mismatch") } log.Debugf("%d >>> ch:%d receiving %d->%d body:\n%s", client.Id, channel, header.ContentSize, header.Bodysize, body) if header.DataSize > 0 { bytesExpected := int(header.DataSize) recvBytes := make([]byte, 0) bytesRead := 0 for bytesRead < bytesExpected { bytes := make([]byte, bytesExpected-bytesRead) client.Conn.SetReadDeadline(time.Now().Add(30 * time.Second)) n, err = client.Conn.Read(bytes) if err != nil { panic(err.Error()) } bytesRead += n recvBytes = append(recvBytes, bytes[:n]...) } } return }
func (ls *LoginService) handleGateLogic(client *net.Client) { defer func() { if x := recover(); x != nil { var request net.ClientRequest request.Type = "Exception" request.Content = fmt.Sprint(x) client.Request <- request log.Debug(x, string(debug.Stack())) } }() if ls.busStub == nil { panic("BusStub of LoginService doesn't exist!") } if ls.config.Server.NeedAuth { var body net.BODYHEAD response := <-client.Response[net.NetChannelPrimary] err := json.Unmarshal([]byte(response.Content), &body) if err != nil { panic(err.Error()) } // must auth synchronize at first if body.Type != "Login" { panic("the first request must be Login") return } var args CommonRequest args.Type = body.Type args.PlayerId = 0 args.Service = "Service" args.Handler = "Login" args.Content = response.Content var reply CommonReply err = ls.busStub.CallByType("GameAuth", "GameService.Login", args, &reply) if err != nil { panic(err.Error()) return } client.SendResponse(reply.Content) if reply.Result != ResultSuccess { return } client.Id = reply.PlayerId net.Clients[client.Id] = client log.Debugf("handleGateLogic:net.Clients(%+v)\n", net.Clients) } for { select { case response := <-client.Response[net.NetChannelPrimary]: var body net.BODYHEAD json.Unmarshal([]byte(response.Content), &body) switch body.Type { case "Beat": net.HandleBeat(client, response.Content) case "Exception": log.Debugf("Quit handleGateLogic : player %d\n", client.Id) default: ls.requestDispatch(client, body.Type, response.Content) } case <-time.After(time.Second * net.HeartBeatRate * 12): client.CloseConnection() log.Debugf("connection from %s timeout, closing logic thread", client.Conn.RemoteAddr()) return } } }