//---------------------------------------------------------- Hub processing func HubAgent(incoming chan []byte, conn net.Conn) { config := cfg.Get() if config["profile"] == "true" { helper.SetMemProfileRate(1) defer func() { helper.GC() helper.DumpHeap() helper.PrintGCSummary() }() } hostid := atomic.AddInt32(&_host_genid, 1) // forward buffer forward := make(chan []byte, MAXCHAN) // output buffer output := make(chan []byte, MAXCHAN) protos.AddServer(hostid, forward) log.Printf("game server [id:%v] connected\n", hostid) go _write_routine(output, conn) defer func() { protos.RemoveServer(hostid) core.LogoutServer(hostid) close(forward) close(output) log.Printf("game server [id:%v] disconnected\n", hostid) }() for { select { case msg, ok := <-incoming: // from hub if !ok { return } reader := packet.Reader(msg) protos.HandleRequest(hostid, reader, output) case msg := <-forward: // send forward packet helper.SendChan(0, msg, output) } } }
//---------------------------------------------------------- Event Server start func EventStart() { config := cfg.Get() if config["profile"] == "true" { helper.SetMemProfileRate(1) defer func() { helper.GC() helper.DumpHeap() helper.PrintGCSummary() }() } // start logger if config["event_log"] != "" { cfg.StartLogger(config["event_log"]) } log.Println("Starting Event Server") startup_work() go SignalProc() // Listen service := DEFAULT_SERVICE if config["event_service"] != "" { service = config["event_service"] } log.Println("Event Service:", service) tcpAddr, err := net.ResolveTCPAddr("tcp4", service) checkError(err) listener, err := net.ListenTCP("tcp", tcpAddr) checkError(err) log.Println("Event Server OK.") for { conn, err := listener.AcceptTCP() if err != nil { continue } helper.SetConnParam(conn) go handleClient(conn) } }
func yyParse(yylex yyLexer) int { var yyn int var yylval yySymType var yyVAL yySymType yyS := make([]yySymType, yyMaxDepth) Nerrs := 0 /* number of errors */ Errflag := 0 /* error recovery flag */ yystate := 0 yychar := -1 yyp := -1 goto yystack ret0: return 0 ret1: return 1 yystack: /* put a state and value onto the stack */ if yyDebug >= 4 { __yyfmt__.Printf("char %v in %v\n", yyTokname(yychar), yyStatname(yystate)) } yyp++ if yyp >= len(yyS) { nyys := make([]yySymType, len(yyS)*2) copy(nyys, yyS) yyS = nyys } yyS[yyp] = yyVAL yyS[yyp].yys = yystate yynewstate: yyn = yyPact[yystate] if yyn <= yyFlag { goto yydefault /* simple state */ } if yychar < 0 { yychar = yylex1(yylex, &yylval) } yyn += yychar if yyn < 0 || yyn >= yyLast { goto yydefault } yyn = yyAct[yyn] if yyChk[yyn] == yychar { /* valid shift */ yychar = -1 yyVAL = yylval yystate = yyn if Errflag > 0 { Errflag-- } goto yystack } yydefault: /* default state action */ yyn = yyDef[yystate] if yyn == -2 { if yychar < 0 { yychar = yylex1(yylex, &yylval) } /* look through exception table */ xi := 0 for { if yyExca[xi+0] == -1 && yyExca[xi+1] == yystate { break } xi += 2 } for xi += 2; ; xi += 2 { yyn = yyExca[xi+0] if yyn < 0 || yyn == yychar { break } } yyn = yyExca[xi+1] if yyn < 0 { goto ret0 } } if yyn == 0 { /* error ... attempt to resume parsing */ switch Errflag { case 0: /* brand new error */ yylex.Error("syntax error") Nerrs++ if yyDebug >= 1 { __yyfmt__.Printf("%s", yyStatname(yystate)) __yyfmt__.Printf("saw %s\n", yyTokname(yychar)) } fallthrough case 1, 2: /* incompletely recovered error ... try again */ Errflag = 3 /* find a state where "error" is a legal shift action */ for yyp >= 0 { yyn = yyPact[yyS[yyp].yys] + yyErrCode if yyn >= 0 && yyn < yyLast { yystate = yyAct[yyn] /* simulate a shift of "error" */ if yyChk[yystate] == yyErrCode { goto yystack } } /* the current p has no shift on "error", pop stack */ if yyDebug >= 2 { __yyfmt__.Printf("error recovery pops state %d\n", yyS[yyp].yys) } yyp-- } /* there is no state on the stack with an error shift ... abort */ goto ret1 case 3: /* no shift yet; clobber input char */ if yyDebug >= 2 { __yyfmt__.Printf("error recovery discards %s\n", yyTokname(yychar)) } if yychar == yyEofCode { goto ret1 } yychar = -1 goto yynewstate /* try again in the same state */ } } /* reduction by production yyn */ if yyDebug >= 2 { __yyfmt__.Printf("reduce %v in:\n\t%v\n", yyn, yyStatname(yystate)) } yynt := yyn yypt := yyp _ = yypt // guard against "declared and not used" yyp -= yyR2[yyn] yyVAL = yyS[yyp+1] /* consult goto table to find next state */ yyn = yyR1[yyn] yyg := yyPgo[yyn] yyj := yyg + yyS[yyp].yys + 1 if yyj >= yyLast { yystate = yyAct[yyg] } else { yystate = yyAct[yyj] if yyChk[yystate] != -yyn { yystate = yyAct[yyg] } } // dummy call; replaced with literal code switch yynt { case 3: //line ./src/inspect/inspect.y:30 { prompt(conn) } case 10: //line ./src/inspect/inspect.y:42 { ListAll(conn) prompt(conn) } case 11: //line ./src/inspect/inspect.y:50 { fmt.Fprintln(conn, "\t(p)rint user_id: inspect a user struct") fmt.Fprintln(conn, "\t(p)rint user_id.Field1.Field2...: dotted fields") fmt.Fprintln(conn, "\t(l)ist: list all online users") fmt.Fprintln(conn, "\tgc: force a garbage collection") prompt(conn) } case 12: //line ./src/inspect/inspect.y:61 { conn.Close() } case 13: //line ./src/inspect/inspect.y:68 { Inspect(int32(yyS[yypt-0].n), conn) prompt(conn) } case 14: //line ./src/inspect/inspect.y:74 { InspectField(int32(yyS[yypt-1].n), yyS[yypt-0].nodes, conn) prompt(conn) } case 15: //line ./src/inspect/inspect.y:81 { helper.GC() helper.FprintGCSummary(conn) prompt(conn) } } goto yystack /* stack new state and value */ }
//----------------------------------------------- Start Agent when a client is connected func StartAgent(in chan []byte, conn net.Conn) { defer helper.PrintPanicStack() config := cfg.Get() if config["profile"] == "true" { helper.SetMemProfileRate(1) defer func() { helper.GC() helper.DumpHeap() helper.PrintGCSummary() }() } var sess Session sess.IP = net.ParseIP(conn.RemoteAddr().String()) sess.MQ = make(chan IPCObject, DEFAULT_MQ_SIZE) sess.ConnectTime = time.Now() sess.LastPacketTime = time.Now().Unix() sess.KickOut = false // standard 1-sec timer std_timer := make(chan int32, 1) timer.Add(1, time.Now().Unix()+1, std_timer) // write buffer bufctrl := make(chan bool) buf := NewBuffer(&sess, conn, bufctrl) go buf.Start() // max # of operartions allowed before flushing flush_ops, err := strconv.Atoi(config["flush_ops"]) if err != nil { log.Println("cannot parse flush_ops from config", err) flush_ops = DEFAULT_FLUSH_OPS } // cleanup work defer func() { close_work(&sess) close(bufctrl) }() // the main message loop for { select { case msg, ok := <-in: if !ok { return } if result := UserRequestProxy(&sess, msg); result != nil { err := buf.Send(result) if err != nil { return } } sess.LastPacketTime = time.Now().Unix() case msg, ok := <-sess.MQ: // async if !ok { return } if result := IPCRequestProxy(&sess, &msg); result != nil { err := buf.Send(result) if err != nil { return } } case <-std_timer: timer_work(&sess) if session_timeout(&sess) { return } timer.Add(1, time.Now().Unix()+1, std_timer) } // 持久化逻辑#1: 超过一定的操作数量,刷入数据库 if sess.OpCount > flush_ops { _flush(&sess) } // 是否被逻辑踢出 if sess.KickOut { return } } }