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 (bs *BaseService) loadConfig(configPath string) error { file, err := os.Open(configPath) if err == nil { defer file.Close() decoder := json.NewDecoder(file) err = decoder.Decode(&bs.config) } else { err = errors.New(fmt.Sprintf("%s Configuration File Not Found", configPath)) } if err != nil { return err } if bs.config.Server.ReadDeadline < 0 { bs.config.Server.ReadDeadline = 0 } else if bs.config.Server.ReadDeadline == 0 { bs.config.Server.ReadDeadline = 3 * bus.HeartBeatRate } bs.config.Valid = true log.Debug("loadConfig : %+v\n", bs.config) return nil }
func (ds *DBService) initDBConn() (err error) { if ds.running { return errors.New("Can not init DB connection while a service is running") } if !ds.config.Valid { return errors.New("Config is not valid") } if !ds.config.DBConfig.DBEnable { return errors.New("DB is not enabled for this service") } connStr := fmt.Sprintf("%s:%s@tcp(%s:%d)/%s", ds.config.DBConfig.DBUser, ds.config.DBConfig.DBPassword, ds.config.DBConfig.DBAddress, ds.config.DBConfig.DBPort, ds.config.DBConfig.DBScheme) ds.db, err = sql.Open("mysql", connStr) if err != nil { panic(err.Error()) } err = ds.db.Ping() if err != nil { panic(err.Error()) } else { log.Debug("database connected") } ds.db.SetMaxIdleConns(ds.config.DBConfig.DBMaxConn / 2) ds.db.SetMaxOpenConns(ds.config.DBConfig.DBMaxConn) return }
// 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 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 main() { defer func() { if x := recover(); x != nil { log.Debug(x, string(debug.Stack())) } }() rand.Seed(time.Now().UnixNano()) err := log.Init("", log.LogAll) if err != nil { panic(err.Error()) } defer log.Close() Quit = make(chan int) service, err := services.CreateService(services.ServiceTypeGate) if err != nil { panic(err.Error()) } if service == nil { panic("services.CreateService returned nil service without error") } err = service.Init(serverConfigPath) if err != nil { panic(err.Error()) } // register customed handlers nHandler := new(notify.NotifyService) err = service.RegisterHandler("NotifyService", nHandler) if err != nil { panic(err.Error()) } // start gate service err = service.Start() if err != nil { panic(err.Error()) } <-Quit }
func main() { defer func() { if x := recover(); x != nil { log.Debug(x, string(debug.Stack())) } }() rand.Seed(time.Now().UnixNano()) err := log.Init("", log.LogAll) if err != nil { panic(err.Error()) } defer log.Close() Quit = make(chan int) service, err := services.CreateService(services.ServiceTypeLogin) if err != nil { panic(err.Error()) } if service == nil { panic("services.CreateService returned nil service without error") } err = service.Init(serverConfigPath) if err != nil { panic(err.Error()) } // start login service err = service.Start() if err != nil { panic(err.Error()) } <-Quit }
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 } } }